From c2b2d4556275fad0360a98128bb62436134e2065 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 17 Jun 2014 08:50:17 -0700 Subject: bacldr: Add loader variant that supports relocatable code Add a version of the loader which supports relocatable code to be loaded at BOFA. Signed-off-by: H. Peter Anvin --- data/bacldr.asm | 5 ++--- data/bacldr2.asm | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ data/bin2bac.pl | 68 ++++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 data/bacldr2.asm diff --git a/data/bacldr.asm b/data/bacldr.asm index 2a232c1..d75f7d2 100644 --- a/data/bacldr.asm +++ b/data/bacldr.asm @@ -6,11 +6,10 @@ LOAD: equ 0xdddd ; Load address ENTRY: equ 0xbbbb ld hl,(BOFA) - ld de,offset - add hl,de + ld bc,offset ; offset <= 255 + add hl,bc ld de,LOAD - ld b,0 ; Get data block length loop: diff --git a/data/bacldr2.asm b/data/bacldr2.asm new file mode 100644 index 0000000..ae9c381 --- /dev/null +++ b/data/bacldr2.asm @@ -0,0 +1,65 @@ + ;; Load an assembly program at BOFA and handle relocations + ;; Relocations are a list of 16-bit addresses at the end of + ;; the image, processed in reverse order, terminated with + ;; an FFFFh sentinel. + + org 0 ; This code must be position-independent + +BOFA: equ 65052 +offset: equ 0xeeee ; Length of the BASIC prefix +ENTRY: equ 0xbbbb + + ld hl,(BOFA) + push hl + ld e,l + ld d,h + ld bc,offset ; Offset < 256 so B = 0 + add hl,bc + + ; Get data block length +loop: + ld a,-8 + add (hl) + jr nc,reloc ; END is a shorter line than any data line + + ; Skip length byte + line number (2 bytes) + string opcode (3 bytes) + ld c,6 + add hl,bc + + ; Copy remaining data + ld c,a + ldir + + ; Skip return + CR + inc hl + inc hl + jr loop + + ;; Process relocations. At this point DE points beyond + ;; the end of the contiguous image. +reloc: + pop bc ; BC <- BOFA +reloc_loop: + ex de,hl + dec hl + ld d,(hl) + dec hl + ld e,(hl) + ld a,e + and d + inc a ; A = FFh only if BC = FFFFh + jr z,reloc_done + ex de,hl + add hl,bc + ld a,(hl) + add c + ld (hl),a + inc hl + ld a,(hl) + adc a,b + ld (hl),a + jr reloc_loop +reloc_done: + ld hl,ENTRY + add hl,bc + jp (hl) diff --git a/data/bin2bac.pl b/data/bin2bac.pl index b3a7208..29b5ebc 100755 --- a/data/bin2bac.pl +++ b/data/bin2bac.pl @@ -27,20 +27,42 @@ sub bacstmt($$$) { sub makebac($$$) { my($data, $addr, $entrypt) = @_; - # - my $bld1 = "\x2a\x1c\xfe\x11"; - # 16-bit offset from BOFA to first data line between $bld1 and $bld2 - my $bld2 = "\x19\x11"; - # 16-bit load address between $bld2 and $bld3 - my $bld3 = "\x06\x00\x3e\xf8\x86\xd2"; - # 16-bit entr point between $bld3 and $bld4 - my $bld4 = "\x0e\x06\x09\x4f\xed\xb0\x23\x23\x18\xf0"; - # 0x00C9 is the address for END in all ABC80 BASIC interpreters - $entrypt = 0x00c9 unless(defined($entrypt)); - - # +2 for the final 0xbb + CR - my $bldlen = length($bld1) + 2 + length($bld2) + 2 + length($bld3) + 2 + - length($bld4) + 2; + my $bldlen; + my @bld; + + if (defined($addr)) { + # - fixed load address + $bld[0] = "\x2a\x1c\xfe\x01"; + # 16-bit offset from BOFA to first data line, must be <= 255 + $bld[1] = "\x09\x11"; + # 16-bit load address + $bld[2] = "\x06\x00\x3e\xf8\x86\xd2"; + # 16-bit entry point + $bld[3] = "\x0e\x06\x09\x4f\xed\xb0\x23\x23\x18\xf0"; + # 0x00C9 is the address for END in all ABC80 BASIC interpreters + $entrypt = 0x00c9 unless(defined($entrypt)); + + # +2 for the final 0xbb + CR + $bldlen = length($bld[0]) + 2 + length($bld[1]) + 2 + + length($bld[2]) + 2 + length($bld[3]) + 2; + } else { + # - relocatable data loaded at BOFA + $bld[0] = "\x2a\x1c\xfe\xe5\x5d\x54\x01"; + # 16-bit offset from BOFA to first data line, must be <= 255 + $bld[1] = "\x09\x3e\xf8\x86\x30\x0a\x0e\0x6\x09\x4f\xed\xb0"; + $bld[1] .= "\x23\x23\x18\xf1"; + $bld[1] .= "\xc1\xeb\x2b\x56\x2b\x5e\x7b\xa2\x3c\x28\x0b"; + $bld[1] .= "\xeb\x09\x7e\x81\x77\x23\x7e\x88\x77\x18\xeb\x21"; + # 16-bit offset for entry point + $bld[2] = "\x09\xe9"; + + # Default to entry = BOFA + $entrypt = 0 unless(defined($entrypt)); + + # +2 for the final 0xbb + CR + $bldlen = length($bld[0]) + 2 + length($bld[1]) + 2 + + length($bld[2]) + 2; + } my $q = "\x82"; # Output (program start marker) my $left = 251; # Bytes left in block @@ -54,8 +76,20 @@ sub makebac($$$) { pack("v",$bldlen)."\xf8\xce\x3a\xb7"); my $pfxlen = length($q) - 1; # The initial 0x82 isn't stored in RAM - my $bld = $bld1 . pack("v", $pfxlen) . $bld2 . pack("v", $addr) . - $bld3 . pack("v", $entrypt) . $bld4; + my $bld; + + die if ($pfxlen > 255); # Should not happen + + if (defined($addr)) { + $bld = $bld[0] . pack("v", $pfxlen) . + $bld[1] . pack("v", $addr) . + $bld[2] . pack("v", $entrypt) . + $bld[3]; + } else { + $bld = $bld[0] . pack("v", $pfxlen); + $bld[1] . pack("v", $entrypt) . + $bld[2]; + } my $i = 0; my $dl = length($data); @@ -93,6 +127,6 @@ open(FILE, '<:raw', $file) or die "$0: $file: $!\n"; $l = read(FILE, $dd, 65536); close(FILE); -$segs{$org} = $dd; +undef $org if ($org =~ /^(bofa|reloc|\-)$/i); print makebac($dd, $org, $entry); -- cgit v1.2.3