Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

jump tables and C8051F120 memory banks

Help
perrystg
2011-09-06
2013-03-12
  • perrystg
    perrystg
    2011-09-06

    Trying the use the Flash bank control register on a C8051F120 to store data. My plan was to set to bank 2 permanently so that all MOVC instructions reference bank 2 and not bank1 where the code is.

    But switch statements are not working with this scheme.

    Does the implementation for switch statement  jump tables on MCS51 depending on MOVC instruction. If so maybe this is why it doesn't work?

    Any ideas?

     
  • Maarten Brock
    Maarten Brock
    2011-09-06

    A switch statement can be converted to a jumptable if the number of cases is high enough and the cases are close to each other. See also 8.1.7 in the SDCC manual.
    Upto 16 cases JMP @A+DPTR is used with a jumptable of LJMP instructions.
    If there are more than 16 cases in the jumptable MOVC A,@A+PC is used with a table of addresses which should work ok, I guess.
    If there are more than 112 cases MOVC A,@A+DPTR is used which can cause problems indeed.

     
  • perrystg
    perrystg
    2011-09-07

    Many thanks for your help. I studied that a bit, I guess any method that involves a MOVC won't work for me. Is there a way to prevent the compiler from generating these type of jump tables? And then are there other instances where the compiler might use a similar type of MOVC mechanism?

    Reason for all this is my idea was to set the C8051F120's COBANK to 2 permanently so I could put a large amount of data in that extra flash space leaving normal bank1 space free for program code. So far I found that I must arrange for all declared CONST data to be in bank0 (below 0x7FFF so it is accessible regardless of COBANK ) and then the issue with the jump tables. Can you think of anything else I may run into? Do you think this is a sound idea?

    Appreciate your help and thoughts on this.

     
  • Maarten Brock
    Maarten Brock
    2011-09-07

    I hope that the F12x uses the IFBANK setting when doing a MOVC A,@A+PC. After all the bank for the program counter is in IFBANK. And the instruction should read at an offset A from PC. Have you checked this?

    For MOVC A,@A+DPTR it will fail so you must try to stay away from this. It is only used in large jumptables. All other instances are real reads from CONST or XINIT. To create smaller jumptables split your switch statements up to have <=112 cases.

    It should be possible to put all CONST (and XINIT) data in bank 2. Use -Wl-bCONST=0x28000 to place area CONST at physical address 0x8000 in bank 2. You probably have to split the generated hex file (with srecord) and upload seperately because I doubt the SiLabs IDE supports extended intel hex files.

    - What host platform are you using?
    - Can you compile SDCC yourself?
    - How many cases are there in your switch statements?

     
  • perrystg
    perrystg
    2011-09-07

    The switch statement has 22 cases Here is the code generated, snipped from the .asm file

    00128$:
    mov a,r2
    add a,#(00129$-3-.)
    movc a,@a+pc
    push acc
    mov a,r2
    add a,#(00130$-3-.)
    movc a,@a+pc
    push acc
    ret
    00129$:
    .db 00123$
    .db 00123$
    .db 00101$
    .db 00123$

    I stepped it through, it doesn't seem to be using the IFBANK because FF FF is pushed to the stack. Of course if I leave the COBANK at default (bank1) it works fine. Also I rearranged the code so that the switches code is located in lower memory (bank0) and this also works fine. Guess that's a fix for now but I'll have to watch carefully all the switch statements.

    As for other two questions:

    - What host platform are you using?

    Windows

    - Can you compile SDCC yourself?

    I have VS2005 or VS2010, not set up for GCC though

    Many thanks, your help is much appreciated.

     
  • Maarten Brock
    Maarten Brock
    2011-09-07

    Hmm, that is a nasty bug. This totally destroys the use of MOVC A,@A+PC.

    The jumptable is generated in src/mcs51/gen.c lines 11380-11493 in function genJumpTab( )
    http://sdcc.svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/src/mcs51/gen.c?revision=6844&view=markup
    Just in case you would want to modify it.

    As mentioned the current implementation works for you up to 16 cases.

    But the easiest solution for you is probably to use a user peephole file with following contents:

    replace {
        add a,#%1
        movc a,@a+pc
        push acc
        mov a,%2
        add a,#%3
        movc a,@a+pc
        push acc
        ret
    } by {
        add a,#%1
        mov _BANK,#0x11
        movc a,@a+pc
        push acc
        mov a,%2
        add a,#%3
        movc a,@a+pc
        push acc
        mov _BANK,#0x21
        ret
    }
    

    I did not look up the exact name of the sfr nor the exact bit positions.
    You probably want a second rule for the DPTR case too.
    Everything you compile with these peephole rules will have adapted jumptable code. This does not work for linked in libraries though but only gets.c printf_large.c and printfl.c use a switch statement. Maybe you need to recompile these too.

    Hope this helps. And if you find a working solution please upload it in the patch tracker for others to find.
    Maarten

     
  • Maarten Brock
    Maarten Brock
    2011-09-08

    Oops, that first insertion must be before the ADD.

    replace {
        add  a,#%1
        movc a,@a+pc
        push acc
        mov  a,%2
        add  a,#%3
        movc a,@a+pc
        push acc
        ret
    } by {
        mov  _PSBANK,#0x11
        add  a,#%1
        movc a,@a+pc
        push acc
        mov  a,%2
        add  a,#%3
        movc a,@a+pc
        push acc
        mov  _PSBANK,#0x21
        ret
    }
    

    It is difficult to save and restore _PSBANK here because the stack is used here and %2 might be B.

    Here is the code for the DPTR case:

    replace {
        mov  dptr,#%1
        movc a,@a+dptr
        push acc
        mov  a,%2
        mov  dptr,#%3
        movc a,@a+dptr
        push acc
        ret
    } by {
        mov  _PSBANK,#0x11
        mov  dptr,#%1
        movc a,@a+dptr
        push acc
        mov  a,%2
        mov  dptr,#%3
        movc a,@a+dptr
        push acc
        mov  _PSBANK,#0x21
        ret
    }
    
     
  • perrystg
    perrystg
    2011-09-08

    Wow!, "Peephole Optimizer" , wild!

    I'll try that out, tell you how it goes.

    Thanks again.

     
  • perrystg
    perrystg
    2011-09-10

    Totally works!

    I moved the code so the switch code was in high memory, then compiled with your peephole replace script above and works just fine. Stepped it through with debugger just to be sure.

    Again, Many thanks!

     
  • Maarten Brock
    Maarten Brock
    2011-10-13

    I had posted the MOVC flaw in the SiLabs forum and sent SiLabs an email. They have now confirmed it and will issue an errata (or is that erratum?).

     
  • perrystg
    perrystg
    2011-10-17

    That's really cool, they actually admit they have an error. I always wondered how those errata got populated.

    Glad I could be part of it.

    Thanks.