Menu

#892 mcs51: codeseg/constseg lost high address byte

None
open
None
5
2023-09-05
2023-07-21
Oleg Endo
No

When compiling as banked code/data, when taking a gptr to data in the current codeseg/constseg the high byte is dropped and always fixed at 0x80.

The following example function:

// sdcc -c --fverbose-asm  --std-sdcc2x -mmcs51 --model-large --stack-auto --fomit-frame-pointer --no-peep -Wl-M -Wl-r -Wl-a -Wl-bBANK1=0x014000  bug.c

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

#pragma codeseg BANK1
#pragma constseg BANK1

void print_something (const char*) __banked;

int main (void)
{
  const char* c = "test moon -- please ignore\n";
  print_something (c);
  return 0;
}

compiles to:

_main:
    ar7 = 0x07
    ar6 = 0x06
    ar5 = 0x05
    ar4 = 0x04
    ar3 = 0x03
    ar2 = 0x02
    ar1 = 0x01
    ar0 = 0x00

;   bug.c:15: const char* c = "test moon -- please ignore\n";
;   bug.c:16: print_something (c);
;   genCall
    mov dpl,#___str_0
    mov dph,#(___str_0 >> 8)
    mov b,#0x80   <<<< high byte of pointer to const data is wrong
                    should be #((___str_0 >> 8) + 0x80)

    mov r0,#_print_something
    mov r1,#(_print_something >> 8)
    mov r2,#(_print_something >> 16)     <<<< high byte of function call address is correct

    lcall   __sdcc_banked_call
;   bug.c:17: return 0;
;   genRet
    mov dpl,#0x00
    mov dph,#0x00
00101$:
;   bug.c:18: }
    ret
    .area BANK1   (CODE)
    .area BANK1   (CODE)
    .area BANK1   (CODE)
___str_0:
    .ascii "test moon -- please ignore"
    .db 0x0a
    .db 0x00
    .area BANK1   (CODE)
    .area XINIT   (CODE)
    .area CABS    (ABS,CODE)

Discussion

  • Oleg Endo

    Oleg Endo - 2023-07-21

    Another case:

    extern const char* bleh_ptr;
    
    void bleh (void)
    {
      bleh_ptr = "bleh\n";
    }
    

    compiles to:

    _bleh:
        ar7 = 0x07
        ar6 = 0x06
        ar5 = 0x05
        ar4 = 0x04
        ar3 = 0x03
        ar2 = 0x02
        ar1 = 0x01
        ar0 = 0x00
    ;   bug.c:40: bleh_ptr = "bleh\n";
    ;   genCast
        mov dptr,#_bleh_ptr
        mov a,#___str_0
        movx    @dptr,a
        mov a,#(___str_0 >> 8)
        inc dptr
        movx    @dptr,a
        mov a,#0x80      <<<< wrong high byte
        inc dptr
        movx    @dptr,a
    00101$:
    ;   bug.c:41: }
        ret
        .area BANK1   (CODE)
        .area BANK1   (CODE)
        .area BANK1   (CODE)
    ___str_0:
        .ascii "bleh"
        .db 0x0a
        .db 0x00
        .area BANK1   (CODE)
        .area XINIT   (CODE)
        .area CABS    (ABS,CODE)
    
     
  • Oleg Endo

    Oleg Endo - 2023-07-23

    It seems there is no way to edit the original description. There is a mistake:

    ;   bug.c:15: const char* c = "test moon -- please ignore\n";
    ;   bug.c:16: print_something (c);
    ;   genCall
        mov dpl,#___str_0
        mov dph,#(___str_0 >> 8)
        mov b,#0x80   <<<< high byte of pointer to const data is wrong
                        should be #((___str_0 >> 8) + 0x80)
    

    should be

    ;   bug.c:15: const char* c = "test moon -- please ignore\n";
    ;   bug.c:16: print_something (c);
    ;   genCall
        mov dpl,#___str_0
        mov dph,#(___str_0 >> 8)
        mov b,#0x80   <<<< high byte of pointer to const data is wrong
                        should be #((___str_0 >> 16) + 0x80)
    
     
  • Maarten Brock

    Maarten Brock - 2023-07-27
    • status: open --> closed-rejected
    • assigned_to: Maarten Brock
     
  • Maarten Brock

    Maarten Brock - 2023-07-27

    In the large memory model the memory is assumed to be <=64kB. Especially the const and xdata is supposed to be in that range. Functions can be marked as banked and so can function pointers. But if you want your variables to live in banked memory as well you must use the huge memory model.

     

    Last edit: Maarten Brock 2023-09-05
  • Oleg Endo

    Oleg Endo - 2023-07-27

    When compiling the example as huge-model it yields s the same result. It doesn't pass the correct __code pointer to the print function. The top byte is always stuck at 0x80.

    Also as per SDCC manual:

    The huge model compiles all functions as banked4.1.3 and is otherwise equal to large for now. All other models compile the functions without bankswitching by default.

    Please consider to re-open this issue.

     

    Last edit: Maarten Brock 2023-09-05
  • Oleg Endo

    Oleg Endo - 2023-09-02

    In the large memory model the memory is assumed to be <=64kB. Especially the const and xdata is supposed to be in that range. Functions can be marked as banked and so can function pointers. But if you want your variables to live in banked memory as well you must use the huge memory model.

    @maartenbrock is there a working example somewhere that demonstrates how to use that?

    From what I have tried and see, there is no way to get the correct full 23-bit pointer to a const data. Please reconsider to re-open this issue.

     
    • Maarten Brock

      Maarten Brock - 2023-09-05

      I'm sorry. I was mistaken. Although the top byte values and gptrget are somewhat prepared for this, it was never implemented. The manual is correct in stating that huge is the same as large with all functions marked __banked.

      This would therefore only qualify as a feature request.

       
  • Maarten Brock

    Maarten Brock - 2023-09-05

    Ticket moved from /p/sdcc/bugs/3622/

    Can't be converted:

    • _category: MCS51
     
  • Maarten Brock

    Maarten Brock - 2023-09-05
    • status: closed-rejected --> open
    • Group: -->
     
  • Oleg Endo

    Oleg Endo - 2023-09-05

    Thanks.

    What I've been doing in my software for some parts which can access the external 24 MByte address space directly:

    #pragma codeseg BANK3    // works
    #pragma constseg BANK3   // is effectively ignored
    
    #define constseg_ptr(x) ((const void*)((const char*)0 + ((uintptr_t)x | (BANK3 & 0xFF0000UL))))
    

    ... and then use that macro to make a user-defined 24-bit pointer with the correct high byte. This is for e.g. transferring data included in the C source file by DMA or other flash reading routines, not directly by CPU code.

    However, compiling this type of code with the latest SDCC SVN trunk version bails out in SDCCgenconstprop.cc because it hits the high byte with "unknown" / "unexpected" value.

    I've applied the attached patch temporarily to my local tree.

     

    Last edit: Oleg Endo 2023-09-05
  • Maarten Brock

    Maarten Brock - 2023-09-05

    I suggest to change the check on gpbyte to look at the selecting bits only. Or maybe only comparing the top nibble is already better. Also, a warning is better suited here than an error IMHO.

     
  • Oleg Endo

    Oleg Endo - 2023-09-05

    I think the cprop code in that spot is already trying to do something with known bits or such. But I didn't understand it at first glance. Perhaps @spth knows this part best.

     

Log in to post a comment.