arm9e: how do I invert sign of a halfword?

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

Reply to
SYL
Loading thread data ...

u32 foo = 0x00110022; u32 bar = (foo ^ 0xFFFF0000) + 0x0001000;

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

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]: 
 Click to see the full signature
Reply to
CBFalconer

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 to
Frank Buss

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)

Reply to
Wilco Dijkstra

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.

VV'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 to
Everett M. Greene

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 to
Frank Buss

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 to
Scott Hemphill

That should be:

u32 bar = (foo - 0x00010000) ^ 0xFFFF0000;

Wilco

Reply to
Wilco Dijkstra

Right, thanks!

Scott

--
Scott Hemphill	hemphill@alumni.caltech.edu
"This isn't flying.  This is falling, with style."  -- Buzz Lightyear
Reply to
Scott Hemphill

The point I was raising was that shifting a value between

0x4000 and 0x7FFF left one place results in a significant bit being shifted into the sign bit. There was a question in my mind as to whether that would work correctly.

I have since run a simulation of the process and find it works in all cases except the one value of 0x8000. Of course, no solution works in this case...

Reply to
Everett M. Greene

It uses basic maths: x - x = 0, and 0 - x = -x, so -x = 0 - x = (x - x) - x = x - (2*x).

Negating the smallest negative number results in itself in two complement's arithmetic, just like negating zero gives zero. Both solutions have the same behaviour as a negate instruction.

Wilco

Reply to
Wilco Dijkstra

Nobody is saying that the equation is not mathematically correct, but as we all know, some arithmetic operations can have problems when being computed with limited range operations.

Reply to
Everett M. Greene

... snip ...

Why don't you read the standard once in a while?

6.5.7 Bitwise shift operators

Syntax

[#1] shift-expr: additive-expr shift-expr > additive-expr

Constraints

[#2] Each of the operands shall have integer type.

Semantics

[#3] The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined. [#4] The result of E1 > E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity, 2 raised to the power E2. If E1 has a signed type and a negative value, the resulting value is implementation- defined.
--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
 Click to see the full signature
Reply to
CBFalconer

FYI The standard is actually incorrect here in making all negative left shifts undefined. Positive leftshifts that overflow are undefined too. However multiplies of positive and negative numbers are defined if no overflow occurs, and only implementation defined if they overflow...

But in what way does this help? The answer the standard gives in most cases is either undefined or implementation defined behaviour. Given there are lots of similar errors in the standard, nobody cares which one it is (except for language lawyers).

Wilco

Reply to
Wilco Dijkstra

... snip ...

There is no known error in the portion I quoted (and you snipped). If you don't pay attention, you will sooner or later have to pay.

--
 [mail]: Chuck F (cbfalconer at maineline dot net) 
 [page]: 
 Click to see the full signature
Reply to
CBFalconer

How is that incorrect? I can believe that it's different than what you want, but that doesn't make it incorrect.

Reply to
Eric Smith

It's incorrect because there is nothing special about left shift. The result is perfectly well defined just like multiply. Note compilers change multiplies by powers of 2 into shifts and can change shifts into multiplies. This is fine as they are identical operations.

Given there is no obvious explanation (the rationale doesn't say anything either), and the difference between implementation defined (it's defined to work correctly) and undefined (it may crash your computer, possibly losing your data), they surely must have meant implementation defined.

Actually if I were to fix the standard and make it really useful, I'd explicitly define most undefined/implementation defined loopholes. Crashing an application and claiming it's OK to crash because the standard accidentally allows it is not acceptable.

Wilco

Reply to
Wilco Dijkstra

If you don't think it's an error, maybe you can explain why it is correct?

Wilco

Reply to
Wilco Dijkstra

[snip]

Which one? The discussion was about ARM and it doesn't have a true standard.

Reply to
Everett M. Greene

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.