Difference between revisions of "Code header"

From BeebWiki
Jump to: navigation, search
m (6809 - ROM type 3)
(Corrected extracting addresses.)
Line 15: Line 15:
 
The general layout of the code header is the following:
 
The general layout of the code header is the following:
  
   Start+0:  JMP Entry                           ; Code entry address or entry point
+
   Start+0:  JMP Entry                             ; Code entry address or entry point
   Start+3:  JMP Service                         ; Service entry point if a ROM
+
   Start+3:  JMP Service                           ; Service entry point if a ROM
   Start+6:  EQUB ROMtype                       ; Code type byte
+
   Start+6:  EQUB ROMtype                           ; Code type byte
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Version number and Title string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string (optional)
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston"         ; Copyright string
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
+
            EQUB &00
   Reloc+4:  EQUD Offset                         ; Offsets if specified by the ROMtype
+
   Reloc+0:  EQUD Start                             ; Load address if ROMtype bit 5 is set
   etc:      ....                               ; Possibly other data
+
   Reloc+4:  EQUD Offset                           ; Offsets if specified by the ROMtype
 +
   etc:      ....                                   ; Possibly other data
 
             ...
 
             ...
             ALIGN                               ; If the code needs to be aligned
+
             ALIGN                                 ; If the code needs to be aligned
 
   Entry:
 
   Entry:
 +
 +
The title, version and copyright strings should be formatted as shown. The binary
 +
version number should be either &0x for version x.yz or &xy for version x.yz.
 +
 +
Theoretically, the copyright offset can be any value up to &FF, and the copyright string
 +
can be any length, resulting in the relocation addresses being at any arbitary distance
 +
from the start of the file. In practice, the header should be written so it fits into
 +
a maximum of 256 bytes.
  
 
===ROM type byte===
 
===ROM type byte===
Line 49: Line 58:
 
If the code is run on a CPU that does not match the CPU type an error
 
If the code is run on a CPU that does not match the CPU type an error
 
similar to 'This is not Z80 code' is generated.
 
similar to 'This is not Z80 code' is generated.
 +
 +
Some clients always expect the relocation data to be present even if bit 5
 +
is clear, so a full header should always be used with the flag byte being
 +
&60+cpu or &E0+cpu.
  
 
===Entry point===
 
===Entry point===
Line 70: Line 83:
  
 
===65x2 - ROM type 0,1,2===
 
===65x2 - ROM type 0,1,2===
   Start+0:  JMP  Entry                         ; Code entry point
+
   Start+0:  JMP  Entry                             ; Code entry point
   Start+3:  JMP  Service                       ; Service entry point
+
   Start+3:  JMP  Service                           ; Service entry point
   Start+6:  EQUB ROMtype                       ; flags+&00, flags+&01, flags+&02
+
   Start+6:  EQUB ROMtype                           ; flags+&00, flags+&01, flags+&02
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
   Reloc+0:  EQUW Start                       ; Load address if ROMtype bit 5 is set
+
   Reloc+0:  EQUW Start                             ; Load address if ROMtype bit 5 is set
   Reloc+2:  EQUW RelocateTable               ; Normally 0, only supported by MOS 3.50
+
   Reloc+2:  EQUW RelocateTable                     ; Normally 0, only supported by MOS 3.50
   Entry:                                     ; Code start
+
  ...
 +
   Entry:                                           ; Code start
  
 
===6809 - ROM type 3===
 
===6809 - ROM type 3===
   Start+0:  BRA  Entry:NOP                     ; If position-independent code
+
   Start+0:  BRA  Entry:EQUB 0                     ; If position-independent code
           or JMP  >Entry                         ; If not position-independent code
+
           or JMP  >Entry                           ; If not position-independent code
   Start+3:  EQUB &4C:EQUW Service               ; 6502 jump to ROM service handler
+
   Start+3:  EQUB &4C:EQUW Service                 ; 6502 jump to ROM service handler
           or EQUB &60:EQUW 0                     ; 6502 RTS if no ROM service handler
+
           or EQUB &60:EQUW 0                       ; 6502 RTS if no ROM service handler
   Start+6:  EQUB flags+&03                     ; ROM type byte
+
   Start+6:  EQUB flags+&03                         ; ROM type byte
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
+
   Reloc+0:  EQUD Start                             ; Load address if ROMtype bit 5 is set
   Entry:                                         ; Code start
+
  ...
 +
   Entry:                                           ; Code start
  
 
===PDP11 - ROM type 7===
 
