I think I had found a bug on Keil V8.12, Does anybody tell me if this bug report will be received by the developers of keil company? and after checked the release note of Keil V9.02, I thought the bug may be not fixed on the latest version (V9.02)
Issue analyze:
[Platform] Device type: Dallas 8032 IDE version: Keil V8.12 Memory Model: Large: variables in XDATA Code Optimization: Level 8 or above
[Condition] //personal guess :)
1. the same code reuse after "C?LSTKPTR" 2. the same code reuse after "C?LSTKXDATA"
[Result]
The constant data encoded as DB statements following the library function call had been lost!
[Analyze] //personal guess :)
The routines "C?LSTKPTR" and "C?LSTKXDATA" should both generate four "DB 0" in this test function, but the compiler not only optimized the code reused segment (test8 = 0;) but also cut the DB statement of first library routines(C?LSTKXDATA)
typedef unsigned char UINT8; typedef unsigned long UINT32; static UINT8 test8 = 1; static UINT32 test32 = 1; static UINT32 *ptest32 = &test32; #pragma OT(8, SPEED) //change to OT(7, SPEED) is OK static UINT8 TestFunc(void) { if (test8) { if (test32) { test32 = 0; //C?LSTKXDATA test8 = 0; //code reused } else { *ptest32 = 0; test8 = 1; } } else { *ptest32 = 0; //C?LSTKPTR test8 = 0; //code reused } printf("test8: %bx\n", test8); return 0; }
11: static UINT8 TestFunc(void) 12: { 13: if (test8) { C:0x0524 90002F MOV DPTR,#0x002F C:0x0527 E0 MOVX A,@DPTR C:0x0528 6029 JZ C:0553 14: if (test32) { C:0x052A 90002B MOV DPTR,#0x002B C:0x052D 120368 LCALL C?LLDXDATA(C:0368) C:0x0530 EC MOV A,R4 C:0x0531 4D ORL A,R5 C:0x0532 4E ORL A,R6 C:0x0533 4F ORL A,R7 C:0x0534 6008 JZ C:053E 15: test32 = 0; C:0x0536 90002B MOV DPTR,#0x002B C:0x0539 120374 LCALL C?LSTKXDATA(C:0374) 16: test8 = 0; 17: } else { C:0x053C 801E SJMP C:055C 18: *ptest32 = 0; C:0x053E 900028 MOV DPTR,#0x0028 C:0x0541 1203BF LCALL C?PLDXDATA(C:03BF) C:0x0544 1203A5 LCALL C?LSTKPTR(C:03A5) C:0x0547 00 NOP C:0x0548 00 NOP C:0x0549 00 NOP C:0x054A 00 NOP 19: test8 = 1; C:0x054B 90002F MOV DPTR,#0x002F C:0x054E 7401 MOV A,#0x01 C:0x0550 F0 MOVX @DPTR,A 20: } 21: } else { C:0x0551 8012 SJMP C:0565 22: *ptest32 = 0; C:0x0553 900028 MOV DPTR,#0x0028 C:0x0556 1203BF LCALL C?PLDXDATA(C:03BF) C:0x0559 1203A5 LCALL C?LSTKPTR(C:03A5) C:0x055C 00 NOP C:0x055D 00 NOP C:0x055E 00 NOP C:0x055F 00 NOP 23: test8 = 0; C:0x0560 E4 CLR A C:0x0561 90002F MOV DPTR,#0x002F C:0x0564 F0 MOVX @DPTR,A 24: } 25: 26: printf("test8: %bx\n", test8); 27: C:0x0565 7BFF MOV R3,#0xFF C:0x0567 7A05 MOV R2,#0x05 C:0x0569 79B2 MOV R1,#0xB2 C:0x056B 90002F MOV DPTR,#0x002F C:0x056E E0 MOVX A,@DPTR C:0x056F 900003 MOV DPTR,#0x0003 C:0x0572 F0 MOVX @DPTR,A C:0x0573 12006E LCALL PRINTF(C:006E) 28: return 0; C:0x0576 7F00 MOV R7,#PRINTF517?BYTE(0x00) 29: }
Should they??
Yes. It's what these run-time helper functions need. They use the (somewhat nasty) approach of passing a 32-bit integer constant to the subroutine by placing it directly in the generated code after the call of the helper function. The return address is then modified accordingly.
I.e. those 4 zeroes are data, not code, so it's really quite wrong to replace them by an SJMP to another copy. As a result, at return from that run-time helper function, not only does "test32" now hold complete garbage ... the program counter is also pointing into the middle of the instruction following that jump!
Oh, and FWIW, tbe current C51 version 9.02 still makes the same mistake.
those 4 zeroes are data, not code >> Yes, we should call them "const variables", right?
the current C51 version 9.02 still makes the same mistake. >> Got it, Thanks for your confirm.
So have either (or both) of you reported this to Keil?
http://www.keil.com/company/contact.asp
I'll trust Mr. Lin to do that.