Issue
I am novice embedded developer. I am developing for SH7058 CPU. I have the following code (it's simplified, but the point remains):
EDIT
I made a typo. The right code is
#define FLAG (0x40)
#define ADDRESS (0xFFFFB000u)
#define P ((volatile unsigned char *)ADDRESS)
unsigned char some_func(){
return *P & FLAG;
}
And corresponding assembly output is
some_func():
mov.w .L3,r1
mov.b @r1,r0
rts
and #64,r0
.L3:
.short -20480
And unsigned long 0xFFFFB000
turns to signed short -20480
. Older versions of GCC give similar results.
Is there a way to tell GCC not to convert unsigned to signed? Convertion of #define
to variable is not suitable.
Solution
You should not worry too much about how the compiler generates code or how the code is presented in the disassembly. It will produce the same result.
The interesting thing here is not the signed/unsigned thing but rather that it shortened the literal. For the short to load into a 32-bit register, and set the upper 16 bits to 0xFFFF, the short must be considered as signed.
It is the compiler being rather clever, the short integer 0xB000 when interpreted as a signed value and loaded into a 32-bit register becomes 0xFFFFB000 as required, but if it were unsigned 0xB000u, it would become 0x0000B000.
What the compiler has done is to use a "trick" to allow a trivial code-size optimisation. If you were to change the address to say 0xFFFF3000, the full 32 bits would be stored because the "sign-extension" trick would not result in 0xFFFF in the upper 16 bits:
Changing to:
#define ADDRESS (0xFFFF3000u)
results in:
some_func():
mov.l .L4,r1
mov.b @r1,r0
rts
and #64,r0
.L4:
.long -53248
Note the literal is now long
. It is still presented as signed because at the assembler level, there really is no difference, it is the same bit pattern, and the same code regardless of the presentation in the disassembly. Signedness is a matter of interpretation (how the bit pattern is used) and presentation (how it is displayed), it makes no difference at the machine-level.
For example, let's say we had a hypothetical 4 bit machine, where 0xF would represent either -1 (two's complement) or 15 depending on whether it was signed or unsigned. Then lets say we have two operations one signed
-1 - 1 = -2
and another
15 - 1 = 14
both expressions are the same machine operation
0xF - 0x1 = 0xE
So the presentation in the disassembly as signed is an irrelevance, it is the same code regardless.
Answered By - Clifford Answer Checked By - Gilberto Lyons (WPSolving Admin)