mirror of
https://github.com/cc65/cc65.git
synced 2024-11-18 15:05:14 +00:00
Added check/support for simple addressing format.
Check the operating system option and return the module id to the caller. Use bzero instead of memset. git-svn-id: svn://svn.cc65.org/cc65/trunk@1278 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
009df2d6b5
commit
9364b206ab
@ -37,7 +37,7 @@
|
|||||||
.include "modload.inc"
|
.include "modload.inc"
|
||||||
|
|
||||||
.import pushax, pusha0, push0, push1, decax1
|
.import pushax, pusha0, push0, push1, decax1
|
||||||
.import _malloc, _free, _memset
|
.import _malloc, _free, _bzero
|
||||||
.import __ZP_START__ ; Linker generated
|
.import __ZP_START__ ; Linker generated
|
||||||
.importzp sp, ptr1, tmp1, regbank
|
.importzp sp, ptr1, tmp1, regbank
|
||||||
|
|
||||||
@ -68,21 +68,16 @@ Header: .res O65_HDR_SIZE ; The o65 header
|
|||||||
; Input
|
; Input
|
||||||
InputByte = Header ; Byte read from input
|
InputByte = Header ; Byte read from input
|
||||||
|
|
||||||
; Segment addresses. Since the ld65 linker uses a relocation base address
|
|
||||||
; of zero for all segments, the addresses of the segments are also the
|
|
||||||
; relocation values.
|
|
||||||
CodeAddr = Module ; Address of code seg
|
|
||||||
DataAddr = Header + 1 ; Address of data seg
|
|
||||||
BssAddr = Header + 3 ; Address of bss seg
|
|
||||||
|
|
||||||
.data
|
.data
|
||||||
Read: jmp $FFFF ; Jump to read routine
|
Read: jmp $FFFF ; Jump to read routine
|
||||||
|
|
||||||
.rodata
|
.rodata
|
||||||
ExpectedHdr: .byte $01, $00 ; non C64 marker
|
ExpectedHdr:
|
||||||
|
.byte $01, $00 ; non C64 marker
|
||||||
.byte $6F, $36, $35 ; Magic ("o65")
|
.byte $6F, $36, $35 ; Magic ("o65")
|
||||||
.byte $00 ; Version
|
.byte $00 ; Version
|
||||||
.word $0000 ; Mode word
|
.word O65_CPU_6502|O65_RELOC_BYTE|O65_SIZE_16BIT|O65_FTYPE_EXE|O65_ADDR_SIMPLE|O65_ALIGN_1
|
||||||
|
|
||||||
ExpectedHdrSize = * - ExpectedHdr
|
ExpectedHdrSize = * - ExpectedHdr
|
||||||
|
|
||||||
|
|
||||||
@ -109,37 +104,33 @@ RestoreRegBank:
|
|||||||
rts
|
rts
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; GetReloc: Return a relocation value based on the segment in A
|
; GetReloc: Return a relocation value based on the segment in A.
|
||||||
|
; The routine uses some knowledge about the values to make the code shorter.
|
||||||
|
|
||||||
.code
|
.code
|
||||||
GetReloc:
|
GetReloc:
|
||||||
cmp #O65_SEGID_TEXT
|
cmp #O65_SEGID_TEXT
|
||||||
bne @L1
|
bcc FormatError
|
||||||
lda CodeAddr
|
cmp #O65_SEGID_ZP
|
||||||
ldx CodeAddr+1
|
beq @L1
|
||||||
|
bcs FormatError
|
||||||
|
|
||||||
|
; Text, data and bss segment
|
||||||
|
|
||||||
|
lda Module
|
||||||
|
ldx Module+1 ; Return start address of buffer
|
||||||
rts
|
rts
|
||||||
|
|
||||||
@L1: cmp #O65_SEGID_DATA
|
; Zero page relocation
|
||||||
bne @L2
|
|
||||||
lda DataAddr
|
|
||||||
ldx DataAddr+1
|
|
||||||
rts
|
|
||||||
|
|
||||||
@L2: cmp #O65_SEGID_BSS
|
@L1: lda #<__ZP_START__
|
||||||
bne @L3
|
|
||||||
lda BssAddr
|
|
||||||
ldx BssAddr+1
|
|
||||||
rts
|
|
||||||
|
|
||||||
@L3: cmp #O65_SEGID_ZP
|
|
||||||
bne FormatError
|
|
||||||
lda #<__ZP_START__
|
|
||||||
ldx #>__ZP_START__
|
ldx #>__ZP_START__
|
||||||
rts
|
rts
|
||||||
|
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
; FormatError: Bail out with an o65 format error
|
; FormatError: Bail out with an o65 format error
|
||||||
|
|
||||||
|
.code
|
||||||
FormatError:
|
FormatError:
|
||||||
lda #MLOAD_ERR_FMT
|
lda #MLOAD_ERR_FMT
|
||||||
; bne CleanupAndExit ; Branch always
|
; bne CleanupAndExit ; Branch always
|
||||||
@ -271,10 +262,8 @@ Loop: jsr ReadByte ; Read byte from relocation table
|
|||||||
RelocLow:
|
RelocLow:
|
||||||
ldy #0
|
ldy #0
|
||||||
clc
|
clc
|
||||||
lda (TPtr),y
|
lda ptr1
|
||||||
adc ptr1
|
bcc AddCommon
|
||||||
sta (TPtr),y
|
|
||||||
jmp Loop
|
|
||||||
|
|
||||||
; Relocate a high byte
|
; Relocate a high byte
|
||||||
|
|
||||||
@ -283,8 +272,10 @@ RelocHigh:
|
|||||||
ldy #0
|
ldy #0
|
||||||
clc
|
clc
|
||||||
adc ptr1 ; We just need the carry
|
adc ptr1 ; We just need the carry
|
||||||
AddHigh:lda (TPtr),y
|
AddHigh:
|
||||||
adc ptr1+1
|
lda ptr1+1
|
||||||
|
AddCommon:
|
||||||
|
adc (TPtr),y
|
||||||
sta (TPtr),y
|
sta (TPtr),y
|
||||||
jmp Loop ; Done, next entry
|
jmp Loop ; Done, next entry
|
||||||
|
|
||||||
@ -293,8 +284,8 @@ AddHigh:lda (TPtr),y
|
|||||||
RelocWord:
|
RelocWord:
|
||||||
ldy #0
|
ldy #0
|
||||||
clc
|
clc
|
||||||
lda (TPtr),y
|
lda ptr1
|
||||||
adc ptr1
|
adc (TPtr),y
|
||||||
sta (TPtr),y
|
sta (TPtr),y
|
||||||
iny
|
iny
|
||||||
bne AddHigh ; Branch always (add high byte)
|
bne AddHigh ; Branch always (add high byte)
|
||||||
@ -350,31 +341,89 @@ _mod_load:
|
|||||||
; We read the o65 header successfully. Validate it.
|
; We read the o65 header successfully. Validate it.
|
||||||
|
|
||||||
ldy #ExpectedHdrSize-1
|
ldy #ExpectedHdrSize-1
|
||||||
@L3: lda Header,y
|
ValidateHeader:
|
||||||
|
lda Header,y
|
||||||
cmp ExpectedHdr,y
|
cmp ExpectedHdr,y
|
||||||
beq @L4
|
bne HeaderError
|
||||||
lda #MLOAD_ERR_HDR
|
dey
|
||||||
jmp CleanupAndExit
|
bpl ValidateHeader
|
||||||
@L4: dey
|
|
||||||
bpl @L3
|
|
||||||
|
|
||||||
; Header is ok as far as we can say now. Read and skip all options. We may
|
; Header is ok as far as we can say now. Read all options, check for the
|
||||||
; add a check here for the OS option later.
|
; OS option and ignore all others. The OS option contains a version number
|
||||||
|
; and the module id as additional data.
|
||||||
|
|
||||||
Opt: jsr ReadByte
|
iny ; Y = $00
|
||||||
|
sty TPtr+1 ; Flag for OS option read
|
||||||
|
Opt: jsr ReadByte ; Read the length byte
|
||||||
beq OptDone ; Jump if done
|
beq OptDone ; Jump if done
|
||||||
sta TPtr ; Use TPtr as a counter
|
sta TPtr ; Use TPtr as a counter
|
||||||
OneOpt: dec TPtr
|
|
||||||
|
; An option has a length of at least 2 bytes
|
||||||
|
|
||||||
|
cmp #2
|
||||||
|
bcc HeaderError ; Must be 2 bytes total at least
|
||||||
|
|
||||||
|
; Check for the OS option
|
||||||
|
|
||||||
|
dec TPtr
|
||||||
|
jsr ReadByte ; Get the option type
|
||||||
|
cmp #O65_OPT_OS ; OS option?
|
||||||
|
bne SkipOpt ; No: Skip
|
||||||
|
|
||||||
|
lda TPtr ; Get remaining length+1
|
||||||
|
cmp #5 ; CC65 has 6 bytes total
|
||||||
|
bne OSError
|
||||||
|
|
||||||
|
jsr ReadByte ; Get the operating system
|
||||||
|
cmp #O65_OS_CC65_MODULE
|
||||||
|
bne OSError ; Wrong operating system
|
||||||
|
|
||||||
|
jsr ReadByte ; Get the version number, expect zero
|
||||||
|
bne OSError ; Wrong version
|
||||||
|
|
||||||
|
jsr ReadByte ; Get low byte of id
|
||||||
|
ldy #MODCTRL_MODULE_ID
|
||||||
|
sta (Ctrl),y
|
||||||
|
jsr ReadByte
|
||||||
|
ldy #MODCTRL_MODULE_ID+1
|
||||||
|
sta (Ctrl),y
|
||||||
|
|
||||||
|
inc TPtr+1 ; Remember that we got the OS
|
||||||
|
|
||||||
|
jmp Opt
|
||||||
|
|
||||||
|
; Skip one option
|
||||||
|
|
||||||
|
SkipOpt:
|
||||||
|
dec TPtr
|
||||||
beq Opt ; Next option
|
beq Opt ; Next option
|
||||||
jsr ReadByte ; Skip one byte
|
jsr ReadByte ; Skip one byte
|
||||||
jmp OneOpt
|
jmp SkipOpt
|
||||||
|
|
||||||
|
; Operating system error
|
||||||
|
|
||||||
|
OSError:
|
||||||
|
lda #MLOAD_ERR_OS
|
||||||
|
jmp CleanupAndExit
|
||||||
|
|
||||||
|
; Options done, check that we got the OS option
|
||||||
|
|
||||||
OptDone:
|
OptDone:
|
||||||
|
lda TPtr+1
|
||||||
|
bne CalcSizes
|
||||||
|
|
||||||
|
; Entry point for header errors
|
||||||
|
|
||||||
|
HeaderError:
|
||||||
|
lda #MLOAD_ERR_HDR
|
||||||
|
jmp CleanupAndExit
|
||||||
|
|
||||||
; Skipped all options. Calculate the size of text+data and of text+data+bss
|
; 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
|
; (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
|
; total module size also into the control structure for evaluation by the
|
||||||
; caller
|
; caller
|
||||||
|
|
||||||
|
CalcSizes:
|
||||||
lda Header + O65_HDR_TLEN
|
lda Header + O65_HDR_TLEN
|
||||||
add Header + O65_HDR_DLEN
|
add Header + O65_HDR_DLEN
|
||||||
sta TPtr
|
sta TPtr
|
||||||
@ -393,12 +442,20 @@ OptDone:
|
|||||||
tax
|
tax
|
||||||
pla ; Restore low byte of total size
|
pla ; Restore low byte of total size
|
||||||
|
|
||||||
; Total memory size is now in a/x. Allocate memory, check if we got it.
|
; Total memory size is now in a/x. Allocate memory and remember the result,
|
||||||
|
; both, locally and in the control structure so it the caller can access
|
||||||
|
; the memory block. After that, check if we got the requested memory.
|
||||||
|
|
||||||
jsr _malloc
|
jsr _malloc
|
||||||
sta Module
|
sta Module
|
||||||
stx Module+1
|
stx Module+1
|
||||||
ora Module+1
|
|
||||||
|
ldy #MODCTRL_MODULE
|
||||||
|
sta (Ctrl),y
|
||||||
|
txa
|
||||||
|
iny
|
||||||
|
sta (Ctrl),y
|
||||||
|
ora Module
|
||||||
bne GotMem
|
bne GotMem
|
||||||
|
|
||||||
; Could not allocate memory
|
; Could not allocate memory
|
||||||
@ -406,39 +463,26 @@ OptDone:
|
|||||||
lda #MLOAD_ERR_MEM
|
lda #MLOAD_ERR_MEM
|
||||||
jmp CleanupAndExit
|
jmp CleanupAndExit
|
||||||
|
|
||||||
; We got the memory block. Place a pointer to the memory block also in the
|
; Control structure is complete now. Clear the bss segment.
|
||||||
; module control structure.
|
; bzero (bss_addr, bss_size)
|
||||||
|
|
||||||
GotMem: lda Module ; Ctrl->module = Module;
|
|
||||||
ldy #MODCTRL_MODULE
|
|
||||||
sta (Ctrl),y
|
|
||||||
txa
|
|
||||||
iny
|
|
||||||
sta (Ctrl),y
|
|
||||||
|
|
||||||
; Calculate the start addresses of the segments. Since the linker uses a
|
|
||||||
; base address of zero for all segments, the load addresses are also the
|
|
||||||
; relocation values for the segments.
|
|
||||||
|
|
||||||
lda Module
|
|
||||||
add Header + O65_HDR_TLEN
|
|
||||||
sta DataAddr
|
|
||||||
lda Module + 1
|
|
||||||
adc Header + O65_HDR_TLEN + 1
|
|
||||||
sta DataAddr + 1
|
|
||||||
|
|
||||||
lda Module
|
lda Module
|
||||||
add TPtr
|
add TPtr
|
||||||
sta BssAddr
|
pha
|
||||||
lda Module+1
|
lda Module+1
|
||||||
add TPtr+1
|
adc TPtr+1 ; Module + tlen + dlen
|
||||||
sta BssAddr + 1
|
tax
|
||||||
|
pla
|
||||||
|
jsr pushax
|
||||||
|
lda Header + O65_HDR_BLEN
|
||||||
|
ldx Header + O65_HDR_BLEN+1
|
||||||
|
jsr _bzero ; bzero (bss, bss_size);
|
||||||
|
|
||||||
; Control structure is complete now. Load code and data segment into memory.
|
; Load code and data segment into memory. The sum of the sizes of
|
||||||
; The sum of the sizes of code+data segment is still in TPtr.
|
; 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
|
GotMem: jsr PushCtrl
|
||||||
lda Module
|
lda Module
|
||||||
ldx Module+1
|
ldx Module+1
|
||||||
jsr pushax
|
jsr pushax
|
||||||
@ -472,19 +516,9 @@ Reloc: lda Module
|
|||||||
lda Module + 1
|
lda Module + 1
|
||||||
adc Header + O65_HDR_TLEN + 1
|
adc Header + O65_HDR_TLEN + 1
|
||||||
tax
|
tax
|
||||||
pla ; Date segment address in a/x
|
pla ; Data segment address in a/x
|
||||||
jsr RelocSeg
|
jsr RelocSeg
|
||||||
|
|
||||||
; Clear the bss segment: memset (bss_addr, 0, bss_size)
|
|
||||||
|
|
||||||
lda BssAddr
|
|
||||||
ldx BssAddr + 1
|
|
||||||
jsr pushax
|
|
||||||
jsr push0
|
|
||||||
lda Header + O65_HDR_BLEN
|
|
||||||
ldx Header + O65_HDR_BLEN+1
|
|
||||||
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 ; X will be zero on return
|
jsr RestoreRegBank ; X will be zero on return
|
||||||
|
Loading…
Reference in New Issue
Block a user