===PDP11 - ROM type 7===
   Start+0:  BR  Entry:EQUB 0                   ; Branch to code if ROMtype bit 5 is clear
+
   Start+0:  BR  Entry:EQUB 0                     ; Branch to code
   Start+3:  EQUB &4C:EQUW Service               ; 6502 jump to ROM service handler
+
   Start+3:  EQUB &4C:EQUW Service                 ; 6502 jump to ROM service handler
           or EQUB &60:EQUW 0                     ; 6502 RTS if no ROM service handler
+
           or EQUB &60:EQUW 0                       ; 6502 RTS if no ROM service handler
   Start+6:  EQUB flags+&07                     ; ROM type byte
+
   Start+6:  EQUB flags+&07                         ; ROM type byte
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
+
   Reloc+0:  EQUD Start                             ; Load address if ROMtype bit 5 is set
   Reloc+4:  EQUD Entry-Start                   ; Offset to entry if ROMtype bit 5 set
+
   Reloc+4:  EQUD Entry-Start                       ; Offset to entry if ROMtype bit 5 set
             ALIGN                               ; Alight to 16-bit words
+
  ...
   Entry:                                         ; Code start
+
             ALIGN                                 ; Align to 16-bit words
 +
   Entry:                                           ; Code start
  
 
===Z80 - ROM type 8===
 
===Z80 - ROM type 8===
   Start+0:  JR  Entry:NOP                     ; If position-independent code
+
   Start+0:  JR  Entry:EQUB 0                     ; If position-independent code
           or JP  Entry                         ; If not position-independent code
+
           or JP  Entry                             ; If not position-independent code
   Start+3:  EQUB &4C:EQUW Service               ; 6502 jump to ROM service handler
+
   Start+3:  EQUB &4C:EQUW Service                 ; 6502 jump to ROM service handler
           or EQUB &60:EQUW 0                     ; 6502 RTS if no ROM service handler
+
           or EQUB &60:EQUW 0                       ; 6502 RTS if no ROM service handler
   Start+6:  EQUB flags+&08                     ; ROM type byte
+
   Start+6:  EQUB flags+&08                         ; ROM type byte
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
+
   Reloc+0:  EQUD Start                             ; Load address if ROMtype bit 5 is set
   Entry:                                         ; Code start
+
  ...
 +
   Entry:                                           ; Code start
  
 
===32000 - ROM type 9===
 
===32000 - ROM type 9===
((NB: needs checking))
+
Even if the ROM type byte bit 5 is clear the entry offset at Reloc+4 must be present.
   Start+0:  EQUB 0:EQUW 0                       ; Ignored
+
 
   Start+3:  EQUB &4C:EQUW Service              ; 6502 jump to ROM service handler
+
   Start+0:  EQUB &60:EQUW 0                       ; 6502 RTS
           or EQUB &60:EQUW 0                    ; 6502 RTS if no ROM service handler
+
          or EQUB &4C:EQUW Language65              ; 6502 jump to 6502 language stub
   Start+6:  EQUB flags+&09                     ; ROM type byte
+
   Start+3:  EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
           or EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
   Start+6:  EQUB flags+&09                         ; ROM type byte
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
   Reloc+4:  EQUD Entry-Start                   ; Offset to entry if ROMtype bit 5 set
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
             ALIGN                               ; Alight to 16-bit words
+
   Reloc+0:  EQUD Start                             ; Load address, even if ROMtype bit 5 is not set
 +
   Reloc+4:  EQUD Entry-Start                       ; Offset to entry, even if ROMtype bit 5 is not set
 +
  ...
 +
             ALIGN                                 ; Align to 16-bit words
 
   Entry:
 
   Entry:
  
===80186, 80286 - ROM type 11,12===
+
===80x86 - ROM type 11===
((NB: needs checking))
+
   Start+0:  BR   Entry:EQUB 0                     ; Code is entered here
   Start+0:  JR   Entry:NOP                     ; If position-independant code
+
           or JMP  Entry                             ;
           or JP  Entry                         ; If not position-independant code
+
   Start+3:  EQUB &4C:EQUW Service                 ; 6502 jump to ROM service handler
   Start+3:  EQUB &4C:EQUW Service               ; 6502 jump to ROM service handler
+
           or EQUB &60:EQUW 0                       ; 6502 RTS if no ROM service handler
           or EQUB &60:EQUW 0                     ; 6502 RTS if no ROM service handler
+
   Start+6:  EQUB flags+&0B                         ; ROM type byte
   Start+6:  EQUB flags+&0B or +&0C              ; ROM type byte
