mirror of
https://github.com/cc65/cc65.git
synced 2024-07-09 01:28:58 +00:00
Streamlined the code, add zero page relocations
git-svn-id: svn://svn.cc65.org/cc65/trunk@1257 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
5d567426cb
commit
6bdf186607
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
.import pushax, pusha0, push0, push1, decax1
|
.import pushax, pusha0, push0, push1, decax1
|
||||||
.import _malloc, _free, _memset
|
.import _malloc, _free, _memset
|
||||||
|
.import __ZP_START__ ; Linker generated
|
||||||
.importzp sp, ptr1, tmp1, regbank
|
.importzp sp, ptr1, tmp1, regbank
|
||||||
|
|
||||||
.macpack generic
|
.macpack generic
|
||||||
@ -59,18 +60,22 @@ TPtr = regbank+4 ; Pointer to module data for relocation
|
|||||||
Stack: .byte 0 ; Old stackpointer
|
Stack: .byte 0 ; Old stackpointer
|
||||||
RegBankSave: .res 6 ; Save area for register bank
|
RegBankSave: .res 6 ; Save area for register bank
|
||||||
|
|
||||||
; The header of the o65 file. Since we don't need the 8 bytes any longer,
|
; The header of the o65 file. Since we don't need the first 8 bytes any
|
||||||
; once we've checked them, we will overlay them with other data to save a
|
; longer, once we've checked them, we will overlay them with other data to
|
||||||
; few bytes.
|
; save a few bytes.
|
||||||
Header: .res O65_HDR_SIZE ; The o65 header
|
Header: .res O65_HDR_SIZE ; The o65 header
|
||||||
|
|
||||||
; Input
|
; Input
|
||||||
InputByte = Header ; Byte read from input
|
InputByte = Header ; Byte read from input
|
||||||
|
|
||||||
; Stuff needed for relocation
|
; Stuff needed for relocation. Since the ld65 linker uses a relocation base
|
||||||
TextReloc = Header + 1 ; Relocation value for code seg
|
; address of zero for all segments, the relocation values needed are actually
|
||||||
DataReloc = Header + 3 ; Relocation value for data seg
|
; the start addresses of the segments. Among other things this means that the
|
||||||
BssReloc = Header + 5 ; Relocation value for bss seg
|
; relocation value for the text segment is the same as the start address as
|
||||||
|
; the whole module block.
|
||||||
|
TextReloc = Module ; Relocation value for code seg
|
||||||
|
DataReloc = Header + 1 ; Relocation value for data seg
|
||||||
|
BssReloc = Header + 3 ; Relocation value for bss seg
|
||||||
|
|
||||||
.data
|
.data
|
||||||
Read: jmp $FFFF ; Jump to read routine
|
Read: jmp $FFFF ; Jump to read routine
|
||||||
@ -106,15 +111,15 @@ LoadCtrl:
|
|||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; RestoreRegBank: Restore the register bank contents from the save area. Will
|
; RestoreRegBank: Restore the register bank contents from the save area. Will
|
||||||
; destroy A and X
|
; destroy A and X (the latter will be zero on return).
|
||||||
|
|
||||||
.code
|
.code
|
||||||
RestoreRegBank:
|
RestoreRegBank:
|
||||||
ldx #6-1
|
ldx #6
|
||||||
@L1: lda RegBankSave,x
|
@L1: lda RegBankSave-1,x
|
||||||
sta regbank,x
|
sta regbank-1,x
|
||||||
dex
|
dex
|
||||||
bpl @L1
|
bne @L1
|
||||||
rts
|
rts
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -140,7 +145,17 @@ GetReloc:
|
|||||||
ldx BssReloc+1
|
ldx BssReloc+1
|
||||||
rts
|
rts
|
||||||
|
|
||||||
@L3: lda #MLOAD_ERR_FMT
|
@L3: cmp #O65_SEGID_ZP
|
||||||
|
bne FormatError
|
||||||
|
lda #<__ZP_START__
|
||||||
|
ldx #>__ZP_START__
|
||||||
|
rts
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; FormatError: Bail out with an o65 format error
|
||||||
|
|
||||||
|
FormatError:
|
||||||
|
lda #MLOAD_ERR_FMT
|
||||||
; bne CleanupAndExit ; Branch always
|
; bne CleanupAndExit ; Branch always
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -181,6 +196,7 @@ CleanupAndExit:
|
|||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; ReadByte: Read one byte with error checking into InputByte and A.
|
; ReadByte: Read one byte with error checking into InputByte and A.
|
||||||
|
; ReadAndCheckError: Call read with the current C stack and check for errors.
|
||||||
|
|
||||||
.code
|
.code
|
||||||
ReadByte:
|
ReadByte:
|
||||||
@ -192,6 +208,10 @@ ReadByte:
|
|||||||
ldx #>InputByte
|
ldx #>InputByte
|
||||||
jsr pushax
|
jsr pushax
|
||||||
jsr push1
|
jsr push1
|
||||||
|
|
||||||
|
; This is a second entry point used by the other calls to Read
|
||||||
|
|
||||||
|
ReadAndCheckError:
|
||||||
jsr Read
|
jsr Read
|
||||||
|
|
||||||
; Check the return code and bail out in case of problems
|
; Check the return code and bail out in case of problems
|
||||||
@ -203,7 +223,7 @@ ReadByte:
|
|||||||
|
|
||||||
; Done
|
; Done
|
||||||
|
|
||||||
@L1: lda InputByte
|
@L1: lda InputByte ; If called ReadByte, load the byte read
|
||||||
Done: rts
|
Done: rts
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
@ -254,43 +274,44 @@ Loop: jsr ReadByte ; Read byte from relocation table
|
|||||||
; Check for and handle the different relocation types.
|
; Check for and handle the different relocation types.
|
||||||
|
|
||||||
cmp #O65_RTYPE_WORD
|
cmp #O65_RTYPE_WORD
|
||||||
bne @L3
|
beq RelocWord
|
||||||
|
cmp #O65_RTYPE_HIGH
|
||||||
|
beq RelocHigh
|
||||||
|
cmp #O65_RTYPE_LOW
|
||||||
|
bne FormatError
|
||||||
|
|
||||||
|
; Relocate the low byte
|
||||||
|
|
||||||
|
RelocLow:
|
||||||
|
ldy #0
|
||||||
|
clc
|
||||||
|
lda (TPtr),y
|
||||||
|
adc ptr1
|
||||||
|
sta (TPtr),y
|
||||||
|
jmp Loop
|
||||||
|
|
||||||
|
; Relocate a high byte
|
||||||
|
|
||||||
|
RelocHigh:
|
||||||
|
jsr ReadByte ; Read low byte from relocation table
|
||||||
|
ldy #0
|
||||||
|
clc
|
||||||
|
adc ptr1 ; We just need the carry
|
||||||
|
AddHigh:lda (TPtr),y
|
||||||
|
adc ptr1+1
|
||||||
|
sta (TPtr),y
|
||||||
|
jmp Loop ; Done, next entry
|
||||||
|
|
||||||
|
; Relocate a word
|
||||||
|
|
||||||
|
RelocWord:
|
||||||
ldy #0
|
ldy #0
|
||||||
clc
|
clc
|
||||||
lda (TPtr),y
|
lda (TPtr),y
|
||||||
adc ptr1
|
adc ptr1
|
||||||
sta (TPtr),y
|
sta (TPtr),y
|
||||||
iny
|
iny
|
||||||
bne @L4 ; Branch always (add high byte)
|
bne AddHigh ; Branch always (add high byte)
|
||||||
|
|
||||||
@L3: cmp #O65_RTYPE_HIGH
|
|
||||||
bne @L5
|
|
||||||
jsr ReadByte ; Read low byte from relocation table
|
|
||||||
ldy #0
|
|
||||||
clc
|
|
||||||
adc ptr1 ; We just need the carry
|
|
||||||
@L4: lda (TPtr),y
|
|
||||||
adc ptr1+1
|
|
||||||
sta (TPtr),y
|
|
||||||
jmp Loop ; Done, next entry
|
|
||||||
|
|
||||||
@L5: cmp #O65_RTYPE_LOW
|
|
||||||
beq @L6
|
|
||||||
|
|
||||||
; Problem: Invalid relocation code
|
|
||||||
|
|
||||||
lda #MLOAD_ERR_FMT
|
|
||||||
jmp CleanupAndExit
|
|
||||||
|
|
||||||
@L6: ldy #0
|
|
||||||
clc
|
|
||||||
lda (TPtr),y
|
|
||||||
adc ptr1
|
|
||||||
sta (TPtr),y
|
|
||||||
|
|
||||||
; Finished with this relocation
|
|
||||||
|
|
||||||
jmp Loop
|
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; mod_load: Load and relocate an o65 module
|
; mod_load: Load and relocate an o65 module
|
||||||
@ -336,18 +357,11 @@ _mod_load:
|
|||||||
jsr pushax
|
jsr pushax
|
||||||
lda #O65_HDR_SIZE
|
lda #O65_HDR_SIZE
|
||||||
jsr pusha0 ; Always less than 256
|
jsr pusha0 ; Always less than 256
|
||||||
jsr Read
|
jsr ReadAndCheckError ; Bails out in case of errors
|
||||||
|
|
||||||
; Check the return code
|
|
||||||
|
|
||||||
tax
|
|
||||||
beq @L2
|
|
||||||
lda #MLOAD_ERR_READ
|
|
||||||
jmp CleanupAndExit
|
|
||||||
|
|
||||||
; We read the o65 header successfully. Validate it.
|
; We read the o65 header successfully. Validate it.
|
||||||
|
|
||||||
@L2: ldy #ExpectedHdrSize-1
|
ldy #ExpectedHdrSize-1
|
||||||
@L3: lda Header,y
|
@L3: lda Header,y
|
||||||
cmp ExpectedHdr,y
|
cmp ExpectedHdr,y
|
||||||
beq @L4
|
beq @L4
|
||||||
@ -368,7 +382,10 @@ OneOpt: dec TPtr
|
|||||||
jmp OneOpt
|
jmp OneOpt
|
||||||
OptDone:
|
OptDone:
|
||||||
|
|
||||||
; Skipped all options. Calculate the sizes of several areas needed later
|
; Skipped all options. Calculate the size of text+data and of text+data+bss
|
||||||
|
; (the latter is the size of the memory block we need). We will store the
|
||||||
|
; total module size also into the control structure for evaluation by the
|
||||||
|
; caller
|
||||||
|
|
||||||
lda Header + O65_HDR_TLEN
|
lda Header + O65_HDR_TLEN
|
||||||
add Header + O65_HDR_DLEN
|
add Header + O65_HDR_DLEN
|
||||||
@ -378,20 +395,17 @@ OptDone:
|
|||||||
sta TPtr+1
|
sta TPtr+1
|
||||||
lda TPtr
|
lda TPtr
|
||||||
add Header + O65_HDR_BLEN
|
add Header + O65_HDR_BLEN
|
||||||
sta tmp1
|
pha ; Save low byte of total size
|
||||||
|
ldy #MODCTRL_MODULE_SIZE
|
||||||
|
sta (Ctrl),y
|
||||||
lda TPtr+1
|
lda TPtr+1
|
||||||
adc Header + O65_HDR_BLEN + 1
|
adc Header + O65_HDR_BLEN + 1
|
||||||
|
iny
|
||||||
; Load the total module size into a/x and store it into the control structure
|
|
||||||
|
|
||||||
ldy #MODCTRL_MODULE_SIZE + 1
|
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
tax
|
tax
|
||||||
dey
|
pla ; Restore low byte of total size
|
||||||
lda tmp1
|
|
||||||
sta (Ctrl),y
|
|
||||||
|
|
||||||
; Allocate memory, check if we got it
|
; Total memory size is now in a/x. Allocate memory, check if we got it.
|
||||||
|
|
||||||
jsr _malloc
|
jsr _malloc
|
||||||
sta Module
|
sta Module
|
||||||
@ -408,10 +422,10 @@ OptDone:
|
|||||||
; structure. We will use internal knowlege about the layout of the structure
|
; structure. We will use internal knowlege about the layout of the structure
|
||||||
; here to save some code.
|
; here to save some code.
|
||||||
|
|
||||||
GotMem: lda Module
|
GotMem: lda Module ; Ctrl->module = Module;
|
||||||
ldy #MODCTRL_MODULE
|
ldy #MODCTRL_MODULE
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
ldy #MODCTRL_CODE
|
ldy #MODCTRL_CODE ; Ctrl->code = Module;
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
txa
|
txa
|
||||||
iny
|
iny
|
||||||
@ -431,28 +445,34 @@ CLoop: lda Header,x
|
|||||||
cpy #MODCTRL_SIZE
|
cpy #MODCTRL_SIZE
|
||||||
bne CLoop
|
bne CLoop
|
||||||
|
|
||||||
; Missing in the control structure now: start of the data and bss segments
|
; Missing in the control structure now: start of the data and bss segments.
|
||||||
|
; Since the linker relocates all segments to zero, these addresses are also
|
||||||
|
; the relocation values for the segments.
|
||||||
|
|
||||||
ldy #MODCTRL_DATA
|
ldy #MODCTRL_DATA
|
||||||
lda Module
|
lda Module
|
||||||
add Header + O65_HDR_TLEN
|
add Header + O65_HDR_TLEN
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
|
sta DataReloc
|
||||||
iny
|
iny
|
||||||
lda Module + 1
|
lda Module + 1
|
||||||
adc Header + O65_HDR_TLEN + 1
|
adc Header + O65_HDR_TLEN + 1
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
|
sta DataReloc + 1
|
||||||
|
|
||||||
ldy #MODCTRL_BSS
|
ldy #MODCTRL_BSS
|
||||||
lda Module
|
lda Module
|
||||||
add TPtr
|
add TPtr
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
|
sta BssReloc
|
||||||
iny
|
iny
|
||||||
lda Module+1
|
lda Module+1
|
||||||
add TPtr+1
|
add TPtr+1
|
||||||
sta (Ctrl),y
|
sta (Ctrl),y
|
||||||
|
sta BssReloc + 1
|
||||||
|
|
||||||
; Control structure is complete now. Load code and data segment into memory.
|
; Control structure is complete now. Load code and data segment into memory.
|
||||||
; The sum of the sizes of code and data segment is still in TPtr.
|
; The sum of the sizes of code+data segment is still in TPtr.
|
||||||
; C->read (C, C->module, H.tlen + H.dlen)
|
; C->read (C, C->module, H.tlen + H.dlen)
|
||||||
|
|
||||||
jsr PushCtrl
|
jsr PushCtrl
|
||||||
@ -462,80 +482,44 @@ CLoop: lda Header,x
|
|||||||
lda TPtr
|
lda TPtr
|
||||||
ldx TPtr+1
|
ldx TPtr+1
|
||||||
jsr pushax
|
jsr pushax
|
||||||
jsr Read
|
jsr ReadAndCheckError ; Bails out in case of errors
|
||||||
|
|
||||||
; Check for errors
|
|
||||||
|
|
||||||
tax
|
|
||||||
beq LoadOk
|
|
||||||
lda #MLOAD_ERR_READ
|
|
||||||
jmp CleanupAndExit
|
|
||||||
|
|
||||||
; We've got the code and data segments in memory. Next section contains
|
; We've got the code and data segments in memory. Next section contains
|
||||||
; undefined references which we don't support. So check if the count of
|
; undefined references which we don't support. So check if the count of
|
||||||
; undefined references is actually zero.
|
; undefined references is actually zero.
|
||||||
|
|
||||||
LoadOk: jsr ReadByte
|
jsr ReadByte
|
||||||
bne Undef
|
bne Undef
|
||||||
jsr ReadByte
|
jsr ReadByte
|
||||||
beq Reloc
|
beq Reloc
|
||||||
Undef: lda #MLOAD_ERR_FMT
|
Undef: jmp FormatError
|
||||||
jmp CleanupAndExit
|
|
||||||
|
|
||||||
; Number of undefined references was zero. Next sections are the relocation
|
; Number of undefined references was zero. Next sections are the relocation
|
||||||
; tables for code and data segment. Before doing the actual relocation, we
|
; tables for code and data segment. Relocate the code segment
|
||||||
; have to setup the relocation values for the three segments.
|
|
||||||
|
|
||||||
Reloc: lda Module
|
Reloc: lda Module
|
||||||
sub Header + O65_HDR_TBASE
|
ldx Module + 1 ; Code segment address
|
||||||
sta TextReloc
|
|
||||||
lda Module + 1
|
|
||||||
sbc Header + O65_HDR_TBASE + 1
|
|
||||||
sta TextReloc + 1
|
|
||||||
|
|
||||||
ldy #MODCTRL_DATA
|
|
||||||
lda (Ctrl),y
|
|
||||||
sub Header + O65_HDR_DBASE
|
|
||||||
sta DataReloc
|
|
||||||
iny
|
|
||||||
lda (Ctrl),y
|
|
||||||
sbc Header + O65_HDR_DBASE + 1
|
|
||||||
sta DataReloc + 1
|
|
||||||
|
|
||||||
ldy #MODCTRL_BSS
|
|
||||||
lda (Ctrl),y
|
|
||||||
sub Header + O65_HDR_BBASE
|
|
||||||
sta BssReloc
|
|
||||||
iny
|
|
||||||
lda (Ctrl),y
|
|
||||||
sbc Header + O65_HDR_BBASE + 1
|
|
||||||
sta BssReloc + 1
|
|
||||||
|
|
||||||
; Relocate the code segment
|
|
||||||
|
|
||||||
lda Module
|
|
||||||
ldx Module + 1 ; Code segment address
|
|
||||||
jsr RelocSeg
|
jsr RelocSeg
|
||||||
|
|
||||||
; Relocate the data segment
|
; Relocate the data segment
|
||||||
|
|
||||||
ldy #MODCTRL_DATA + 1
|
ldy #MODCTRL_DATA + 1
|
||||||
jsr LoadCtrl ; Get data segment address
|
jsr LoadCtrl ; Get data segment address
|
||||||
jsr RelocSeg
|
jsr RelocSeg
|
||||||
|
|
||||||
; Clear the bss segment
|
; Clear the bss segment
|
||||||
|
|
||||||
ldy #MODCTRL_BSS + 1
|
ldy #MODCTRL_BSS + 1
|
||||||
jsr LoadCtrl ; Load bss segment address
|
jsr LoadCtrl ; Load bss segment address
|
||||||
jsr pushax
|
jsr pushax
|
||||||
jsr push0
|
jsr push0
|
||||||
ldy #MODCTRL_BSS_SIZE + 1
|
lda Header + O65_HDR_BLEN
|
||||||
jsr LoadCtrl ; Load bss segment size
|
ldx Header + O65_HDR_BLEN+1
|
||||||
jsr _memset ; memset (bss, 0, bss_size);
|
jsr _memset ; memset (bss, 0, bss_size);
|
||||||
|
|
||||||
; We're done. Restore the register bank and return a success code
|
; We're done. Restore the register bank and return a success code
|
||||||
|
|
||||||
jsr RestoreRegBank
|
jsr RestoreRegBank ; X will be zero on return
|
||||||
lda #MLOAD_OK
|
lda #MLOAD_OK
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user