about summary refs log tree commit diff stats
path: root/linux
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-08-22 21:38:22 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-08-22 21:40:03 -0700
commitba4a3c5be70d473479e663be0400b798f88c113d (patch)
treed0e332d7d67302cef5ef31e17152aeaec01b8ab6 /linux
parent5c26d765c7b0f263b48fcb5e903c2f284027859b (diff)
downloadmu-ba4a3c5be70d473479e663be0400b798f88c113d.tar.gz
start throwing error on labels too far for /disp8
While I'm doing this I might as well lay out a story I don't seem to
have told before in this commit log.

I translated Mu programs to Linux before I did so to bare metal like I
do in the top-level these days. The translator programs still run from
the linux/ directory. However they don't always have good error
messages. As long as I was translating to Linux this wasn't a huge deal
because I always translated Mu programs using the bootstrap translator
in linux/bootstrap/ -- which has great error messages. However,
linux/bootstrap/ can't build bare-metal programs because boot.subx uses
real-mode instructions that aren't supported. As a hack I created a
script called misc_checks that at least tries to run everything besides
boot.subx -- even though translation can never succeed. If I run it and
get to errors about unknown variables I know everything besides
boot.subx raised no errors.

Having labels too far in /disp8 args is is the single biggest reason we
need the misc_checks hack. Hopefully it's now obsolete.
Diffstat (limited to 'linux')
-rwxr-xr-xlinux/labels_baremetalbin52042 -> 52290 bytes
-rw-r--r--linux/labels_baremetal.subx70
2 files changed, 70 insertions, 0 deletions
diff --git a/linux/labels_baremetal b/linux/labels_baremetal
index ce80777e..c1db3ad6 100755
--- a/linux/labels_baremetal
+++ b/linux/labels_baremetal
Binary files differdiff --git a/linux/labels_baremetal.subx b/linux/labels_baremetal.subx
index 54d45425..be1dc768 100644
--- a/linux/labels_baremetal.subx
+++ b/linux/labels_baremetal.subx
@@ -435,6 +435,10 @@ emit-output:  # in: (addr stream byte), out: (addr buffered-file), labels: (addr
     #         emit(out, *address, 4)
     #       else if has-metadata?(word-slice, "disp8")
     #         value = *address - address-of-next-instruction
+    #         if value > 127
+    #           abort
+    #         if value < -128
+    #           abort
     #         emit(out, value, 1)
     #       else if has-metadata?(word-slice, "disp32")
     #         if far-jump-or-call?
@@ -1013,6 +1017,12 @@ $emit-output:emit-disp8:
     # var value/eax: int = *address - address-of-next-instruction
     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           3/r32/ebx   .               .                 # subtract ebx from eax
+    # if (value > 127) abort
+    3d/compare-eax-and  0x7f/imm32
+    0f 8f/jump-if->  $emit-output:error-disp8-too-large/disp32
+    # if (value < -128) abort
+    3d/compare-eax-and  -0x80/imm32
+    0f 8c/jump-if-<  $emit-output:error-disp8-too-large/disp32
     # emit-hex(out, value, 1)
     # . . push args
     68/push  1/imm32
@@ -1139,6 +1149,66 @@ $emit-output:abort:
     e8/call  syscall_exit/disp32
     # never gets here
 
+$emit-output:error-disp8-too-large:
+    # print(stderr, word-slice ": label too far below for /disp8; use /disp32")
+    # . write-slice-buffered(Stderr, word-slice)
+    # . . push args
+    52/push-edx
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  write-slice-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . flush(Stderr)
+    # . . push args
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . _write(2/stderr, msg)
+    # . . push args
+    68/push  ": label too far below for /disp8; use /disp32"/imm32
+    68/push  2/imm32/stderr
+    # . . call
+    e8/call  _write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . syscall_exit(1)
+    bb/copy-to-ebx  1/imm32
+    e8/call  syscall_exit/disp32
+    # never gets here
+
+$emit-output:error-disp8-too-small:
+    # print(stderr, word-slice ": label too far above for /disp8; use /disp32")
+    # . write-slice-buffered(Stderr, word-slice)
+    # . . push args
+    52/push-edx
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  write-slice-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . flush(Stderr)
+    # . . push args
+    68/push  Stderr/imm32
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
+    # . _write(2/stderr, msg)
+    # . . push args
+    68/push  ": label too far above for /disp8; use /disp32"/imm32
+    68/push  2/imm32/stderr
+    # . . call
+    e8/call  _write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # . syscall_exit(1)
+    bb/copy-to-ebx  1/imm32
+    e8/call  syscall_exit/disp32
+    # never gets here
+
 test-emit-output-non-far-control-flow:
     # labels turn into absolute addresses if opcodes are not far jumps or calls
     #