summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2014-06-17 15:50:17 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2014-06-17 15:50:17 (GMT)
commitc2b2d4556275fad0360a98128bb62436134e2065 (patch)
treeeb50c22ab3044b72e74ccf326d522535dfd61cf3
parenta6a1600daa977d4f97f7e02a7499e1236afe54e9 (diff)
downloadabc80-c2b2d4556275fad0360a98128bb62436134e2065.zip
abc80-c2b2d4556275fad0360a98128bb62436134e2065.tar.gz
abc80-c2b2d4556275fad0360a98128bb62436134e2065.tar.bz2
abc80-c2b2d4556275fad0360a98128bb62436134e2065.tar.xz
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 <hpa@zytor.com>
-rw-r--r--data/bacldr.asm5
-rw-r--r--data/bacldr2.asm65
-rwxr-xr-xdata/bin2bac.pl68
3 files changed, 118 insertions, 20 deletions
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) = @_;
- # <bacldr.asm code>
- 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)) {
+ # <bacldr.asm code> - 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 {
+ # <bacldr2.asm> - 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);