What's the meaning of __saveds
in Amiga C code?
It's applied to function prototypes, and is required for functions that are to be called by assembler code, if I understand correctly.
Retrocomputing Stack Exchange is a question and answer site for vintage-computer hobbyists interested in restoring, preserving, and using the classic computer and gaming systems of yesteryear. It only takes a minute to sign up.
Sign up to join this communityWhat's the meaning of __saveds
in Amiga C code?
It's applied to function prototypes, and is required for functions that are to be called by assembler code, if I understand correctly.
Quoting from the SAS/C© Development System User's Guide, arguably the authoritative source for Amiga C code:
If you define a function with the
__saveds
keyword, the compiler generates extra code at the beginning of the function that loads the address of the near data section into register A4. Defining a function with the__saveds
keyword is equivalent to compiling that function with thesaveds
compiler option.
The extra code would typically look something like this:
...
LEA _LinkerDB,A4
...
_LinkerDB
is a symbol supplied by the linker, and points to the Near Data section.
The compiler tries to fit everything in this section, but it's limited to 64 KiB[1]. This limit means that it can be addressed using a shorter and faster 16-bit addressing mode. Another quote from the SAS/C manual:
When you link your program, all data in the near data and near BSS hunks are merged into one near data section. When you run your program, the startup module loads the address of the near data section into register A4, and this section is referenced with 16-bit A4-relative addresses.
Not only are the instructions shorter, but they don't need an entry in the relocation table, so it makes the executable file even smaller.
The key point here is that the startup module initializes A4, and the rest of the compiled code never touches it again. In "normal" code, you don't have to think about this. However, that "normal" code will expect A4 to point to the location of the data. If not, every single function would have to load the pointer, which would mostly negate the benefits of having one globally.
Thus, there are a few cases where you have to initialize it manually:
__saveds
once, and then it doesn't have to be touched again.[1]: Sometimes 32 KiB depending on the linker. Some linkers did not allow the full range to be used.
This is to make sure that the compiler generates code that loads the near data pointer in register a4 on each function entry so that your function is able to access its data. (source)