Menu

#4060 the __banked __nonbanked functions

open
nobody
None
GBZ80
5
2026-09-01
2026-08-17
Tony Pavlov
No

the recent versions of SDCC report this warning and looks like it cancel the __banked calling convention:

../../src/core/vm.c:95: warning 134: Both banked and nonbanked attributes used. nonbanked wins.

i kindly ask you not do so, because __banked and __nonbanked are different attributes, and declaring both for the function make sense. while __banked defines the calling CONVENTION, __nonbanked is a STORAGE attribute. "the whale and the elephant fought and whale won": why they fought, they even could have never face in battle!

the practical usage:

in GBStudio there is a virtual machine that need to call the functions which are defined in the differenmt banks "in the unified way", but some of those functions, which manipulate the banks, must be located in the nonbanked area. that's why putting both attributes make sense!

of course there are workarounds which either difficult (assembly-only implementation), or very slow (wrappers), or ugly (dummy argumets which are different for the different targets) but i don't see why not to revert to the old behavior.

this works, but very ugly:

#if defined(NINTENDO)
#define VM_CALL OLDCALL BANKED
#define STEP_FUNC_ATTR
typedef UWORD DUMMY0_t;
typedef UWORD DUMMY1_t;
#define VM_CALL_NONBANKED OLDCALL NONBANKED
#elif defined(SEGA)
#define VM_CALL OLDCALL BANKED
#define STEP_FUNC_ATTR Z88DK_FASTCALL
typedef UBYTE DUMMY0_t;
typedef UWORD DUMMY1_t;
#define VM_CALL_NONBANKED OLDCALL NONBANKED
#endif

...
void vm_beginthread(DUMMY0_t dummy0, DUMMY1_t dummy1, SCRIPT_CTX * THIS, UBYTE bank, UBYTE * pc, INT16 idx, UBYTE nargs) VM_CALL_NONBANKED;
...

so i suggest either revert to the old behavior or introduce the separate storage attribute for the functions across all the targets.

Discussion

  • Maarten Brock

    Maarten Brock - 2026-08-31

    When I introduced __banked and __nonbanked (for the mcs51) the idea was that you could selectively place functions in a switchable bank when not using model huge, or in the common area in spite of a selected huge memory model. Both define a calling convention and both select a default storage area. The warning exists just as long.

     
    • Tony Pavlov

      Tony Pavlov - 2026-09-01

      luckily, it is not working like that on z80 targets. anyway, there is sense in introducing the storage attributes for the constants, like:

      const int data __nonbanked = 42;
      

      or introduce the __attribute__() keyword, similar to gcc and clang.

      also there is sense to remove the obscure behavior, when in the banked C codethere is the __nonbanked function, the constant array just before that function also goes to the nonbanked space - that's frustrating.

      #pragma bank 2
      #include <stdint.h>
      const uint8_t my_array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
      void test_func(void) __nonbanked {
          return;
      }
      

      result in:

          .area _HOME
      ;src/some.c:7: void test_func(void) __nonbanked {
      ;   ---------------------------------
      ; Function test_func
      ; ---------------------------------
      _test_func::
      ;src/some.c:8: return;
      ;src/some.c:9: }
          ret
      _my_array:
          .db #0x00   ; 0
          .db #0x01   ; 1
          .db #0x02   ; 2
          .db #0x03   ; 3
          .db #0x04   ; 4
          .db #0x05   ; 5
          .db #0x06   ; 6
          .db #0x07   ; 7
          .db #0x08   ; 8
          .db #0x09   ; 9
      

      i guess why that was made like that, but that is the ugliest dirty hack.

       

Log in to post a comment.