Skip to content

REL File Format

ksherlock edited this page Dec 3, 2024 · 12 revisions
  • File Type: $F8 (User #8)
  • Aux Type: (offset of relocation table)

Relocatable intermediate files are generated via the REL pseudo op. OMF object files may also be converted to REL format with the CON command (via the editor command box).

The file is assembled, and all expressions are evaluated, with an origin of $8000. External labels are given an address of $8000

Bytes 0 -- (aux type-1) are the assembled data. This is followed by 0 or more relocation records, a 0 byte, 0 or more label entries, and a 0 byte.

Relocation Records

Relocation records are 4 bytes long. The first bytes is a flag byte. This is followed by a 16-bit offset, and an 8-bit operand byte. For external references, the operand byte is the external symbol number. For local references, the operand byte is the low 8-bits of the assembled operand.

Flag Byte

  • bits 0-3 always populated ($0f)
  • bit 4 ($10) indicates an external label
  • bit 7 ($80) indicates a 2-byte relocation
  • bit 6 ($40) indicates a 1-byte relocation with an 8-bit shift
  • bit 5 ($20) indicates a 3-byte relocation
  • bit 7 and 5 ($a0) indicates a 2-byte, byte swapped relocation (DDB).
  • $0f indicates a 1-byte relocation
  • $ff indicates a shift (see below)
  • $ef indicates an ERR \ operation (see below)
  • $cf indicates a DS \ operation (see below)

This is followed by the 16-bit offset to patch.

For external symbols, the 4th byte is the symbol number (which starts at 0). The inline operand bytes at offset (1-4 bytes) are an offset from the symbol, biased by $8000.

For local symbols, the 4th byte is the low byte of the operand at the offset.

Shifting

Shifts (16 bit or 8 bit only) use two relocation records. The first record uses a flag byte of $ff. This is followed by the offset and operand/symbol number as above.

Following the $ff record is the shift record.

  • $d0 is the shift operand.
  • bit 2 is the external ($04) / internal flag.
  • $d0 is a 16-bit, 1-byte shift (n.b. due to 24-bit address space, high byte of a 16-bit shift is always 0).
  • $d1 is an 8-bit, 2-byte shift
  • $d3 is an 8-bit, 1-byte shift

Other shift sizes are not supported.

This is followed by a 3-byte address of the value before shifting (as always, assuming an origin of $8000)

$4F Shifting

There is also a 1-relocation record shift available. This is 1-byte, 8-bit shift to an internal label.

The flag byte is $4f. The value is split, with the MSB inline and the LSB in the relocation record.

Labels

The label type and length are encoded in the first byte.

  • bits 0-4 ($1f) are the label length.
  • bit 5 ($20) indicates an absolute label (ie, exporting an EQU)
  • bit 6 ($40) indicates a local (ENTry) label.
  • bit 7 ($80) indicates an EXTernal label.

This is followed by the label and a 3-byte address.

For local and EQU labels, this is the label address (based on the $8000 origin).

For external labels, this is the external label number + $8000. For external direct page labels (EXD), this is the external label number.

DS \

Flag byte $cf indicates a DS \ opcode, which fills to the next page with a specified byte. This is followed, as before, by the 16-bit offset (which is meaningless) and the 8-bit fill byte (default is $00).

When this opcode is found in an REL file, it causes the Linker to load the next file in the linker name file at the first available page boundary, and to fill memory either with zeros or with the value specified by the expression. If used, this opcode should only be placed at the end of your source file.

ERR \

Flag byte $ef indicates an ERR \ opcode. This is followed by a 24-bit value.

This opcode will instruct the Linker to check that the last byte of the current file does not extend to "expression" or beyond. The expression must be absolute and not a relative expression.

If the Linker finds this is not the case, linking will abort with the message: CONSTRAINT ERROR: followed by the value of the expression in the ERR opcode.

The position of this opcode in a REL file has no bearing on its action. It is recommended that it be put at the end of a file.

References

  • Merlin 8/16 User's Manual
  • Merlin 16+ source code
  • Quick Asm source code
  • Empirical testing