| The Small Code/Data model

Previous | The A68k Assembler | Next

Version 2.4 implements a rudimentary small code/data model. It consists of converting any data reference to one of the following three addressing modes:

- address register indirect with displacement using a specified address register, defaulting to `A4` (for references to the `DATA` or `BSS` section);
- program counter indirect with displacement (for references to the `CODE` section);
- absolute word (for absolute and 16-bit relocatable values).

These conversions do not take place unless a `NEAR` directive is encountered. The `NEAR` directive can take one operand, which must be either an address register or a symbol which has been equated (using `EQUR`) to an address register. Register `A7` (`SP`) may not be used. If no register is given, `A4` is assumed.
Conversion is done for all operands until a `FAR` directive is encountered. `NEAR` and `FAR` directives can occur any number of times, enabling conversion to be turned on and off at will.
Backward references which cannot be converted (e.g. external labels declared as `XREF`) will remain as absolute long addressing. All forward references are assumed to be convertible, since during pass 1 `A68k` has no way of telling whether conversion is possible. If conversion turns out to be impossible, invalid object code will be generated - an error message ("Invalid forward reference") will indicate when this occurs.
Although the small code/data model can greatly reduce the size of assembled programs, several restrictions apply:

- Small code and small data models are active simultaneously. You can't have one without the other, since during pass 1 A68k doesn't know whether forward references are to `CODE` or to `DATA`/`BSS`.
- Programs can consist of a maximum of two sections, one `CODE`, the other `DATA` or `BSS`. If you try to define a third section, the message "Too many SECTIONs" will be displayed. The `NEAR` directive is active only within the `CODE` section.
- While the `NEAR` directive is active, external labels (`XREF`) must be declared before they are used, `CODE` section references must be with 32K of the current position (i.e. expressible as PC-relative), and `DATA`/`BSS` section references must be in the first 64K of the `DATA`/`BSS` section (i.e. expressible as address register indirect with displacement). Any instructions which do not satisfy these requirements cannot be detected in pass 1, so A68k has no choice but to display an error message in pass 2 ("Invalid forward reference") which in this case indicates that invalid code has been generated. To properly assemble such instructions, you can temporarily disable conversion with a `FAR` directive, then resume afterwards with another `NEAR` directive.
- Conversion cannot be done for references between modules. All external references must be left as absolute long.
- `A68k` assumes that the base register (normally `A4`) points to the start of the `DATA`/`BSS` section plus 32768 bytes (this assumed offset can be changed by the '-m' command-line parameter). The register must be preloaded with this value before executing any code converted by the `NEAR` directive. One way to do this is to code the instruction that loads the register prior to the `NEAR` directive. Another way is to use a `MOVE.L` with immediate mode, which is never converted. Here are examples of the two methods:

           LEA data+32768,a4                NEAR
           NEAR ;defaults to A4             MOVE.L #data+32768,a4
           <remainder of code>              <remainder of code>
           BSS                              BSS
      data:                            data:
           <data areas>                     <data areas>
           END                              END

I'll be the first to admit that this is a very crude and ugly implementation. I hope to improve it in future versions.