December 23, 2007 - 5:03pm
Guest |
When building simple C functions for the small memory memory model or for idata memory space, RC51 often reserves space in data or idata when it could use just registers. It doesn't always do this but, here's an example where it does.
void fromROMtoRAM( unsigned char const code *src, unsigned char *dest, unsigned char cnt )
{
for( ; cnt; cnt--, src++, dest++ ) *dest = *src;
}
With the large memory model this gives:
; FUNCTION _CopyConstBytesU8 (BEGIN)
; Register R6R7 is assigned to parameter src
; Register R4R5 is assigned to parameter dest
; SOURCE LINE # 8
0000 900000 R MOV DPTR,#cnt
0003 EB MOV A,R3
0004 F0 MOVX @DPTR,A
0005 ?FOR1:
; SOURCE LINE # 9
0005 900000 R MOV DPTR,#cnt
0008 E0 MOVX A,@DPTR
0009 601D JZ ?NXT2
000B 8E83 MOV DPH,R6
000D 8F82 MOV DPL,R7
000F E4 CLR A
0010 93 MOVC A,@A+DPTR
0011 8C83 MOV DPH,R4
0013 8D82 MOV DPL,R5
0015 F0 MOVX @DPTR,A
0016 900000 R MOV DPTR,#cnt
0019 E0 MOVX A,@DPTR
001A 14 DEC A
001B F0 MOVX @DPTR,A
001C 0F INC R7
001D EF MOV A,R7
001E 7001 JNZ ?LAB3
0020 0E INC R6
0021 ?LAB3:
0021 0D INC R5
0022 ED MOV A,R5
0023 70E0 JNZ ?FOR1
0025 0C INC R4
0026 80DD SJMP ?FOR1
0028 ?NXT2:
0028 22 RET
'src' and 'dest' are in registers (good); 'cnt' was placed in xdata (bad). But overall OK. How build this for the small model. This gives:
; FUNCTION _CopyConstBytesU8 (BEGIN)
; SOURCE LINE # 8
0000 8E00 R MOV src,R6
0002 8F00 R MOV src+01H,R7
0004 8D00 R MOV dest,R5
0006 8B00 R MOV cnt,R3
0008 ?FOR2:
; SOURCE LINE # 9
0008 E500 R MOV A,cnt
000A 6019 JZ ?NXT4
000C 850083 R MOV DPH,src
000F 850082 R MOV DPL,src+01H
0012 A800 R MOV R0,dest
0014 E4 CLR A
0015 93 MOVC A,@A+DPTR
0016 F6 MOV @R0,A
0017 1500 R DEC cnt
0019 0500 R INC src+01H
001B E500 R MOV A,src+01H
001D 7002 JNZ ?LAB4
001F 0500 R INC src
0021 ?LAB4:
0021 0500 R INC dest
0023 80E3 SJMP ?FOR2
0025 ?NXT4:
0025 22 RET
RC51 has reserved 'data' for 'src', 'dest' and 'cnt', even though only 4 registers are need for the function. This is very bad, as 'data' space is limited. Similarly, if 'dest' is in idata:
void fromROMtoRAM( unsigned char const code *src, unsigned char idata *dest, unsigned char cnt )
{
for( ; cnt; cnt--, src++, dest++ ) *dest = *src;
}
Then we get:
; FUNCTION _CopyConstBytesU8 (BEGIN)
; SOURCE LINE # 8
0000 900000 R MOV DPTR,#src
0003 EE MOV A,R6
0004 F0 MOVX @DPTR,A
0005 A3 INC DPTR
0006 EF MOV A,R7
0007 F0 MOVX @DPTR,A
0008 A3 INC DPTR
0009 ED MOV A,R5
000A F0 MOVX @DPTR,A
000B A3 INC DPTR
000C EB MOV A,R3
000D F0 MOVX @DPTR,A
000E ?FOR2:
; SOURCE LINE # 9
000E 900000 R MOV DPTR,#cnt
0011 E0 MOVX A,@DPTR
0012 602B JZ ?NXT4
0014 900000 R MOV DPTR,#src
0017 120000 R LCALL ?C_DPTR2DPTR
001A E4 CLR A
001B 93 MOVC A,@A+DPTR
001C FA MOV R2,A
001D 900000 R MOV DPTR,#dest
0020 E0 MOVX A,@DPTR
0021 F8 MOV R0,A
0022 A602 MOV @R0,AR2
0024 A3 INC DPTR
0025 E0 MOVX A,@DPTR
0026 14 DEC A
0027 F0 MOVX @DPTR,A
0028 900000 R MOV DPTR,#src
002B A3 INC DPTR
002C E0 MOVX A,@DPTR
002D 04 INC A
002E F0 MOVX @DPTR,A
002F 900000 R MOV DPTR,#src
0032 7003 JNZ ?LAB4
0034 E0 MOVX A,@DPTR
0035 04 INC A
0036 F0 MOVX @DPTR,A
0037 ?LAB4:
0037 900000 R MOV DPTR,#dest
003A E0 MOVX A,@DPTR
003B 04 INC A
003C F0 MOVX @DPTR,A
003D 80CF SJMP ?FOR2
003F ?NXT4:
003F 22 RET
Again RC51 has unecessarily reserved RAM for all 3 function parameters, this time all in idata. Even if all parameters had to be in RAM, it would be more compact to place the remainder in data.
The irony is that RC51 has optimised RAM usage best on the largest memory model, where this matters least. There's not much 'data' and 'idata' RAM, so failure to optimise even a few functions correctly is a big penalty. Overlaying will mitigate this, but only partly. Anyway, I hope you can improve small model optimisation. This is my first project on an 8051 derivative without xdata memory, and I'm discovering that it really matters.
regards Steven Pruzina
|
Happy New Year!
We plan to introduce some new optimizations in Q1. We will look at this code. Thanks.
Note that the compiler generates a better code for:
unsigned char i;
for( i = 0 ; i < cnt; i++ ) *dest++ = *src++;
but, anyway, I agree that it could be better.