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.
This commit is contained in:
Kartik K. Agaram 2021-08-22 21:38:22 -07:00
parent 5c26d765c7
commit ba4a3c5be7
2 changed files with 70 additions and 0 deletions

Binary file not shown.

View File

@ -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
#