+
   Start+7:  EQUB Copyright-Start                   ; Offset to copyright string
   Start+7:  EQUB Copyright-Start               ; Offset to copyright string
+
   Start+8:  EQUB Ver:EQUS "Title"                 ; Binary version number and title string
   Start+8:  EQUB 0:EQUS "Title"                 ; Binary version number and title string
+
             EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
             EQUB 0:EQUS "0.00 (01 Jan 2001)"   ; Version string (optional)
+
   Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
   Copyright: EQUB 0:EQUS "(C)J.G.Harston":EQUB 0 ; Copyright string
+
   Reloc+0:  EQUD Start                             ; Load address if ROMtype bit 5 is set
   Reloc+0:  EQUD Start                         ; Load address if ROMtype bit 5 is set
 
 
   Entry:
 
   Entry:
  
 
===ARM - ROM type 13===
 
===ARM - ROM type 13===
The ARM ROM header is complicated by having been implemented differently on
+
See also notes later.
different platforms, the Acorn ARM Evaluation System, the Arthur/RISC OS
 
RomFS, and the Sprow ARM CoProcessor.
 
 
 
((( I'm still writing this part, so will come back to it later )))
 
  
 +
  Start+0:  EQUW (Entry-Start-8)/4:EQUB 0:EQUB &EA ; ARM branch instruction, overlaps Start+3
 +
  Start+4:  EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
 +
          or EQUB &D0:EQUB Service-Start-6          ; 6502 BNE to ROM service handler
 +
  Start+6:  EQUB flags+&0D                        ; ROM type byte
 +
  Start+7:  EQUB Copyright-Start                  ; Offset to copyright string
 +
  Start+8:  EQUB Ver:EQUS "Title"                  ; Binary version number and title string
 +
            EQUB &00:EQUS "0.00 (01 Jan 2001)"    ; Version string
 +
  Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 +
  Reloc+0:  EQUD Start                            ; Load address, even if ROMtype bit 5 is not set
 +
  Reloc+4:  EQUD End-Entry                        ; Size of code, even if ROMtype bit 5 is not set
 +
  ...
 +
            ALIGN                                  ; Align to 32-bit words
 +
  Entry:
 +
  ...
 +
  End:
  
 
==Extracting load/exec address==
 
==Extracting load/exec address==
The load and execution addresses can be extracted from the code header with
+
File load and execution addresses can be extracted from the code header with
the follow pseudo-code:
+
the follow pseudo-code. The execution address is the same as the load address
 +
as the client code calculates the entry point as an offset from the execution
 +
address, which is the first byte of the header.
  
   load=unknown
+
   load=unknown; exec=load
  exec=unknown
+
   if start[7] does not point to &00,"(C)", then exit // Raw code
   if start+7 does not point to &00,"(C)", then exit   // Raw code
+
   load=&FFFF8000; exec=load
   load=&FFFF8000
 
  exec=&FFFF8000
 
 
   romtype=start[6]
 
   romtype=start[6]
 
   if rombyte bit 6 is clear, then exit                // No code, service ROM
 
   if rombyte bit 6 is clear, then exit                // No code, service ROM
   load=&8000
+
   load=&8000; exec=load
   exec=&8000
+
   if (rombyte AND 15)=9, then set bit 5 of rombyte    // 32000 always uses relocation address
 
   if romtype bit 5 is clear, then exit                // No relocation address
 
   if romtype bit 5 is clear, then exit                // No relocation address
 
   point to the relocation address after the zero
 
   point to the relocation address after the zero
 
     byte at the end of the copyright string
 
     byte at the end of the copyright string
   load=reload[0..3]
+
   load=reload[0..3]; exec=load
   exec=reload[0..3]
+
 
   switch (romtype AND 15) {
+
Clients calculate the entry point with the following pseudo-code.
     when 7,9: exec=load+reload[4..7]                 // PDP11, 32000
+
 
    when 13:  exec=start+8+start[0..2]*4              // ARM (not complete)
+
  entry=start
 +
  if start[7] does not point to &00,"(C)", then enter code        // Raw code
 +
  romtype=start[6]
 +
  if rombyte bit 6 is clear, then error "This is not code"        // No code
 +
  if (rombyte AND 15)<>mycpu, then error "This is not MyCPU code" // Wrong CPU
 +
  if (rombyte AND 15)=9, then assume bit 5 of rombyte is set      // 32000 always uses relocation address
 +
  if romtype bit 5 is clear, then enter code                      // No relocation address
 +
  point to the relocation address after the zero
 +
    byte at the end of the copyright string
 +
   entry=reload[0..3]
 +
   switch (rombyte AND 15) {
 +
     when 7,9: entry=start+reload[4..7]                           // PDP11, 32000, offset to entry point
 
   }
 
   }
   exit
+
   enter code
 +
 
  
[[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 22:07, 16 January 2017 (UTC)
+
[[User:Jgharston|Jgharston]] ([[User talk:Jgharston|talk]]) 00:07, 23 January 2017 (UTC)

Revision as of 01:07, 23 January 2017

Files have load and execution addresses that specify where they are loaded to and executed. These specify I/O memory by being &FFxxxxxx and language memory by being <>&FFxxxxxx. The I/O processor is always a 65x2, but the language processor can be one of many CPUs. Files can have a header which specifies what processor the code is written for so if it is run on the wrong processor the client code can generate an error.

The header is the same as the ROM header as ROMs also need to specify what CPU the code is written for and where the code should be copied to in the language memory. The code header also allows files to be loaded from filesystems that don't have load/exec addresses, such as DOS/Windows.

Header

The general layout of the code header is the following:

 Start+0:   JMP Entry                              ; Code entry address or entry point
 Start+3:   JMP Service                            ; Service entry point if a ROM
 Start+6:   EQUB ROMtype                           ; Code type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Version number and Title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string (optional)
 Copyright: EQUB &00:EQUS "(C)J.G.Harston"         ; Copyright string
            EQUB &00
 Reloc+0:   EQUD Start                             ; Load address if ROMtype bit 5 is set
 Reloc+4:   EQUD Offset                            ; Offsets if specified by the ROMtype
 etc:       ....                                   ; Possibly other data
            ...
            ALIGN                                  ; If the code needs to be aligned
 Entry:

The title, version and copyright strings should be formatted as shown. The binary version number should be either &0x for version x.yz or &xy for version x.yz.

Theoretically, the copyright offset can be any value up to &FF, and the copyright string can be any length, resulting in the relocation addresses being at any arbitary distance from the start of the file. In practice, the header should be written so it fits into a maximum of 256 bytes.

ROM type byte

The ROM type byte at Start+6 indicates what CPU the code is written for.

 bit 7 - Service entry for ROMs, ignored when loaded
 bit 6 - Contains code, if clear will generate an error similar to 'This is not a language'
 bit 5 - Contains a relocation address, if clear the code loads to &8000
 bit 4 - Electron key expansion
 bit 3-0 indicates the CPU type:
           0 6502 BASIC         5 -            8 Z80         12 80286
           1 Turbo6502          6 -            9 32016       13 ARM
           2 6502               7 -           10 -           14 -
           3 6800/6809/68000    8 PDP11       11 80186       15 -

Code in a ROM will normally have a ROM type byte of &E0+cpu, code loaded from a file that is not also a ROM image will normally have a ROM type byte of &60+cpu. If the ROM type byte is &40+cpu or &C0+cpu there is no relocation address and the code loads to &8000.

If the code is run on a CPU that does not match the CPU type an error similar to 'This is not Z80 code' is generated.

Some clients always expect the relocation data to be present even if bit 5 is clear, so a full header should always be used with the flag byte being &60+cpu or &E0+cpu.

Entry point

The entry point at Start+0 must be an unconditional branch to the code's start point in the machine code for the CPU. If the ROM type byte bit 7 is set then Start+3 contains the ROM service entry point, so the entry point at Start+0 must fit into three bytes. If the ROM type byte bit 7 is clear the code at Start+0 can be up to six bytes long, and some CPUs require this.

If ROMtype bit 7 is set then the entry point at Start+3 must be a 6502 unconditional branch to the ROM's service code, or a 6502 RTS.

The code is entered at the entry point with the registers set to a defined state. This is normally:

 Primary register:   0=raw code (no header), 1=code with a header
 Secondary register: points to command line tail
 Flags:              CC=entered at reset, CS=entered otherwise, eg a *command

Example headers

65x2 - ROM type 0,1,2

 Start+0:   JMP  Entry                             ; Code entry point
 Start+3:   JMP  Service                           ; Service entry point
 Start+6:   EQUB ROMtype                           ; flags+&00, flags+&01, flags+&02
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUW Start                             ; Load address if ROMtype bit 5 is set
 Reloc+2:   EQUW RelocateTable                     ; Normally 0, only supported by MOS 3.50
 ...
 Entry:                                            ; Code start

6809 - ROM type 3

 Start+0:   BRA  Entry:EQUB 0                      ; If position-independent code
         or JMP  >Entry                            ; If not position-independent code
 Start+3:   EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
         or EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
 Start+6:   EQUB flags+&03                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address if ROMtype bit 5 is set
 ...
 Entry:                                            ; Code start

PDP11 - ROM type 7

 Start+0:   BR   Entry:EQUB 0                      ; Branch to code
 Start+3:   EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
         or EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
 Start+6:   EQUB flags+&07                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address if ROMtype bit 5 is set
 Reloc+4:   EQUD Entry-Start                       ; Offset to entry if ROMtype bit 5 set
 ...
            ALIGN                                  ; Align to 16-bit words
 Entry:                                            ; Code start

Z80 - ROM type 8

 Start+0:   JR   Entry:EQUB 0                      ; If position-independent code
         or JP   Entry                             ; If not position-independent code
 Start+3:   EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
         or EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
 Start+6:   EQUB flags+&08                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address if ROMtype bit 5 is set
 ...
 Entry:                                            ; Code start

32000 - ROM type 9

Even if the ROM type byte bit 5 is clear the entry offset at Reloc+4 must be present.

 Start+0:   EQUB &60:EQUW 0                        ; 6502 RTS
         or EQUB &4C:EQUW Language65               ; 6502 jump to 6502 language stub
 Start+3:   EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
         or EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
 Start+6:   EQUB flags+&09                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address, even if ROMtype bit 5 is not set
 Reloc+4:   EQUD Entry-Start                       ; Offset to entry, even if ROMtype bit 5 is not set
 ...
            ALIGN                                  ; Align to 16-bit words
 Entry:

80x86 - ROM type 11

 Start+0:   BR   Entry:EQUB 0                      ; Code is entered here
         or JMP  Entry                             ;
 Start+3:   EQUB &4C:EQUW Service                  ; 6502 jump to ROM service handler
         or EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
 Start+6:   EQUB flags+&0B                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address if ROMtype bit 5 is set
 Entry:

ARM - ROM type 13

See also notes later.

 Start+0:   EQUW (Entry-Start-8)/4:EQUB 0:EQUB &EA ; ARM branch instruction, overlaps Start+3
 Start+4:   EQUB &60:EQUW 0                        ; 6502 RTS if no ROM service handler
         or EQUB &D0:EQUB Service-Start-6          ; 6502 BNE to ROM service handler
 Start+6:   EQUB flags+&0D                         ; ROM type byte
 Start+7:   EQUB Copyright-Start                   ; Offset to copyright string
 Start+8:   EQUB Ver:EQUS "Title"                  ; Binary version number and title string
            EQUB &00:EQUS "0.00 (01 Jan 2001)"     ; Version string
 Copyright: EQUB &00:EQUS "(C)J.G.Harston":EQUB 0  ; Copyright string
 Reloc+0:   EQUD Start                             ; Load address, even if ROMtype bit 5 is not set
 Reloc+4:   EQUD End-Entry                         ; Size of code, even if ROMtype bit 5 is not set
 ...
            ALIGN                                  ; Align to 32-bit words
 Entry:
 ...
 End:

Extracting load/exec address

File load and execution addresses can be extracted from the code header with the follow pseudo-code. The execution address is the same as the load address as the client code calculates the entry point as an offset from the execution address, which is the first byte of the header.

 load=unknown; exec=load
 if start[7] does not point to &00,"(C)", then exit  // Raw code
 load=&FFFF8000; exec=load
 romtype=start[6]
 if rombyte bit 6 is clear, then exit                // No code, service ROM
 load=&8000; exec=load
 if (rombyte AND 15)=9, then set bit 5 of rombyte    // 32000 always uses relocation address
 if romtype bit 5 is clear, then exit                // No relocation address
 point to the relocation address after the zero
   byte at the end of the copyright string
 load=reload[0..3]; exec=load

Clients calculate the entry point with the following pseudo-code.

 entry=start
 if start[7] does not point to &00,"(C)", then enter code        // Raw code
 romtype=start[6]
 if rombyte bit 6 is clear, then error "This is not code"        // No code
 if (rombyte AND 15)<>mycpu, then error "This is not MyCPU code" // Wrong CPU
 if (rombyte AND 15)=9, then assume bit 5 of rombyte is set      // 32000 always uses relocation address
 if romtype bit 5 is clear, then enter code                      // No relocation address
 point to the relocation address after the zero
   byte at the end of the copyright string
 entry=reload[0..3]
 switch (rombyte AND 15) {
   when 7,9: entry=start+reload[4..7]                            // PDP11, 32000, offset to entry point
 }
 enter code


Jgharston (talk) 00:07, 23 January 2017 (UTC)