Hi, suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one register, r0 = 0x00110022. Now I only want to invert the sign of the top halfword so that r0 = 0xFFEF0022. Is there an way to do this? I guess I can do something like ------------------ qadd16 r1, r0, r0 @r0 *= 2 movt r1, #0 qsub16 r0, r1, r0 ------------------ but this looks stupid. Thanks syl
arm9e: how do I invert sign of a halfword?
Started by ●July 25, 2008
Reply by ●July 25, 20082008-07-25
SYL wrote:> Hi, > > suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one > register, r0 = 0x00110022. Now I only want to invert the sign of the > top halfword so that r0 = 0xFFEF0022. > > Is there an way to do this? > > I guess I can do something like > ------------------ > qadd16 r1, r0, r0 @r0 *= 2 > movt r1, #0 > qsub16 r0, r1, r0 > ------------------ > but this looks stupid.u32 foo = 0x00110022; u32 bar = (foo ^ 0xFFFF0000) + 0x0001000; Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
Reply by ●July 25, 20082008-07-25
Vladimir Vassilevsky wrote:> SYL wrote: > >> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed >> in one register, r0 = 0x00110022. Now I only want to invert the >> sign of the top halfword so that r0 = 0xFFEF0022. >> >> Is there an way to do this? >> >> I guess I can do something like >> ------------------ >> qadd16 r1, r0, r0 @r0 *= 2 >> movt r1, #0 >> qsub16 r0, r1, r0 >> ------------------ >> but this looks stupid. > > u32 foo = 0x00110022; > u32 bar = (foo ^ 0xFFFF0000) + 0x0001000;Well, if you change 0x0001000 to 0x00010000, and assume you want 2's complement, and assume that the systems doesn't detect arithmetic overflows, and that it does wrapping in 2's complement for such overflows, then it will maybe work. Meanwhile I suggest you at least annotate your code to describe the non-standard performance you require. Oh yes - somebody decide if you are packing 8 bits into 16, or 16 bits into 32. It will make a difference. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
Reply by ●July 25, 20082008-07-25
SYL wrote:> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one > register, r0 = 0x00110022. Now I only want to invert the sign of the > top halfword so that r0 = 0xFFEF0022. > > Is there an way to do this? > > I guess I can do something like > ------------------ > qadd16 r1, r0, r0 @r0 *= 2 > movt r1, #0 > qsub16 r0, r1, r0 > ------------------Are you sure that you can use qadd16 and qsub16? These are ARMv6 instructions, but I think the arm9e supports ARMv5, only. And even if you can use it, I don't think that your code works. This code should work: mvn r1, #0 eors r0, r0, r1, lsl #16 add r0, #0x10000 -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de
Reply by ●July 26, 20082008-07-26
"CBFalconer" <cbfalconer@yahoo.com> wrote in message news:488A7724.D0B4D42F@yahoo.com...> Vladimir Vassilevsky wrote: >> SYL wrote: >> >>> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed >>> in one register, r0 = 0x00110022. Now I only want to invert the >>> sign of the top halfword so that r0 = 0xFFEF0022. >>> >>> Is there an way to do this? >>> >>> I guess I can do something like >>> ------------------ >>> qadd16 r1, r0, r0 @r0 *= 2 >>> movt r1, #0 >>> qsub16 r0, r1, r0 >>> ------------------ >>> but this looks stupid. >> >> u32 foo = 0x00110022; >> u32 bar = (foo ^ 0xFFFF0000) + 0x0001000; > > Well, if you change 0x0001000 to 0x00010000, and assume you want > 2's complement, and assume that the systems doesn't detect > arithmetic overflows, and that it does wrapping in 2's complement > for such overflows, then it will maybe work.Name me an ARM that is ones-complement or implements signed overflow, or for that matter any CPU in existence. Note Vlad's code uses unsigned anyway... A simpler method uses -x = (x - x * 2) to get it in 2 instructions: bar = foo - (((int32)foo >> 16) << 17); ASR r1,r0,#16 SUB r0,r0,r1,LSL #17 Wilco
Reply by ●July 26, 20082008-07-26
"Wilco Dijkstra" <Wilco.removethisDijkstra@ntlworld.com> writes:> "CBFalconer" <cbfalconer@yahoo.com> wrote > > Vladimir Vassilevsky wrote: > >> SYL wrote: > >> > >>> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed > >>> in one register, r0 = 0x00110022. Now I only want to invert the > >>> sign of the top halfword so that r0 = 0xFFEF0022. > >>> > >>> Is there an way to do this? > >>> > >>> I guess I can do something like > >>> ------------------ > >>> qadd16 r1, r0, r0 @r0 *= 2 > >>> movt r1, #0 > >>> qsub16 r0, r1, r0 > >>> ------------------ > >>> but this looks stupid. > >> > >> u32 foo = 0x00110022; > >> u32 bar = (foo ^ 0xFFFF0000) + 0x0001000; > > > > Well, if you change 0x0001000 to 0x00010000, and assume you want > > 2's complement, and assume that the systems doesn't detect > > arithmetic overflows, and that it does wrapping in 2's complement > > for such overflows, then it will maybe work. > > Name me an ARM that is ones-complement or implements signed overflow, > or for that matter any CPU in existence.The old CDC and Univac mainframes were ones-complement. I don't know of any micro that uses ones-complement. There's no end-around carry/borrow in twos-complement.> Note Vlad's code uses unsigned anyway... > > A simpler method uses -x = (x - x * 2) to get it in 2 instructions: > > bar = foo - (((int32)foo >> 16) << 17); > > ASR r1,r0,#16 > SUB r0,r0,r1,LSL #17VV's (corrected) solution works in all cases. Wilco's is suspect for large values (>0x40000000), but I haven't investigated the boundary cases. BTW: SYL's problem description is misleading in that the illustration is taking the twos-complement of the upper halfword of the register, not "inverting the sign".
Reply by ●July 26, 20082008-07-26
Everett M. Greene wrote:> VV's (corrected) solution works in all cases. Wilco's > is suspect for large values (>0x40000000), but I haven't > investigated the boundary cases.It works for values > 0x3fff, because it doesn't matter that the LSL #17 shift operation shifts the highest bit out of the 32 bit register, because subtracting 0x10000 from any 16 bit word results still in the same 16 bit word, only the upper (not present) bits are switched all to 1. Nice solution! -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de
Reply by ●July 26, 20082008-07-26
Vladimir Vassilevsky <antispam_bogus@hotmail.com> writes:> SYL wrote: > >> Hi, >> >> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one >> register, r0 = 0x00110022. Now I only want to invert the sign of the >> top halfword so that r0 = 0xFFEF0022. >> >> Is there an way to do this? >> >> I guess I can do something like >> ------------------ >> qadd16 r1, r0, r0 @r0 *= 2 >> movt r1, #0 >> qsub16 r0, r1, r0 >> ------------------ >> but this looks stupid. > > u32 foo = 0x00110022; > u32 bar = (foo ^ 0xFFFF0000) + 0x0001000;This is correct if 0x0001000 is changed to 0x00010000. You can also invert the order of operations: u32 foo = 0x00110022; u32 bar = (foo + 0x00010000) ^ 0xFFFF0000; Scott -- Scott Hemphill hemphill@alumni.caltech.edu "This isn't flying. This is falling, with style." -- Buzz Lightyear
Reply by ●July 26, 20082008-07-26
"Scott Hemphill" <hemphill@hemphills.net> wrote in message news:m3hcaceceq.fsf@hemphills.net...> Vladimir Vassilevsky <antispam_bogus@hotmail.com> writes: > >> SYL wrote: >> >>> Hi, >>> >>> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one >>> register, r0 = 0x00110022. Now I only want to invert the sign of the >>> top halfword so that r0 = 0xFFEF0022. >>> >>> Is there an way to do this? >>> >>> I guess I can do something like >>> ------------------ >>> qadd16 r1, r0, r0 @r0 *= 2 >>> movt r1, #0 >>> qsub16 r0, r1, r0 >>> ------------------ >>> but this looks stupid. >> >> u32 foo = 0x00110022; >> u32 bar = (foo ^ 0xFFFF0000) + 0x0001000; > > This is correct if 0x0001000 is changed to 0x00010000. You can also > invert the order of operations: > > u32 foo = 0x00110022; > u32 bar = (foo + 0x00010000) ^ 0xFFFF0000;That should be: u32 bar = (foo - 0x00010000) ^ 0xFFFF0000; Wilco
Reply by ●July 26, 20082008-07-26
"Wilco Dijkstra" <Wilco.removethisDijkstra@ntlworld.com> writes:> "Scott Hemphill" <hemphill@hemphills.net> wrote in message news:m3hcaceceq.fsf@hemphills.net... >> Vladimir Vassilevsky <antispam_bogus@hotmail.com> writes: >> >>> SYL wrote: >>> >>>> Hi, >>>> >>>> suppose I have two 16bit coefficients (c1=0x11, c2=0x22) packed in one >>>> register, r0 = 0x00110022. Now I only want to invert the sign of the >>>> top halfword so that r0 = 0xFFEF0022. >>>> >>>> Is there an way to do this? >>>> >>>> I guess I can do something like >>>> ------------------ >>>> qadd16 r1, r0, r0 @r0 *= 2 >>>> movt r1, #0 >>>> qsub16 r0, r1, r0 >>>> ------------------ >>>> but this looks stupid. >>> >>> u32 foo = 0x00110022; >>> u32 bar = (foo ^ 0xFFFF0000) + 0x0001000; >> >> This is correct if 0x0001000 is changed to 0x00010000. You can also >> invert the order of operations: >> >> u32 foo = 0x00110022; >> u32 bar = (foo + 0x00010000) ^ 0xFFFF0000; > > That should be: > > u32 bar = (foo - 0x00010000) ^ 0xFFFF0000;Right, thanks! Scott -- Scott Hemphill hemphill@alumni.caltech.edu "This isn't flying. This is falling, with style." -- Buzz Lightyear






