We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I just noticed this recently... whenever I have a xdata DWORD - 32 bits - and I try to set it to a constant value (or any value I think), the assembly that gets generated seems all messed up for such a simple routine. See below. Writing a WORD (TotalSleepTime.m16.ab) works fine, but writing a DWORD (NextSleepTime), makes a call to some external routine which is excessively long and then has a series of NOPs.
77: TotalSleepTime.m16.ab = 0; C:0x3347 900181 MOV DPTR,#TotalSleepTime(0x0181) C:0x334A F0 MOVX @DPTR,A C:0x334B A3 INC DPTR C:0x334C F0 MOVX @DPTR,A 78: TotalSleepTime.m16.cd = 0; 79: C:0x334D 900183 MOV DPTR,#0x0183 C:0x3350 F0 MOVX @DPTR,A C:0x3351 A3 INC DPTR C:0x3352 F0 MOVX @DPTR,A 80: NextSleepTime = 1; C:0x3353 900185 MOV DPTR,#NextSleepTime(0x0185) C:0x3356 120FB2 LCALL C?LSTKXDATA(C:0FB2) C:0x3359 00 NOP C:0x335A 00 NOP C:0x335B 00 NOP C:0x335C 0122 AJMP C:3022
I noticed that something like
variable.m32.abcd = 0
would generate screwed up code like this, so I though it may have to do with the union not being accessed correctly, so I tried changing a variable just to a straight up DWORD (NextSleepTime as seen above), but the same thing happens.
Is this behavior normal? I can't follow the undocumented assembly that is called very well, but it definitely seems excessively complicated for a simple command. I just checked on a blank project with
void main(void) { unsigned long xdata test; test = 0; }
Same thing.
I can understand that if I were using 32-bit variables all over my code, using the library routine would probably save a lot of code SIZE while compromising speed, but this is the ONLY place that I ever assign a 32 variable to an immediate value.
You pretty much answered your own question right there. You presumably asked for size-optimized code, and the tools do what is the most probable to yield the smallest code, in a typical situation. And your counter-example is biased --- 0 is an untypically simple case. Once you generalize that to an arbitrary immediate value to write, code following your pattern would grow from 11 to a whopping 18 bytes, compared to the compiler's 10. Which means the compiler wins as soon as there are about 5 of these operations in the entire program.
The only insight missing is that there's no way for the compiler to guess that this is going to be the single such operation in the whole program, because the compiler doesn't usually see the whole program. Only the linker sees the whole program, but it doesn't get to decide about micro-scale code generation.