gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > Sign-extend instruction?

#54855 - paladine - Fri Sep 23, 2005 4:19 am

I have found a THUMB reference that indicates SXTB can be used to sign extend a byte into a word. This is perfect since I want to take a signed byte and convert to an integer. GCC doesn't like it. Is this supported on the GBA's processor?

#54856 - tepples - Fri Sep 23, 2005 4:24 am

SXTB might be a macroinstruction for a left shift followed by a right shift. I seem to remember that MIPS assemblers support lots of macros out of the box; ARM's own tools might do the same.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#54857 - paladine - Fri Sep 23, 2005 4:29 am

My mind is currently blank as I'm about to go to sleep. How could I accomplish this same task using shifts? The pseudocode works as expected but I'd like to avoid the branch condition if possible. I'm sure it can be done using standard shifting/or'ing.

Code:

inline static i32 SpriteGetY(LPSPRITE pSprite)
{
  if (pSprite->attrib[0] & 0x80)
    return (0xFFFFFF00 | pSprite->attrib[0]);

  return (pSprite->attrib[0] & 0xFF);
}



I'd like to extend bit 8 through bits 9-32 to form the integer.

#54858 - tepples - Fri Sep 23, 2005 4:41 am

To sign-extend an 8-bit value, in C (assuming 32-bit ints):
Code:
static inline signed int extend_s8_s32(signed int x)
{
  return (x << 24) >> 24;
}

Or in asm:
Code:
  lsl r0, r0, 24
  asr r0, r0, 24


If you want to extend a 9-bit value (copy bits 8 onto bits 9 through 31), it's similar. In C:
Code:
static inline signed int extend_s8_s32(signed int x)
{
  return (x << 23) >> 23;
}

Or in asm:
Code:
  lsl r0, r0, 23
  asr r0, r0, 23


Besides...
Don't sprite y values on the GBA or Nintendo DS go from -64 to 191? This kind of wrapping can be done with the following expression:
Code:
y_component = ((attribute_0 + 64) & 0xff) - 64;

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#54860 - paladine - Fri Sep 23, 2005 4:51 am

I guess the 'magic' occurs in the right shift. I'm more of a software guy so it didn't occur to me that when the right shift occurs it uses the MSB to fill in the data. Thanks!

#54883 - Cearn - Fri Sep 23, 2005 8:20 am

With the arithmetic right-shift (asr) the magic happens. With the logical right-shift (lsr), it's always zero-extension. They're basically the signed and unsigned right shifts. Don't confuse the two, or there will be trouble.

#54886 - FluBBa - Fri Sep 23, 2005 8:29 am

I'm not sure about Thumb but in Arm you have ldrsb & ldrsh to signextend the value on register load, though it is quite restrictive in it's addressing modes.
_________________
I probably suck, my not is a programmer.

#54913 - paladine - Fri Sep 23, 2005 3:58 pm

Thanks Cearn, you are correct. I looked at the generated assembly from GCC and noticed that the C code (x << 24) >> 24 generated a lsl followed by an asr. GCC is smart enough to use asr,lsr based on the sign of the argument. In my case I was using a signed integer so it worked as expected.