GNO Support
This commit is contained in:
parent
f4503f73c0
commit
9e53e5fd38
55 changed files with 3490 additions and 389 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -20,3 +20,6 @@ tests/coremark/coreMark.bin
|
|||
*.swo
|
||||
.DS_Store
|
||||
*~
|
||||
|
||||
stuff/
|
||||
ROM Source Code.zip
|
||||
|
|
|
|||
59
demos/buildGno.sh
Executable file
59
demos/buildGno.sh
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env bash
|
||||
# buildGno.sh — compile a C source into a GNO/ME-loadable OMF shell command.
|
||||
#
|
||||
# Usage: bash demos/buildGno.sh <basename>
|
||||
# demos/<basename>.c -> demos/<basename>.omf
|
||||
#
|
||||
# Uses crt0Gno (GNO entry contract) + the GNO libc backend, then wraps
|
||||
# the flat image in a relocatable ExpressLoad OMF via omfEmit — the
|
||||
# GS/OS Loader (which GNO uses to launch commands) requires a real OMF,
|
||||
# not a flat binary.
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
[ $# -ge 1 ] || { echo "usage: $0 <basename>" >&2; exit 2; }
|
||||
BASE="$1"
|
||||
SRC="$SCRIPT_DIR/$BASE.c"
|
||||
[ -f "$SRC" ] || { echo "no source: $SRC" >&2; exit 2; }
|
||||
|
||||
CLANG="$ROOT/tools/llvm-mos-build/bin/clang"
|
||||
LINK="$ROOT/tools/link816"
|
||||
OMF="$ROOT/tools/omfEmit"
|
||||
RT="$ROOT/runtime"
|
||||
|
||||
OBJ="$SCRIPT_DIR/$BASE.o"
|
||||
BIN="$SCRIPT_DIR/$BASE.bin"
|
||||
MAP="$SCRIPT_DIR/$BASE.map"
|
||||
RELOC="$SCRIPT_DIR/$BASE.reloc"
|
||||
OUT="$SCRIPT_DIR/$BASE.omf"
|
||||
|
||||
echo "compile: $BASE.c -> $BASE.o"
|
||||
"$CLANG" --target=w65816 -I"$RT/include" -O2 -ffunction-sections -c "$SRC" -o "$OBJ"
|
||||
|
||||
echo "link: -> $BASE.bin"
|
||||
"$LINK" -o "$BIN" --text-base 0x1000 --bss-base 0xA000 \
|
||||
--map "$MAP" --reloc-out "$RELOC" \
|
||||
"$RT/crt0Gno.o" "$OBJ" \
|
||||
"$RT/libcGno.o" "$RT/gnoKernel.o" "$RT/gnoGsos.o" \
|
||||
"$RT/libc.o" "$RT/snprintf.o" "$RT/extras.o" \
|
||||
"$RT/softFloat.o" "$RT/softDouble.o" \
|
||||
"$RT/libgcc.o"
|
||||
|
||||
echo "OMF: -> $BASE.omf"
|
||||
# Declare a dedicated DP/Stack (OMF KIND=0x1012) segment. Without it GNO
|
||||
# falls back to a 4 KB default stack shared with DP and placed low in bank 0,
|
||||
# which is too small / mis-placed for GS/OS file I/O: GNO's GS/OS interceptor
|
||||
# (StackGSOS) carves its direct-page work area off the caller's S and the FST
|
||||
# nests deep below it, corrupting the saved SP on certain stack-buffer layouts.
|
||||
# A sized $12 segment makes the Loader allocate a larger bank-0 block (S set
|
||||
# high in it), giving headroom and moving stack buffers off the collision.
|
||||
# This is the idiomatic ORCA/GNO mechanism (== #pragma stacksize).
|
||||
"$OMF" --input "$BIN" --map "$MAP" \
|
||||
--base 0x1000 --entry __start --output "$OUT" \
|
||||
--name "$(echo "$BASE" | tr '[:lower:]' '[:upper:]' | cut -c1-8)" \
|
||||
--expressload --relocs "$RELOC" --stack-size "${GNO_STACK_SIZE:-0x4000}"
|
||||
|
||||
ls -la "$OUT"
|
||||
echo "done: $OUT (run with: bash scripts/runInGno.sh $OUT --check 0x025000=C0DE)"
|
||||
BIN
demos/gnoCat.bin
Normal file
BIN
demos/gnoCat.bin
Normal file
Binary file not shown.
15
demos/gnoCat.c
Normal file
15
demos/gnoCat.c
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// gnoCat.c — read one line from stdin (GNO console) and echo it.
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char line[80];
|
||||
printf("Type a line:\n");
|
||||
if (fgets(line, sizeof(line), stdin))
|
||||
printf("You typed: %s", line);
|
||||
else
|
||||
printf("(EOF)\n");
|
||||
*(volatile uint16_t *)0x025000UL = 0xC0DE;
|
||||
for (volatile unsigned long i = 0; i < 300000UL; i++) {}
|
||||
return 0;
|
||||
}
|
||||
221
demos/gnoCat.map
Normal file
221
demos/gnoCat.map
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x0051f7 ( 16887 bytes)
|
||||
.rodata : 0x0051f7 .. 0x0056c0 ( 1225 bytes)
|
||||
.bss : 0x00a000 .. 0x00a182 ( 386 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
113 /home/scott/claude/llvm816/runtime/crt0Gno.o
|
||||
458 /home/scott/claude/llvm816/demos/gnoCat.o
|
||||
3444 /home/scott/claude/llvm816/runtime/libcGno.o
|
||||
925 /home/scott/claude/llvm816/runtime/gnoKernel.o
|
||||
34 /home/scott/claude/llvm816/runtime/gnoGsos.o
|
||||
32141 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9075 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
2552 /home/scott/claude/llvm816/runtime/libgcc.o
|
||||
|
||||
# global symbols (sorted by address)
|
||||
0x000000 __bss_bank
|
||||
0x000000 __bss_seg0_bank
|
||||
0x000000 __bss_seg1_bank
|
||||
0x000000 __bss_seg1_lo16
|
||||
0x000000 __bss_seg1_size
|
||||
0x000000 __bss_seg2_bank
|
||||
0x000000 __bss_seg2_lo16
|
||||
0x000000 __bss_seg2_size
|
||||
0x000000 __bss_seg3_bank
|
||||
0x000000 __bss_seg3_lo16
|
||||
0x000000 __bss_seg3_size
|
||||
0x000182 __bss_seg0_size
|
||||
0x000182 __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x001071 main
|
||||
0x00123b gsosRead
|
||||
0x001251 __putByte
|
||||
0x00139e __getByte
|
||||
0x00153e __gnoStartup
|
||||
0x0017e0 _exit
|
||||
0x001811 __gnoGsosCall
|
||||
0x001826 __gnoCallNum
|
||||
0x001828 __gnoPBlock
|
||||
0x001833 memset
|
||||
0x001891 puts
|
||||
0x00194b vprintf
|
||||
0x00276e writeULong
|
||||
0x0028e0 writeUDec
|
||||
0x002a20 writeHex
|
||||
0x002baf printf
|
||||
0x002c34 fgetc
|
||||
0x00306c fgets
|
||||
0x003170 __adddf3
|
||||
0x003cfa __subdf3
|
||||
0x003d34 __muldf3
|
||||
0x0043b7 __floatsidf
|
||||
0x004535 __floatunsidf
|
||||
0x004654 __fixdfsi
|
||||
0x0047ff __jsl_indir
|
||||
0x004802 __mulhi3
|
||||
0x004821 __umulhisi3
|
||||
0x004878 __ashlhi3
|
||||
0x004887 __lshrhi3
|
||||
0x004897 __ashrhi3
|
||||
0x0048aa __udivhi3
|
||||
0x0048b6 __umodhi3
|
||||
0x0048c2 __divhi3
|
||||
0x0048dc __modhi3
|
||||
0x0048f6 __divmod_setup
|
||||
0x004929 __udivmod_core
|
||||
0x004947 __mulsi3
|
||||
0x004a00 __ashlsi3
|
||||
0x004a15 __lshrsi3
|
||||
0x004a2a __ashrsi3
|
||||
0x004a44 __udivmodsi_core
|
||||
0x004a7c __udivsi3
|
||||
0x004a90 __umodsi3
|
||||
0x004aa4 __divsi3
|
||||
0x004acb __modsi3
|
||||
0x004af2 __divmodsi_setup
|
||||
0x004b43 __divmoddi4_stash
|
||||
0x004b60 __retdi
|
||||
0x004b6d __ashldi3
|
||||
0x004b90 __lshrdi3
|
||||
0x004bb3 __ashrdi3
|
||||
0x004bd9 __muldi3
|
||||
0x004c40 __ucmpdi2
|
||||
0x004c69 __cmpdi2
|
||||
0x004ca0 __udivdi3
|
||||
0x004ca9 __umoddi3
|
||||
0x004cc2 __udivmoddi_core
|
||||
0x004d0f __divdi3
|
||||
0x004d2e __moddi3
|
||||
0x004d5b __absdi_a
|
||||
0x004d63 __absdi_b
|
||||
0x004d6b __negdi_a
|
||||
0x004d89 __negdi_b
|
||||
0x004da7 setjmp
|
||||
0x004dcf longjmp
|
||||
0x004df9 __umulhisi3_qsq
|
||||
0x0051f7 __rodata_start
|
||||
0x0051f7 __text_end
|
||||
0x005589 writeHex.digits
|
||||
0x0055a4 __mfs
|
||||
0x005684 stdin
|
||||
0x005688 stdout
|
||||
0x00568c stderr
|
||||
0x005690 __c_lconv
|
||||
0x0056c0 __init_array_end
|
||||
0x0056c0 __init_array_start
|
||||
0x0056c0 __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
0x00a000 argBuf
|
||||
0x00a100 argVec
|
||||
0x00a180 __indirTarget
|
||||
0x00a182 __bss_end
|
||||
0x00a182 __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x004d5b
|
||||
__absdi_b = 0x004d63
|
||||
__adddf3 = 0x003170
|
||||
__ashldi3 = 0x004b6d
|
||||
__ashlhi3 = 0x004878
|
||||
__ashlsi3 = 0x004a00
|
||||
__ashrdi3 = 0x004bb3
|
||||
__ashrhi3 = 0x004897
|
||||
__ashrsi3 = 0x004a2a
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a182
|
||||
__bss_lo16 = 0x00a000
|
||||
__bss_seg0_bank = 0x000000
|
||||
__bss_seg0_lo16 = 0x00a000
|
||||
__bss_seg0_size = 0x000182
|
||||
__bss_seg1_bank = 0x000000
|
||||
__bss_seg1_lo16 = 0x000000
|
||||
__bss_seg1_size = 0x000000
|
||||
__bss_seg2_bank = 0x000000
|
||||
__bss_seg2_lo16 = 0x000000
|
||||
__bss_seg2_size = 0x000000
|
||||
__bss_seg3_bank = 0x000000
|
||||
__bss_seg3_lo16 = 0x000000
|
||||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x000182
|
||||
__bss_start = 0x00a000
|
||||
__c_lconv = 0x005690
|
||||
__cmpdi2 = 0x004c69
|
||||
__divdi3 = 0x004d0f
|
||||
__divhi3 = 0x0048c2
|
||||
__divmod_setup = 0x0048f6
|
||||
__divmoddi4_stash = 0x004b43
|
||||
__divmodsi_setup = 0x004af2
|
||||
__divsi3 = 0x004aa4
|
||||
__fixdfsi = 0x004654
|
||||
__floatsidf = 0x0043b7
|
||||
__floatunsidf = 0x004535
|
||||
__getByte = 0x00139e
|
||||
__gnoCallNum = 0x001826
|
||||
__gnoGsosCall = 0x001811
|
||||
__gnoPBlock = 0x001828
|
||||
__gnoStartup = 0x00153e
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a182
|
||||
__indirTarget = 0x00a180
|
||||
__init_array_end = 0x0056c0
|
||||
__init_array_start = 0x0056c0
|
||||
__jsl_indir = 0x0047ff
|
||||
__lshrdi3 = 0x004b90
|
||||
__lshrhi3 = 0x004887
|
||||
__lshrsi3 = 0x004a15
|
||||
__mfs = 0x0055a4
|
||||
__moddi3 = 0x004d2e
|
||||
__modhi3 = 0x0048dc
|
||||
__modsi3 = 0x004acb
|
||||
__muldf3 = 0x003d34
|
||||
__muldi3 = 0x004bd9
|
||||
__mulhi3 = 0x004802
|
||||
__mulsi3 = 0x004947
|
||||
__negdi_a = 0x004d6b
|
||||
__negdi_b = 0x004d89
|
||||
__putByte = 0x001251
|
||||
__retdi = 0x004b60
|
||||
__rodata_end = 0x0056c0
|
||||
__rodata_start = 0x0051f7
|
||||
__start = 0x001000
|
||||
__subdf3 = 0x003cfa
|
||||
__text_end = 0x0051f7
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x004c40
|
||||
__udivdi3 = 0x004ca0
|
||||
__udivhi3 = 0x0048aa
|
||||
__udivmod_core = 0x004929
|
||||
__udivmoddi_core = 0x004cc2
|
||||
__udivmodsi_core = 0x004a44
|
||||
__udivsi3 = 0x004a7c
|
||||
__umoddi3 = 0x004ca9
|
||||
__umodhi3 = 0x0048b6
|
||||
__umodsi3 = 0x004a90
|
||||
__umulhisi3 = 0x004821
|
||||
__umulhisi3_qsq = 0x004df9
|
||||
_exit = 0x0017e0
|
||||
argBuf = 0x00a000
|
||||
argVec = 0x00a100
|
||||
fgetc = 0x002c34
|
||||
fgets = 0x00306c
|
||||
gsosRead = 0x00123b
|
||||
longjmp = 0x004dcf
|
||||
main = 0x001071
|
||||
memset = 0x001833
|
||||
printf = 0x002baf
|
||||
puts = 0x001891
|
||||
setjmp = 0x004da7
|
||||
stderr = 0x00568c
|
||||
stdin = 0x005684
|
||||
stdout = 0x005688
|
||||
vprintf = 0x00194b
|
||||
writeHex = 0x002a20
|
||||
writeHex.digits = 0x005589
|
||||
writeUDec = 0x0028e0
|
||||
writeULong = 0x00276e
|
||||
BIN
demos/gnoCat.o
Normal file
BIN
demos/gnoCat.o
Normal file
Binary file not shown.
BIN
demos/gnoCat.omf
Normal file
BIN
demos/gnoCat.omf
Normal file
Binary file not shown.
BIN
demos/gnoCat.reloc
Normal file
BIN
demos/gnoCat.reloc
Normal file
Binary file not shown.
BIN
demos/gnoFile.bin
Normal file
BIN
demos/gnoFile.bin
Normal file
Binary file not shown.
31
demos/gnoFile.c
Normal file
31
demos/gnoFile.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// gnoFile.c — buffered FILE* file I/O on GNO/ME. Writes a file, reopens
|
||||
// it, reads it back, and verifies the content round-trips byte-for-byte.
|
||||
// Proves fopen/fwrite/fread/fclose route to real GS/OS files via libc's
|
||||
// FILE* layer + GNO's inline-form GS/OS dispatch.
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *path = "llvm816.txt";
|
||||
const char *msg = "written by llvm816 under GNO";
|
||||
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) { printf("fopen(w) failed\n"); return 1; }
|
||||
fwrite(msg, 1, strlen(msg), f);
|
||||
fclose(f);
|
||||
|
||||
char buf[64];
|
||||
f = fopen(path, "r");
|
||||
if (!f) { printf("fopen(r) failed\n"); return 1; }
|
||||
size_t n = fread(buf, 1, sizeof(buf) - 1, f);
|
||||
fclose(f);
|
||||
buf[n] = 0;
|
||||
|
||||
int ok = (n == strlen(msg)) && (strcmp(buf, msg) == 0);
|
||||
printf("read %d bytes, content %s\n", (int)n, ok ? "OK" : "MISMATCH");
|
||||
|
||||
*(volatile uint16_t *)0x025000UL = ok ? 0xC0DE : 0xBAD0;
|
||||
for (volatile unsigned long i = 0; i < 400000UL; i++) {}
|
||||
return 0;
|
||||
}
|
||||
269
demos/gnoFile.map
Normal file
269
demos/gnoFile.map
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x006f8a ( 24458 bytes)
|
||||
.rodata : 0x006f8a .. 0x007622 ( 1688 bytes)
|
||||
.bss : 0x00a000 .. 0x00a402 ( 1026 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
113 /home/scott/claude/llvm816/runtime/crt0Gno.o
|
||||
737 /home/scott/claude/llvm816/demos/gnoFile.o
|
||||
3444 /home/scott/claude/llvm816/runtime/libcGno.o
|
||||
925 /home/scott/claude/llvm816/runtime/gnoKernel.o
|
||||
34 /home/scott/claude/llvm816/runtime/gnoGsos.o
|
||||
32139 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9073 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
2552 /home/scott/claude/llvm816/runtime/libgcc.o
|
||||
|
||||
# global symbols (sorted by address)
|
||||
0x000000 __bss_bank
|
||||
0x000000 __bss_seg0_bank
|
||||
0x000000 __bss_seg1_bank
|
||||
0x000000 __bss_seg1_lo16
|
||||
0x000000 __bss_seg1_size
|
||||
0x000000 __bss_seg2_bank
|
||||
0x000000 __bss_seg2_lo16
|
||||
0x000000 __bss_seg2_size
|
||||
0x000000 __bss_seg3_bank
|
||||
0x000000 __bss_seg3_lo16
|
||||
0x000000 __bss_seg3_size
|
||||
0x000402 __bss_seg0_size
|
||||
0x000402 __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x001071 main
|
||||
0x001352 gsosCreate
|
||||
0x001368 gsosOpen
|
||||
0x00137e gsosRead
|
||||
0x001394 gsosWrite
|
||||
0x0013aa gsosClose
|
||||
0x0013c0 gsosGetEOF
|
||||
0x0013d6 gsosSetEOF
|
||||
0x0013ec gsosSetMark
|
||||
0x001402 __putByte
|
||||
0x00154f __putByteErr
|
||||
0x00169c __gnoStartup
|
||||
0x00193e _exit
|
||||
0x00196f __gnoGsosCall
|
||||
0x001984 __gnoCallNum
|
||||
0x001986 __gnoPBlock
|
||||
0x001991 memset
|
||||
0x0019ef memcmp
|
||||
0x001a9c puts
|
||||
0x001b56 vprintf
|
||||
0x002977 writeULong
|
||||
0x002ae9 writeUDec
|
||||
0x002c29 writeHex
|
||||
0x002db8 printf
|
||||
0x002e3d putcharStd
|
||||
0x002e83 fclose
|
||||
0x0030d3 fwrite
|
||||
0x00389a fopen
|
||||
0x00489c fread
|
||||
0x004f03 __adddf3
|
||||
0x005a8d __subdf3
|
||||
0x005ac7 __muldf3
|
||||
0x00614a __floatsidf
|
||||
0x0062c8 __floatunsidf
|
||||
0x0063e7 __fixdfsi
|
||||
0x006592 __jsl_indir
|
||||
0x006595 __mulhi3
|
||||
0x0065b4 __umulhisi3
|
||||
0x00660b __ashlhi3
|
||||
0x00661a __lshrhi3
|
||||
0x00662a __ashrhi3
|
||||
0x00663d __udivhi3
|
||||
0x006649 __umodhi3
|
||||
0x006655 __divhi3
|
||||
0x00666f __modhi3
|
||||
0x006689 __divmod_setup
|
||||
0x0066bc __udivmod_core
|
||||
0x0066da __mulsi3
|
||||
0x006793 __ashlsi3
|
||||
0x0067a8 __lshrsi3
|
||||
0x0067bd __ashrsi3
|
||||
0x0067d7 __udivmodsi_core
|
||||
0x00680f __udivsi3
|
||||
0x006823 __umodsi3
|
||||
0x006837 __divsi3
|
||||
0x00685e __modsi3
|
||||
0x006885 __divmodsi_setup
|
||||
0x0068d6 __divmoddi4_stash
|
||||
0x0068f3 __retdi
|
||||
0x006900 __ashldi3
|
||||
0x006923 __lshrdi3
|
||||
0x006946 __ashrdi3
|
||||
0x00696c __muldi3
|
||||
0x0069d3 __ucmpdi2
|
||||
0x0069fc __cmpdi2
|
||||
0x006a33 __udivdi3
|
||||
0x006a3c __umoddi3
|
||||
0x006a55 __udivmoddi_core
|
||||
0x006aa2 __divdi3
|
||||
0x006ac1 __moddi3
|
||||
0x006aee __absdi_a
|
||||
0x006af6 __absdi_b
|
||||
0x006afe __negdi_a
|
||||
0x006b1c __negdi_b
|
||||
0x006b3a setjmp
|
||||
0x006b62 longjmp
|
||||
0x006b8c __umulhisi3_qsq
|
||||
0x006f8a __rodata_start
|
||||
0x006f8a __text_end
|
||||
0x00736f writeHex.digits
|
||||
0x00738a __monthDays
|
||||
0x007506 __mfs
|
||||
0x0075e6 stdin
|
||||
0x0075ea stdout
|
||||
0x0075ee stderr
|
||||
0x0075f2 __c_lconv
|
||||
0x007622 __init_array_end
|
||||
0x007622 __init_array_start
|
||||
0x007622 __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
0x00a000 argBuf
|
||||
0x00a100 argVec
|
||||
0x00a180 freeList
|
||||
0x00a184 bumpPtr
|
||||
0x00a188 heapEnd
|
||||
0x00a18c __atexitFn
|
||||
0x00a190 errno
|
||||
0x00a192 __toolboxInited
|
||||
0x00a194 __vblPrev
|
||||
0x00a196 __vblBase
|
||||
0x00a19a __mfsReg
|
||||
0x00a2ba __quickFn
|
||||
0x00a2be __gsosPathBuf
|
||||
0x00a3c0 __sigHandlers
|
||||
0x00a400 __indirTarget
|
||||
0x00a402 __bss_end
|
||||
0x00a402 __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x006aee
|
||||
__absdi_b = 0x006af6
|
||||
__adddf3 = 0x004f03
|
||||
__ashldi3 = 0x006900
|
||||
__ashlhi3 = 0x00660b
|
||||
__ashlsi3 = 0x006793
|
||||
__ashrdi3 = 0x006946
|
||||
__ashrhi3 = 0x00662a
|
||||
__ashrsi3 = 0x0067bd
|
||||
__atexitFn = 0x00a18c
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a402
|
||||
__bss_lo16 = 0x00a000
|
||||
__bss_seg0_bank = 0x000000
|
||||
__bss_seg0_lo16 = 0x00a000
|
||||
__bss_seg0_size = 0x000402
|
||||
__bss_seg1_bank = 0x000000
|
||||
__bss_seg1_lo16 = 0x000000
|
||||
__bss_seg1_size = 0x000000
|
||||
__bss_seg2_bank = 0x000000
|
||||
__bss_seg2_lo16 = 0x000000
|
||||
__bss_seg2_size = 0x000000
|
||||
__bss_seg3_bank = 0x000000
|
||||
__bss_seg3_lo16 = 0x000000
|
||||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x000402
|
||||
__bss_start = 0x00a000
|
||||
__c_lconv = 0x0075f2
|
||||
__cmpdi2 = 0x0069fc
|
||||
__divdi3 = 0x006aa2
|
||||
__divhi3 = 0x006655
|
||||
__divmod_setup = 0x006689
|
||||
__divmoddi4_stash = 0x0068d6
|
||||
__divmodsi_setup = 0x006885
|
||||
__divsi3 = 0x006837
|
||||
__fixdfsi = 0x0063e7
|
||||
__floatsidf = 0x00614a
|
||||
__floatunsidf = 0x0062c8
|
||||
__gnoCallNum = 0x001984
|
||||
__gnoGsosCall = 0x00196f
|
||||
__gnoPBlock = 0x001986
|
||||
__gnoStartup = 0x00169c
|
||||
__gsosPathBuf = 0x00a2be
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a402
|
||||
__indirTarget = 0x00a400
|
||||
__init_array_end = 0x007622
|
||||
__init_array_start = 0x007622
|
||||
__jsl_indir = 0x006592
|
||||
__lshrdi3 = 0x006923
|
||||
__lshrhi3 = 0x00661a
|
||||
__lshrsi3 = 0x0067a8
|
||||
__mfs = 0x007506
|
||||
__mfsReg = 0x00a19a
|
||||
__moddi3 = 0x006ac1
|
||||
__modhi3 = 0x00666f
|
||||
__modsi3 = 0x00685e
|
||||
__monthDays = 0x00738a
|
||||
__muldf3 = 0x005ac7
|
||||
__muldi3 = 0x00696c
|
||||
__mulhi3 = 0x006595
|
||||
__mulsi3 = 0x0066da
|
||||
__negdi_a = 0x006afe
|
||||
__negdi_b = 0x006b1c
|
||||
__putByte = 0x001402
|
||||
__putByteErr = 0x00154f
|
||||
__quickFn = 0x00a2ba
|
||||
__retdi = 0x0068f3
|
||||
__rodata_end = 0x007622
|
||||
__rodata_start = 0x006f8a
|
||||
__sigHandlers = 0x00a3c0
|
||||
__start = 0x001000
|
||||
__subdf3 = 0x005a8d
|
||||
__text_end = 0x006f8a
|
||||
__text_start = 0x001000
|
||||
__toolboxInited = 0x00a192
|
||||
__ucmpdi2 = 0x0069d3
|
||||
__udivdi3 = 0x006a33
|
||||
__udivhi3 = 0x00663d
|
||||
__udivmod_core = 0x0066bc
|
||||
__udivmoddi_core = 0x006a55
|
||||
__udivmodsi_core = 0x0067d7
|
||||
__udivsi3 = 0x00680f
|
||||
__umoddi3 = 0x006a3c
|
||||
__umodhi3 = 0x006649
|
||||
__umodsi3 = 0x006823
|
||||
__umulhisi3 = 0x0065b4
|
||||
__umulhisi3_qsq = 0x006b8c
|
||||
__vblBase = 0x00a196
|
||||
__vblPrev = 0x00a194
|
||||
_exit = 0x00193e
|
||||
argBuf = 0x00a000
|
||||
argVec = 0x00a100
|
||||
bumpPtr = 0x00a184
|
||||
errno = 0x00a190
|
||||
fclose = 0x002e83
|
||||
fopen = 0x00389a
|
||||
fread = 0x00489c
|
||||
freeList = 0x00a180
|
||||
fwrite = 0x0030d3
|
||||
gsosClose = 0x0013aa
|
||||
gsosCreate = 0x001352
|
||||
gsosGetEOF = 0x0013c0
|
||||
gsosOpen = 0x001368
|
||||
gsosRead = 0x00137e
|
||||
gsosSetEOF = 0x0013d6
|
||||
gsosSetMark = 0x0013ec
|
||||
gsosWrite = 0x001394
|
||||
heapEnd = 0x00a188
|
||||
longjmp = 0x006b62
|
||||
main = 0x001071
|
||||
memcmp = 0x0019ef
|
||||
memset = 0x001991
|
||||
printf = 0x002db8
|
||||
putcharStd = 0x002e3d
|
||||
puts = 0x001a9c
|
||||
setjmp = 0x006b3a
|
||||
stderr = 0x0075ee
|
||||
stdin = 0x0075e6
|
||||
stdout = 0x0075ea
|
||||
vprintf = 0x001b56
|
||||
writeHex = 0x002c29
|
||||
writeHex.digits = 0x00736f
|
||||
writeUDec = 0x002ae9
|
||||
writeULong = 0x002977
|
||||
BIN
demos/gnoFile.o
Normal file
BIN
demos/gnoFile.o
Normal file
Binary file not shown.
BIN
demos/gnoFile.omf
Normal file
BIN
demos/gnoFile.omf
Normal file
Binary file not shown.
BIN
demos/gnoFile.reloc
Normal file
BIN
demos/gnoFile.reloc
Normal file
Binary file not shown.
BIN
demos/gnoFmt.bin
Normal file
BIN
demos/gnoFmt.bin
Normal file
Binary file not shown.
21
demos/gnoFmt.c
Normal file
21
demos/gnoFmt.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// gnoFmt.c — snprintf format checks (stack %s was the bug).
|
||||
// m0 = "%s" of stack str -> 0x4241 ("AB")
|
||||
// m1 = "%s" of literal -> 0x5857 ("WX")
|
||||
// m2 = "%ld" of 42L -> 0x3234 ("42") (original slot-alias case)
|
||||
// m3 = "%d" of 1234 -> 0x3231 ("12")
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
static uint16_t two(const char *s) { return (uint16_t)((uint8_t)s[0] | ((uint8_t)s[1] << 8)); }
|
||||
int main(int argc, char **argv) {
|
||||
char s[8]; s[0]='A'; s[1]='B'; s[2]='C'; s[3]='D'; s[4]=0;
|
||||
char o0[16]; snprintf(o0, sizeof o0, "%s", s);
|
||||
char o1[16]; snprintf(o1, sizeof o1, "%s", "WXYZ");
|
||||
char o2[16]; snprintf(o2, sizeof o2, "%ld", 42L);
|
||||
char o3[16]; snprintf(o3, sizeof o3, "%d", 1234);
|
||||
*(volatile uint16_t *)0x025000UL = two(o0);
|
||||
*(volatile uint16_t *)0x025002UL = two(o1);
|
||||
*(volatile uint16_t *)0x025004UL = two(o2);
|
||||
*(volatile uint16_t *)0x025006UL = two(o3);
|
||||
for (volatile unsigned long i = 0; i < 300000UL; i++) {}
|
||||
return 0;
|
||||
}
|
||||
203
demos/gnoFmt.map
Normal file
203
demos/gnoFmt.map
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x0055fe ( 17918 bytes)
|
||||
.rodata : 0x0055fe .. 0x005620 ( 34 bytes)
|
||||
.bss : 0x00a000 .. 0x00a18e ( 398 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
113 /home/scott/claude/llvm816/runtime/crt0Gno.o
|
||||
628 /home/scott/claude/llvm816/demos/gnoFmt.o
|
||||
3444 /home/scott/claude/llvm816/runtime/libcGno.o
|
||||
925 /home/scott/claude/llvm816/runtime/gnoKernel.o
|
||||
34 /home/scott/claude/llvm816/runtime/gnoGsos.o
|
||||
32173 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9075 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
2552 /home/scott/claude/llvm816/runtime/libgcc.o
|
||||
|
||||
# global symbols (sorted by address)
|
||||
0x000000 __bss_bank
|
||||
0x000000 __bss_seg0_bank
|
||||
0x000000 __bss_seg1_bank
|
||||
0x000000 __bss_seg1_lo16
|
||||
0x000000 __bss_seg1_size
|
||||
0x000000 __bss_seg2_bank
|
||||
0x000000 __bss_seg2_lo16
|
||||
0x000000 __bss_seg2_size
|
||||
0x000000 __bss_seg3_bank
|
||||
0x000000 __bss_seg3_lo16
|
||||
0x000000 __bss_seg3_size
|
||||
0x00018e __bss_seg0_size
|
||||
0x00018e __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x001071 main
|
||||
0x0012e5 __gnoStartup
|
||||
0x001587 _exit
|
||||
0x0015b8 __gnoGsosCall
|
||||
0x0015cd __gnoCallNum
|
||||
0x0015cf __gnoPBlock
|
||||
0x0015da memset
|
||||
0x001638 snprintf
|
||||
0x001788 format
|
||||
0x002f1d emitULong
|
||||
0x0031f0 emitUDec
|
||||
0x00348a emitHex
|
||||
0x0036f5 __adddf3
|
||||
0x00427f __subdf3
|
||||
0x0042b9 __muldf3
|
||||
0x00493c __floatunsidf
|
||||
0x004a5b __fixdfsi
|
||||
0x004c06 __jsl_indir
|
||||
0x004c09 __mulhi3
|
||||
0x004c28 __umulhisi3
|
||||
0x004c7f __ashlhi3
|
||||
0x004c8e __lshrhi3
|
||||
0x004c9e __ashrhi3
|
||||
0x004cb1 __udivhi3
|
||||
0x004cbd __umodhi3
|
||||
0x004cc9 __divhi3
|
||||
0x004ce3 __modhi3
|
||||
0x004cfd __divmod_setup
|
||||
0x004d30 __udivmod_core
|
||||
0x004d4e __mulsi3
|
||||
0x004e07 __ashlsi3
|
||||
0x004e1c __lshrsi3
|
||||
0x004e31 __ashrsi3
|
||||
0x004e4b __udivmodsi_core
|
||||
0x004e83 __udivsi3
|
||||
0x004e97 __umodsi3
|
||||
0x004eab __divsi3
|
||||
0x004ed2 __modsi3
|
||||
0x004ef9 __divmodsi_setup
|
||||
0x004f4a __divmoddi4_stash
|
||||
0x004f67 __retdi
|
||||
0x004f74 __ashldi3
|
||||
0x004f97 __lshrdi3
|
||||
0x004fba __ashrdi3
|
||||
0x004fe0 __muldi3
|
||||
0x005047 __ucmpdi2
|
||||
0x005070 __cmpdi2
|
||||
0x0050a7 __udivdi3
|
||||
0x0050b0 __umoddi3
|
||||
0x0050c9 __udivmoddi_core
|
||||
0x005116 __divdi3
|
||||
0x005135 __moddi3
|
||||
0x005162 __absdi_a
|
||||
0x00516a __absdi_b
|
||||
0x005172 __negdi_a
|
||||
0x005190 __negdi_b
|
||||
0x0051ae setjmp
|
||||
0x0051d6 longjmp
|
||||
0x005200 __umulhisi3_qsq
|
||||
0x0055fe __rodata_start
|
||||
0x0055fe __text_end
|
||||
0x005608 emitHex.digits
|
||||
0x005620 __init_array_end
|
||||
0x005620 __init_array_start
|
||||
0x005620 __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
0x00a000 argBuf
|
||||
0x00a100 argVec
|
||||
0x00a180 gCur
|
||||
0x00a184 gEnd
|
||||
0x00a188 gTotal
|
||||
0x00a18c __indirTarget
|
||||
0x00a18e __bss_end
|
||||
0x00a18e __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x005162
|
||||
__absdi_b = 0x00516a
|
||||
__adddf3 = 0x0036f5
|
||||
__ashldi3 = 0x004f74
|
||||
__ashlhi3 = 0x004c7f
|
||||
__ashlsi3 = 0x004e07
|
||||
__ashrdi3 = 0x004fba
|
||||
__ashrhi3 = 0x004c9e
|
||||
__ashrsi3 = 0x004e31
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a18e
|
||||
__bss_lo16 = 0x00a000
|
||||
__bss_seg0_bank = 0x000000
|
||||
__bss_seg0_lo16 = 0x00a000
|
||||
__bss_seg0_size = 0x00018e
|
||||
__bss_seg1_bank = 0x000000
|
||||
__bss_seg1_lo16 = 0x000000
|
||||
__bss_seg1_size = 0x000000
|
||||
__bss_seg2_bank = 0x000000
|
||||
__bss_seg2_lo16 = 0x000000
|
||||
__bss_seg2_size = 0x000000
|
||||
__bss_seg3_bank = 0x000000
|
||||
__bss_seg3_lo16 = 0x000000
|
||||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x00018e
|
||||
__bss_start = 0x00a000
|
||||
__cmpdi2 = 0x005070
|
||||
__divdi3 = 0x005116
|
||||
__divhi3 = 0x004cc9
|
||||
__divmod_setup = 0x004cfd
|
||||
__divmoddi4_stash = 0x004f4a
|
||||
__divmodsi_setup = 0x004ef9
|
||||
__divsi3 = 0x004eab
|
||||
__fixdfsi = 0x004a5b
|
||||
__floatunsidf = 0x00493c
|
||||
__gnoCallNum = 0x0015cd
|
||||
__gnoGsosCall = 0x0015b8
|
||||
__gnoPBlock = 0x0015cf
|
||||
__gnoStartup = 0x0012e5
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a18e
|
||||
__indirTarget = 0x00a18c
|
||||
__init_array_end = 0x005620
|
||||
__init_array_start = 0x005620
|
||||
__jsl_indir = 0x004c06
|
||||
__lshrdi3 = 0x004f97
|
||||
__lshrhi3 = 0x004c8e
|
||||
__lshrsi3 = 0x004e1c
|
||||
__moddi3 = 0x005135
|
||||
__modhi3 = 0x004ce3
|
||||
__modsi3 = 0x004ed2
|
||||
__muldf3 = 0x0042b9
|
||||
__muldi3 = 0x004fe0
|
||||
__mulhi3 = 0x004c09
|
||||
__mulsi3 = 0x004d4e
|
||||
__negdi_a = 0x005172
|
||||
__negdi_b = 0x005190
|
||||
__retdi = 0x004f67
|
||||
__rodata_end = 0x005620
|
||||
__rodata_start = 0x0055fe
|
||||
__start = 0x001000
|
||||
__subdf3 = 0x00427f
|
||||
__text_end = 0x0055fe
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x005047
|
||||
__udivdi3 = 0x0050a7
|
||||
__udivhi3 = 0x004cb1
|
||||
__udivmod_core = 0x004d30
|
||||
__udivmoddi_core = 0x0050c9
|
||||
__udivmodsi_core = 0x004e4b
|
||||
__udivsi3 = 0x004e83
|
||||
__umoddi3 = 0x0050b0
|
||||
__umodhi3 = 0x004cbd
|
||||
__umodsi3 = 0x004e97
|
||||
__umulhisi3 = 0x004c28
|
||||
__umulhisi3_qsq = 0x005200
|
||||
_exit = 0x001587
|
||||
argBuf = 0x00a000
|
||||
argVec = 0x00a100
|
||||
emitHex = 0x00348a
|
||||
emitHex.digits = 0x005608
|
||||
emitUDec = 0x0031f0
|
||||
emitULong = 0x002f1d
|
||||
format = 0x001788
|
||||
gCur = 0x00a180
|
||||
gEnd = 0x00a184
|
||||
gTotal = 0x00a188
|
||||
longjmp = 0x0051d6
|
||||
main = 0x001071
|
||||
memset = 0x0015da
|
||||
setjmp = 0x0051ae
|
||||
snprintf = 0x001638
|
||||
BIN
demos/gnoFmt.o
Normal file
BIN
demos/gnoFmt.o
Normal file
Binary file not shown.
BIN
demos/gnoFmt.omf
Normal file
BIN
demos/gnoFmt.omf
Normal file
Binary file not shown.
BIN
demos/gnoFmt.reloc
Normal file
BIN
demos/gnoFmt.reloc
Normal file
Binary file not shown.
BIN
demos/gnoHello.bin
Normal file
BIN
demos/gnoHello.bin
Normal file
Binary file not shown.
14
demos/gnoHello.c
Normal file
14
demos/gnoHello.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// gnoHello.c — GNO/ME shell command demo: prints a greeting + formatted
|
||||
// output via standard stdio (libc printf/puts over the GNO console).
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
puts("Hello from llvm816 on GNO/ME!");
|
||||
printf("argc=%d argv0=%s\n", argc, (argc > 0 && argv) ? argv[0] : "(none)");
|
||||
printf("sum 1..10 = %d, hex = %x\n", 55, 0xC0DE);
|
||||
|
||||
*(volatile uint16_t *)0x025000UL = 0xC0DE; // harness marker
|
||||
for (volatile unsigned long i = 0; i < 600000UL; i++) {}
|
||||
return 0;
|
||||
}
|
||||
203
demos/gnoHello.map
Normal file
203
demos/gnoHello.map
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x004b2e ( 15150 bytes)
|
||||
.rodata : 0x004b2e .. 0x004f0b ( 989 bytes)
|
||||
.bss : 0x00a000 .. 0x00a182 ( 386 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
113 /home/scott/claude/llvm816/runtime/crt0Gno.o
|
||||
501 /home/scott/claude/llvm816/demos/gnoHello.o
|
||||
3444 /home/scott/claude/llvm816/runtime/libcGno.o
|
||||
925 /home/scott/claude/llvm816/runtime/gnoKernel.o
|
||||
34 /home/scott/claude/llvm816/runtime/gnoGsos.o
|
||||
32139 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9073 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
2552 /home/scott/claude/llvm816/runtime/libgcc.o
|
||||
|
||||
# global symbols (sorted by address)
|
||||
0x000000 __bss_bank
|
||||
0x000000 __bss_seg0_bank
|
||||
0x000000 __bss_seg1_bank
|
||||
0x000000 __bss_seg1_lo16
|
||||
0x000000 __bss_seg1_size
|
||||
0x000000 __bss_seg2_bank
|
||||
0x000000 __bss_seg2_lo16
|
||||
0x000000 __bss_seg2_size
|
||||
0x000000 __bss_seg3_bank
|
||||
0x000000 __bss_seg3_lo16
|
||||
0x000000 __bss_seg3_size
|
||||
0x000182 __bss_seg0_size
|
||||
0x000182 __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x001071 main
|
||||
0x001266 __putByte
|
||||
0x0013b3 __gnoStartup
|
||||
0x001655 _exit
|
||||
0x001686 __gnoGsosCall
|
||||
0x00169b __gnoCallNum
|
||||
0x00169d __gnoPBlock
|
||||
0x0016a8 memset
|
||||
0x001706 puts
|
||||
0x0017c0 vprintf
|
||||
0x0025e1 writeULong
|
||||
0x002753 writeUDec
|
||||
0x002893 writeHex
|
||||
0x002a22 printf
|
||||
0x002aa7 __adddf3
|
||||
0x003631 __subdf3
|
||||
0x00366b __muldf3
|
||||
0x003cee __floatsidf
|
||||
0x003e6c __floatunsidf
|
||||
0x003f8b __fixdfsi
|
||||
0x004136 __jsl_indir
|
||||
0x004139 __mulhi3
|
||||
0x004158 __umulhisi3
|
||||
0x0041af __ashlhi3
|
||||
0x0041be __lshrhi3
|
||||
0x0041ce __ashrhi3
|
||||
0x0041e1 __udivhi3
|
||||
0x0041ed __umodhi3
|
||||
0x0041f9 __divhi3
|
||||
0x004213 __modhi3
|
||||
0x00422d __divmod_setup
|
||||
0x004260 __udivmod_core
|
||||
0x00427e __mulsi3
|
||||
0x004337 __ashlsi3
|
||||
0x00434c __lshrsi3
|
||||
0x004361 __ashrsi3
|
||||
0x00437b __udivmodsi_core
|
||||
0x0043b3 __udivsi3
|
||||
0x0043c7 __umodsi3
|
||||
0x0043db __divsi3
|
||||
0x004402 __modsi3
|
||||
0x004429 __divmodsi_setup
|
||||
0x00447a __divmoddi4_stash
|
||||
0x004497 __retdi
|
||||
0x0044a4 __ashldi3
|
||||
0x0044c7 __lshrdi3
|
||||
0x0044ea __ashrdi3
|
||||
0x004510 __muldi3
|
||||
0x004577 __ucmpdi2
|
||||
0x0045a0 __cmpdi2
|
||||
0x0045d7 __udivdi3
|
||||
0x0045e0 __umoddi3
|
||||
0x0045f9 __udivmoddi_core
|
||||
0x004646 __divdi3
|
||||
0x004665 __moddi3
|
||||
0x004692 __absdi_a
|
||||
0x00469a __absdi_b
|
||||
0x0046a2 __negdi_a
|
||||
0x0046c0 __negdi_b
|
||||
0x0046de setjmp
|
||||
0x004706 longjmp
|
||||
0x004730 __umulhisi3_qsq
|
||||
0x004b2e __rodata_start
|
||||
0x004b2e __text_end
|
||||
0x004ef0 writeHex.digits
|
||||
0x004f0b __init_array_end
|
||||
0x004f0b __init_array_start
|
||||
0x004f0b __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
0x00a000 argBuf
|
||||
0x00a100 argVec
|
||||
0x00a180 __indirTarget
|
||||
0x00a182 __bss_end
|
||||
0x00a182 __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x004692
|
||||
__absdi_b = 0x00469a
|
||||
__adddf3 = 0x002aa7
|
||||
__ashldi3 = 0x0044a4
|
||||
__ashlhi3 = 0x0041af
|
||||
__ashlsi3 = 0x004337
|
||||
__ashrdi3 = 0x0044ea
|
||||
__ashrhi3 = 0x0041ce
|
||||
__ashrsi3 = 0x004361
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a182
|
||||
__bss_lo16 = 0x00a000
|
||||
__bss_seg0_bank = 0x000000
|
||||
__bss_seg0_lo16 = 0x00a000
|
||||
__bss_seg0_size = 0x000182
|
||||
__bss_seg1_bank = 0x000000
|
||||
__bss_seg1_lo16 = 0x000000
|
||||
__bss_seg1_size = 0x000000
|
||||
__bss_seg2_bank = 0x000000
|
||||
__bss_seg2_lo16 = 0x000000
|
||||
__bss_seg2_size = 0x000000
|
||||
__bss_seg3_bank = 0x000000
|
||||
__bss_seg3_lo16 = 0x000000
|
||||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x000182
|
||||
__bss_start = 0x00a000
|
||||
__cmpdi2 = 0x0045a0
|
||||
__divdi3 = 0x004646
|
||||
__divhi3 = 0x0041f9
|
||||
__divmod_setup = 0x00422d
|
||||
__divmoddi4_stash = 0x00447a
|
||||
__divmodsi_setup = 0x004429
|
||||
__divsi3 = 0x0043db
|
||||
__fixdfsi = 0x003f8b
|
||||
__floatsidf = 0x003cee
|
||||
__floatunsidf = 0x003e6c
|
||||
__gnoCallNum = 0x00169b
|
||||
__gnoGsosCall = 0x001686
|
||||
__gnoPBlock = 0x00169d
|
||||
__gnoStartup = 0x0013b3
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a182
|
||||
__indirTarget = 0x00a180
|
||||
__init_array_end = 0x004f0b
|
||||
__init_array_start = 0x004f0b
|
||||
__jsl_indir = 0x004136
|
||||
__lshrdi3 = 0x0044c7
|
||||
__lshrhi3 = 0x0041be
|
||||
__lshrsi3 = 0x00434c
|
||||
__moddi3 = 0x004665
|
||||
__modhi3 = 0x004213
|
||||
__modsi3 = 0x004402
|
||||
__muldf3 = 0x00366b
|
||||
__muldi3 = 0x004510
|
||||
__mulhi3 = 0x004139
|
||||
__mulsi3 = 0x00427e
|
||||
__negdi_a = 0x0046a2
|
||||
__negdi_b = 0x0046c0
|
||||
__putByte = 0x001266
|
||||
__retdi = 0x004497
|
||||
__rodata_end = 0x004f0b
|
||||
__rodata_start = 0x004b2e
|
||||
__start = 0x001000
|
||||
__subdf3 = 0x003631
|
||||
__text_end = 0x004b2e
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x004577
|
||||
__udivdi3 = 0x0045d7
|
||||
__udivhi3 = 0x0041e1
|
||||
__udivmod_core = 0x004260
|
||||
__udivmoddi_core = 0x0045f9
|
||||
__udivmodsi_core = 0x00437b
|
||||
__udivsi3 = 0x0043b3
|
||||
__umoddi3 = 0x0045e0
|
||||
__umodhi3 = 0x0041ed
|
||||
__umodsi3 = 0x0043c7
|
||||
__umulhisi3 = 0x004158
|
||||
__umulhisi3_qsq = 0x004730
|
||||
_exit = 0x001655
|
||||
argBuf = 0x00a000
|
||||
argVec = 0x00a100
|
||||
longjmp = 0x004706
|
||||
main = 0x001071
|
||||
memset = 0x0016a8
|
||||
printf = 0x002a22
|
||||
puts = 0x001706
|
||||
setjmp = 0x0046de
|
||||
vprintf = 0x0017c0
|
||||
writeHex = 0x002893
|
||||
writeHex.digits = 0x004ef0
|
||||
writeUDec = 0x002753
|
||||
writeULong = 0x0025e1
|
||||
BIN
demos/gnoHello.o
Normal file
BIN
demos/gnoHello.o
Normal file
Binary file not shown.
BIN
demos/gnoHello.omf
Normal file
BIN
demos/gnoHello.omf
Normal file
Binary file not shown.
BIN
demos/gnoHello.reloc
Normal file
BIN
demos/gnoHello.reloc
Normal file
Binary file not shown.
BIN
demos/gnoStdin.bin
Normal file
BIN
demos/gnoStdin.bin
Normal file
Binary file not shown.
23
demos/gnoStdin.c
Normal file
23
demos/gnoStdin.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// gnoStdin.c — stdin verification, now with a printf BEFORE the read
|
||||
// (mirroring gnoCat) to test whether prior stdout output corrupts fgets.
|
||||
// 0xC0DE = exact "FILE-STDIN-OK"; 0xBAD1 = other; 0xBAD0 = EOF.
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
int main(int argc, char **argv) {
|
||||
char line[80];
|
||||
line[0] = 0;
|
||||
printf("Type a line:\n"); // <-- prior stdout write, like gnoCat
|
||||
char *r = fgets(line, sizeof(line), stdin);
|
||||
size_t n = strlen(line);
|
||||
while (n && (line[n-1] == '\n' || line[n-1] == '\r')) line[--n] = 0;
|
||||
uint16_t mark;
|
||||
if (r && strcmp(line, "FILE-STDIN-OK") == 0) mark = 0xC0DE;
|
||||
else if (r && n > 0) mark = 0xBAD1;
|
||||
else mark = 0xBAD0;
|
||||
*(volatile uint16_t *)0x025000UL = mark;
|
||||
*(volatile uint16_t *)0x025002UL = (uint16_t)n;
|
||||
*(volatile uint16_t *)0x025004UL = (uint16_t)(uint8_t)line[0];
|
||||
for (volatile unsigned long i = 0; i < 300000UL; i++) {}
|
||||
return 0;
|
||||
}
|
||||
201
demos/gnoStdin.map
Normal file
201
demos/gnoStdin.map
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x002a9c ( 6812 bytes)
|
||||
.rodata : 0x002a9c .. 0x002f5f ( 1219 bytes)
|
||||
.bss : 0x00a000 .. 0x00a182 ( 386 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
113 /home/scott/claude/llvm816/runtime/crt0Gno.o
|
||||
802 /home/scott/claude/llvm816/demos/gnoStdin.o
|
||||
3444 /home/scott/claude/llvm816/runtime/libcGno.o
|
||||
925 /home/scott/claude/llvm816/runtime/gnoKernel.o
|
||||
34 /home/scott/claude/llvm816/runtime/gnoGsos.o
|
||||
32139 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9073 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
2552 /home/scott/claude/llvm816/runtime/libgcc.o
|
||||
|
||||
# global symbols (sorted by address)
|
||||
0x000000 __bss_bank
|
||||
0x000000 __bss_seg0_bank
|
||||
0x000000 __bss_seg1_bank
|
||||
0x000000 __bss_seg1_lo16
|
||||
0x000000 __bss_seg1_size
|
||||
0x000000 __bss_seg2_bank
|
||||
0x000000 __bss_seg2_lo16
|
||||
0x000000 __bss_seg2_size
|
||||
0x000000 __bss_seg3_bank
|
||||
0x000000 __bss_seg3_lo16
|
||||
0x000000 __bss_seg3_size
|
||||
0x000182 __bss_seg0_size
|
||||
0x000182 __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x001071 main
|
||||
0x001393 gsosRead
|
||||
0x0013a9 __putByte
|
||||
0x0014f6 __getByte
|
||||
0x001696 __gnoStartup
|
||||
0x001938 _exit
|
||||
0x001969 __gnoGsosCall
|
||||
0x00197e __gnoCallNum
|
||||
0x001980 __gnoPBlock
|
||||
0x00198b memcmp
|
||||
0x001a38 strlen
|
||||
0x001aae puts
|
||||
0x001b68 fgetc
|
||||
0x001fa0 fgets
|
||||
0x0020a4 __jsl_indir
|
||||
0x0020a7 __mulhi3
|
||||
0x0020c6 __umulhisi3
|
||||
0x00211d __ashlhi3
|
||||
0x00212c __lshrhi3
|
||||
0x00213c __ashrhi3
|
||||
0x00214f __udivhi3
|
||||
0x00215b __umodhi3
|
||||
0x002167 __divhi3
|
||||
0x002181 __modhi3
|
||||
0x00219b __divmod_setup
|
||||
0x0021ce __udivmod_core
|
||||
0x0021ec __mulsi3
|
||||
0x0022a5 __ashlsi3
|
||||
0x0022ba __lshrsi3
|
||||
0x0022cf __ashrsi3
|
||||
0x0022e9 __udivmodsi_core
|
||||
0x002321 __udivsi3
|
||||
0x002335 __umodsi3
|
||||
0x002349 __divsi3
|
||||
0x002370 __modsi3
|
||||
0x002397 __divmodsi_setup
|
||||
0x0023e8 __divmoddi4_stash
|
||||
0x002405 __retdi
|
||||
0x002412 __ashldi3
|
||||
0x002435 __lshrdi3
|
||||
0x002458 __ashrdi3
|
||||
0x00247e __muldi3
|
||||
0x0024e5 __ucmpdi2
|
||||
0x00250e __cmpdi2
|
||||
0x002545 __udivdi3
|
||||
0x00254e __umoddi3
|
||||
0x002567 __udivmoddi_core
|
||||
0x0025b4 __divdi3
|
||||
0x0025d3 __moddi3
|
||||
0x002600 __absdi_a
|
||||
0x002608 __absdi_b
|
||||
0x002610 __negdi_a
|
||||
0x00262e __negdi_b
|
||||
0x00264c setjmp
|
||||
0x002674 longjmp
|
||||
0x00269e __umulhisi3_qsq
|
||||
0x002a9c __rodata_start
|
||||
0x002a9c __text_end
|
||||
0x002e28 writeHex.digits
|
||||
0x002e43 __mfs
|
||||
0x002f23 stdin
|
||||
0x002f27 stdout
|
||||
0x002f2b stderr
|
||||
0x002f2f __c_lconv
|
||||
0x002f5f __init_array_end
|
||||
0x002f5f __init_array_start
|
||||
0x002f5f __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
0x00a000 argBuf
|
||||
0x00a100 argVec
|
||||
0x00a180 __indirTarget
|
||||
0x00a182 __bss_end
|
||||
0x00a182 __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x002600
|
||||
__absdi_b = 0x002608
|
||||
__ashldi3 = 0x002412
|
||||
__ashlhi3 = 0x00211d
|
||||
__ashlsi3 = 0x0022a5
|
||||
__ashrdi3 = 0x002458
|
||||
__ashrhi3 = 0x00213c
|
||||
__ashrsi3 = 0x0022cf
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a182
|
||||
__bss_lo16 = 0x00a000
|
||||
__bss_seg0_bank = 0x000000
|
||||
__bss_seg0_lo16 = 0x00a000
|
||||
__bss_seg0_size = 0x000182
|
||||
__bss_seg1_bank = 0x000000
|
||||
__bss_seg1_lo16 = 0x000000
|
||||
__bss_seg1_size = 0x000000
|
||||
__bss_seg2_bank = 0x000000
|
||||
__bss_seg2_lo16 = 0x000000
|
||||
__bss_seg2_size = 0x000000
|
||||
__bss_seg3_bank = 0x000000
|
||||
__bss_seg3_lo16 = 0x000000
|
||||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x000182
|
||||
__bss_start = 0x00a000
|
||||
__c_lconv = 0x002f2f
|
||||
__cmpdi2 = 0x00250e
|
||||
__divdi3 = 0x0025b4
|
||||
__divhi3 = 0x002167
|
||||
__divmod_setup = 0x00219b
|
||||
__divmoddi4_stash = 0x0023e8
|
||||
__divmodsi_setup = 0x002397
|
||||
__divsi3 = 0x002349
|
||||
__getByte = 0x0014f6
|
||||
__gnoCallNum = 0x00197e
|
||||
__gnoGsosCall = 0x001969
|
||||
__gnoPBlock = 0x001980
|
||||
__gnoStartup = 0x001696
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a182
|
||||
__indirTarget = 0x00a180
|
||||
__init_array_end = 0x002f5f
|
||||
__init_array_start = 0x002f5f
|
||||
__jsl_indir = 0x0020a4
|
||||
__lshrdi3 = 0x002435
|
||||
__lshrhi3 = 0x00212c
|
||||
__lshrsi3 = 0x0022ba
|
||||
__mfs = 0x002e43
|
||||
__moddi3 = 0x0025d3
|
||||
__modhi3 = 0x002181
|
||||
__modsi3 = 0x002370
|
||||
__muldi3 = 0x00247e
|
||||
__mulhi3 = 0x0020a7
|
||||
__mulsi3 = 0x0021ec
|
||||
__negdi_a = 0x002610
|
||||
__negdi_b = 0x00262e
|
||||
__putByte = 0x0013a9
|
||||
__retdi = 0x002405
|
||||
__rodata_end = 0x002f5f
|
||||
__rodata_start = 0x002a9c
|
||||
__start = 0x001000
|
||||
__text_end = 0x002a9c
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x0024e5
|
||||
__udivdi3 = 0x002545
|
||||
__udivhi3 = 0x00214f
|
||||
__udivmod_core = 0x0021ce
|
||||
__udivmoddi_core = 0x002567
|
||||
__udivmodsi_core = 0x0022e9
|
||||
__udivsi3 = 0x002321
|
||||
__umoddi3 = 0x00254e
|
||||
__umodhi3 = 0x00215b
|
||||
__umodsi3 = 0x002335
|
||||
__umulhisi3 = 0x0020c6
|
||||
__umulhisi3_qsq = 0x00269e
|
||||
_exit = 0x001938
|
||||
argBuf = 0x00a000
|
||||
argVec = 0x00a100
|
||||
fgetc = 0x001b68
|
||||
fgets = 0x001fa0
|
||||
gsosRead = 0x001393
|
||||
longjmp = 0x002674
|
||||
main = 0x001071
|
||||
memcmp = 0x00198b
|
||||
puts = 0x001aae
|
||||
setjmp = 0x00264c
|
||||
stderr = 0x002f2b
|
||||
stdin = 0x002f23
|
||||
stdout = 0x002f27
|
||||
strlen = 0x001a38
|
||||
writeHex.digits = 0x002e28
|
||||
BIN
demos/gnoStdin.o
Normal file
BIN
demos/gnoStdin.o
Normal file
Binary file not shown.
BIN
demos/gnoStdin.omf
Normal file
BIN
demos/gnoStdin.omf
Normal file
Binary file not shown.
BIN
demos/gnoStdin.reloc
Normal file
BIN
demos/gnoStdin.reloc
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -1,16 +1,16 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x001c3d ( 3133 bytes)
|
||||
.rodata : 0x001c3d .. 0x001c51 ( 20 bytes)
|
||||
.text : 0x001000 .. 0x001be6 ( 3046 bytes)
|
||||
.rodata : 0x001be6 .. 0x001be6 ( 0 bytes)
|
||||
.bss : 0x00a000 .. 0x00a002 ( 2 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
186 /home/scott/claude/llvm816/runtime/crt0Gsos.o
|
||||
99 /home/scott/claude/llvm816/runtime/crt0Gsos.o
|
||||
395 /home/scott/claude/llvm816/demos/helloBeep.o
|
||||
30853 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9098 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10865 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4374 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13388 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
32173 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9075 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
176 /home/scott/claude/llvm816/runtime/iigsGsos.o
|
||||
20670 /home/scott/claude/llvm816/runtime/iigsToolbox.o
|
||||
1139 /home/scott/claude/llvm816/runtime/desktop.o
|
||||
|
|
@ -32,55 +32,54 @@
|
|||
0x000002 __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x0010ba main
|
||||
0x001245 __jsl_indir
|
||||
0x001248 __mulhi3
|
||||
0x001267 __umulhisi3
|
||||
0x0012be __ashlhi3
|
||||
0x0012cd __lshrhi3
|
||||
0x0012dd __ashrhi3
|
||||
0x0012f0 __udivhi3
|
||||
0x0012fc __umodhi3
|
||||
0x001308 __divhi3
|
||||
0x001322 __modhi3
|
||||
0x00133c __divmod_setup
|
||||
0x00136f __udivmod_core
|
||||
0x00138d __mulsi3
|
||||
0x001446 __ashlsi3
|
||||
0x00145b __lshrsi3
|
||||
0x001470 __ashrsi3
|
||||
0x00148a __udivmodsi_core
|
||||
0x0014c2 __udivsi3
|
||||
0x0014d6 __umodsi3
|
||||
0x0014ea __divsi3
|
||||
0x001511 __modsi3
|
||||
0x001538 __divmodsi_setup
|
||||
0x001589 __divmoddi4_stash
|
||||
0x0015a6 __retdi
|
||||
0x0015b3 __ashldi3
|
||||
0x0015d6 __lshrdi3
|
||||
0x0015f9 __ashrdi3
|
||||
0x00161f __muldi3
|
||||
0x001686 __ucmpdi2
|
||||
0x0016af __cmpdi2
|
||||
0x0016e6 __udivdi3
|
||||
0x0016ef __umoddi3
|
||||
0x001708 __udivmoddi_core
|
||||
0x001755 __divdi3
|
||||
0x001774 __moddi3
|
||||
0x0017a1 __absdi_a
|
||||
0x0017a9 __absdi_b
|
||||
0x0017b1 __negdi_a
|
||||
0x0017cf __negdi_b
|
||||
0x0017ed setjmp
|
||||
0x001815 longjmp
|
||||
0x00183f __umulhisi3_qsq
|
||||
0x001c3d __rodata_start
|
||||
0x001c3d __text_end
|
||||
0x001c3d gChainPath
|
||||
0x001c51 __init_array_end
|
||||
0x001c51 __init_array_start
|
||||
0x001c51 __rodata_end
|
||||
0x001063 main
|
||||
0x0011ee __jsl_indir
|
||||
0x0011f1 __mulhi3
|
||||
0x001210 __umulhisi3
|
||||
0x001267 __ashlhi3
|
||||
0x001276 __lshrhi3
|
||||
0x001286 __ashrhi3
|
||||
0x001299 __udivhi3
|
||||
0x0012a5 __umodhi3
|
||||
0x0012b1 __divhi3
|
||||
0x0012cb __modhi3
|
||||
0x0012e5 __divmod_setup
|
||||
0x001318 __udivmod_core
|
||||
0x001336 __mulsi3
|
||||
0x0013ef __ashlsi3
|
||||
0x001404 __lshrsi3
|
||||
0x001419 __ashrsi3
|
||||
0x001433 __udivmodsi_core
|
||||
0x00146b __udivsi3
|
||||
0x00147f __umodsi3
|
||||
0x001493 __divsi3
|
||||
0x0014ba __modsi3
|
||||
0x0014e1 __divmodsi_setup
|
||||
0x001532 __divmoddi4_stash
|
||||
0x00154f __retdi
|
||||
0x00155c __ashldi3
|
||||
0x00157f __lshrdi3
|
||||
0x0015a2 __ashrdi3
|
||||
0x0015c8 __muldi3
|
||||
0x00162f __ucmpdi2
|
||||
0x001658 __cmpdi2
|
||||
0x00168f __udivdi3
|
||||
0x001698 __umoddi3
|
||||
0x0016b1 __udivmoddi_core
|
||||
0x0016fe __divdi3
|
||||
0x00171d __moddi3
|
||||
0x00174a __absdi_a
|
||||
0x001752 __absdi_b
|
||||
0x00175a __negdi_a
|
||||
0x001778 __negdi_b
|
||||
0x001796 setjmp
|
||||
0x0017be longjmp
|
||||
0x0017e8 __umulhisi3_qsq
|
||||
0x001be6 __init_array_end
|
||||
0x001be6 __init_array_start
|
||||
0x001be6 __rodata_end
|
||||
0x001be6 __rodata_start
|
||||
0x001be6 __text_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
|
|
@ -88,14 +87,14 @@
|
|||
0x00a002 __bss_end
|
||||
0x00a002 __heap_start
|
||||
0x00bf00 __heap_end
|
||||
__absdi_a = 0x0017a1
|
||||
__absdi_b = 0x0017a9
|
||||
__ashldi3 = 0x0015b3
|
||||
__ashlhi3 = 0x0012be
|
||||
__ashlsi3 = 0x001446
|
||||
__ashrdi3 = 0x0015f9
|
||||
__ashrhi3 = 0x0012dd
|
||||
__ashrsi3 = 0x001470
|
||||
__absdi_a = 0x00174a
|
||||
__absdi_b = 0x001752
|
||||
__ashldi3 = 0x00155c
|
||||
__ashlhi3 = 0x001267
|
||||
__ashlsi3 = 0x0013ef
|
||||
__ashrdi3 = 0x0015a2
|
||||
__ashrhi3 = 0x001286
|
||||
__ashrsi3 = 0x001419
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a002
|
||||
__bss_lo16 = 0x00a000
|
||||
|
|
@ -113,49 +112,48 @@ __bss_seg3_lo16 = 0x000000
|
|||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x000002
|
||||
__bss_start = 0x00a000
|
||||
__cmpdi2 = 0x0016af
|
||||
__divdi3 = 0x001755
|
||||
__divhi3 = 0x001308
|
||||
__divmod_setup = 0x00133c
|
||||
__divmoddi4_stash = 0x001589
|
||||
__divmodsi_setup = 0x001538
|
||||
__divsi3 = 0x0014ea
|
||||
__cmpdi2 = 0x001658
|
||||
__divdi3 = 0x0016fe
|
||||
__divhi3 = 0x0012b1
|
||||
__divmod_setup = 0x0012e5
|
||||
__divmoddi4_stash = 0x001532
|
||||
__divmodsi_setup = 0x0014e1
|
||||
__divsi3 = 0x001493
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a002
|
||||
__indirTarget = 0x00a000
|
||||
__init_array_end = 0x001c51
|
||||
__init_array_start = 0x001c51
|
||||
__jsl_indir = 0x001245
|
||||
__lshrdi3 = 0x0015d6
|
||||
__lshrhi3 = 0x0012cd
|
||||
__lshrsi3 = 0x00145b
|
||||
__moddi3 = 0x001774
|
||||
__modhi3 = 0x001322
|
||||
__modsi3 = 0x001511
|
||||
__muldi3 = 0x00161f
|
||||
__mulhi3 = 0x001248
|
||||
__mulsi3 = 0x00138d
|
||||
__negdi_a = 0x0017b1
|
||||
__negdi_b = 0x0017cf
|
||||
__retdi = 0x0015a6
|
||||
__rodata_end = 0x001c51
|
||||
__rodata_start = 0x001c3d
|
||||
__init_array_end = 0x001be6
|
||||
__init_array_start = 0x001be6
|
||||
__jsl_indir = 0x0011ee
|
||||
__lshrdi3 = 0x00157f
|
||||
__lshrhi3 = 0x001276
|
||||
__lshrsi3 = 0x001404
|
||||
__moddi3 = 0x00171d
|
||||
__modhi3 = 0x0012cb
|
||||
__modsi3 = 0x0014ba
|
||||
__muldi3 = 0x0015c8
|
||||
__mulhi3 = 0x0011f1
|
||||
__mulsi3 = 0x001336
|
||||
__negdi_a = 0x00175a
|
||||
__negdi_b = 0x001778
|
||||
__retdi = 0x00154f
|
||||
__rodata_end = 0x001be6
|
||||
__rodata_start = 0x001be6
|
||||
__start = 0x001000
|
||||
__text_end = 0x001c3d
|
||||
__text_end = 0x001be6
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x001686
|
||||
__udivdi3 = 0x0016e6
|
||||
__udivhi3 = 0x0012f0
|
||||
__udivmod_core = 0x00136f
|
||||
__udivmoddi_core = 0x001708
|
||||
__udivmodsi_core = 0x00148a
|
||||
__udivsi3 = 0x0014c2
|
||||
__umoddi3 = 0x0016ef
|
||||
__umodhi3 = 0x0012fc
|
||||
__umodsi3 = 0x0014d6
|
||||
__umulhisi3 = 0x001267
|
||||
__umulhisi3_qsq = 0x00183f
|
||||
gChainPath = 0x001c3d
|
||||
longjmp = 0x001815
|
||||
main = 0x0010ba
|
||||
setjmp = 0x0017ed
|
||||
__ucmpdi2 = 0x00162f
|
||||
__udivdi3 = 0x00168f
|
||||
__udivhi3 = 0x001299
|
||||
__udivmod_core = 0x001318
|
||||
__udivmoddi_core = 0x0016b1
|
||||
__udivmodsi_core = 0x001433
|
||||
__udivsi3 = 0x00146b
|
||||
__umoddi3 = 0x001698
|
||||
__umodhi3 = 0x0012a5
|
||||
__umodsi3 = 0x00147f
|
||||
__umulhisi3 = 0x001210
|
||||
__umulhisi3_qsq = 0x0017e8
|
||||
longjmp = 0x0017be
|
||||
main = 0x001063
|
||||
setjmp = 0x001796
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,16 +1,16 @@
|
|||
# section layout
|
||||
.text : 0x001000 .. 0x002108 ( 4360 bytes)
|
||||
.rodata : 0x002108 .. 0x002176 ( 110 bytes)
|
||||
.text : 0x001000 .. 0x0020b1 ( 4273 bytes)
|
||||
.rodata : 0x0020b1 .. 0x00210b ( 90 bytes)
|
||||
.bss : 0x00a000 .. 0x00a00a ( 10 bytes)
|
||||
|
||||
# per-input-file .text contributions
|
||||
186 /home/scott/claude/llvm816/runtime/crt0Gsos.o
|
||||
99 /home/scott/claude/llvm816/runtime/crt0Gsos.o
|
||||
546 /home/scott/claude/llvm816/demos/helloText.o
|
||||
30853 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9098 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10865 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4374 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13388 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
32173 /home/scott/claude/llvm816/runtime/libc.o
|
||||
9075 /home/scott/claude/llvm816/runtime/snprintf.o
|
||||
10814 /home/scott/claude/llvm816/runtime/extras.o
|
||||
4364 /home/scott/claude/llvm816/runtime/softFloat.o
|
||||
13051 /home/scott/claude/llvm816/runtime/softDouble.o
|
||||
176 /home/scott/claude/llvm816/runtime/iigsGsos.o
|
||||
20670 /home/scott/claude/llvm816/runtime/iigsToolbox.o
|
||||
1139 /home/scott/claude/llvm816/runtime/desktop.o
|
||||
|
|
@ -32,71 +32,70 @@
|
|||
0x00000a __bss_size
|
||||
0x001000 __start
|
||||
0x001000 __text_start
|
||||
0x0010ba main
|
||||
0x0012dc CtlStartUp
|
||||
0x0012ec EMStartUp
|
||||
0x00130b GetNextEvent
|
||||
0x001322 FMStartUp
|
||||
0x001332 LEStartUp
|
||||
0x001342 LoadOneTool
|
||||
0x001352 NewHandle
|
||||
0x001378 MenuStartUp
|
||||
0x001388 QDStartUp
|
||||
0x00139e DrawString
|
||||
0x0013b0 MoveTo
|
||||
0x0013c0 startdesk
|
||||
0x0016de paintDesktopBackdrop
|
||||
0x001710 __jsl_indir
|
||||
0x001713 __mulhi3
|
||||
0x001732 __umulhisi3
|
||||
0x001789 __ashlhi3
|
||||
0x001798 __lshrhi3
|
||||
0x0017a8 __ashrhi3
|
||||
0x0017bb __udivhi3
|
||||
0x0017c7 __umodhi3
|
||||
0x0017d3 __divhi3
|
||||
0x0017ed __modhi3
|
||||
0x001807 __divmod_setup
|
||||
0x00183a __udivmod_core
|
||||
0x001858 __mulsi3
|
||||
0x001911 __ashlsi3
|
||||
0x001926 __lshrsi3
|
||||
0x00193b __ashrsi3
|
||||
0x001955 __udivmodsi_core
|
||||
0x00198d __udivsi3
|
||||
0x0019a1 __umodsi3
|
||||
0x0019b5 __divsi3
|
||||
0x0019dc __modsi3
|
||||
0x001a03 __divmodsi_setup
|
||||
0x001a54 __divmoddi4_stash
|
||||
0x001a71 __retdi
|
||||
0x001a7e __ashldi3
|
||||
0x001aa1 __lshrdi3
|
||||
0x001ac4 __ashrdi3
|
||||
0x001aea __muldi3
|
||||
0x001b51 __ucmpdi2
|
||||
0x001b7a __cmpdi2
|
||||
0x001bb1 __udivdi3
|
||||
0x001bba __umoddi3
|
||||
0x001bd3 __udivmoddi_core
|
||||
0x001c20 __divdi3
|
||||
0x001c3f __moddi3
|
||||
0x001c6c __absdi_a
|
||||
0x001c74 __absdi_b
|
||||
0x001c7c __negdi_a
|
||||
0x001c9a __negdi_b
|
||||
0x001cb8 setjmp
|
||||
0x001ce0 longjmp
|
||||
0x001d0a __umulhisi3_qsq
|
||||
0x002108 __rodata_start
|
||||
0x002108 __text_end
|
||||
0x002108 gChainPath
|
||||
0x00211c line1
|
||||
0x002131 line2
|
||||
0x00215e line3
|
||||
0x002176 __init_array_end
|
||||
0x002176 __init_array_start
|
||||
0x002176 __rodata_end
|
||||
0x001063 main
|
||||
0x001285 CtlStartUp
|
||||
0x001295 EMStartUp
|
||||
0x0012b4 GetNextEvent
|
||||
0x0012cb FMStartUp
|
||||
0x0012db LEStartUp
|
||||
0x0012eb LoadOneTool
|
||||
0x0012fb NewHandle
|
||||
0x001321 MenuStartUp
|
||||
0x001331 QDStartUp
|
||||
0x001347 DrawString
|
||||
0x001359 MoveTo
|
||||
0x001369 startdesk
|
||||
0x001687 paintDesktopBackdrop
|
||||
0x0016b9 __jsl_indir
|
||||
0x0016bc __mulhi3
|
||||
0x0016db __umulhisi3
|
||||
0x001732 __ashlhi3
|
||||
0x001741 __lshrhi3
|
||||
0x001751 __ashrhi3
|
||||
0x001764 __udivhi3
|
||||
0x001770 __umodhi3
|
||||
0x00177c __divhi3
|
||||
0x001796 __modhi3
|
||||
0x0017b0 __divmod_setup
|
||||
0x0017e3 __udivmod_core
|
||||
0x001801 __mulsi3
|
||||
0x0018ba __ashlsi3
|
||||
0x0018cf __lshrsi3
|
||||
0x0018e4 __ashrsi3
|
||||
0x0018fe __udivmodsi_core
|
||||
0x001936 __udivsi3
|
||||
0x00194a __umodsi3
|
||||
0x00195e __divsi3
|
||||
0x001985 __modsi3
|
||||
0x0019ac __divmodsi_setup
|
||||
0x0019fd __divmoddi4_stash
|
||||
0x001a1a __retdi
|
||||
0x001a27 __ashldi3
|
||||
0x001a4a __lshrdi3
|
||||
0x001a6d __ashrdi3
|
||||
0x001a93 __muldi3
|
||||
0x001afa __ucmpdi2
|
||||
0x001b23 __cmpdi2
|
||||
0x001b5a __udivdi3
|
||||
0x001b63 __umoddi3
|
||||
0x001b7c __udivmoddi_core
|
||||
0x001bc9 __divdi3
|
||||
0x001be8 __moddi3
|
||||
0x001c15 __absdi_a
|
||||
0x001c1d __absdi_b
|
||||
0x001c25 __negdi_a
|
||||
0x001c43 __negdi_b
|
||||
0x001c61 setjmp
|
||||
0x001c89 longjmp
|
||||
0x001cb3 __umulhisi3_qsq
|
||||
0x0020b1 __rodata_start
|
||||
0x0020b1 __text_end
|
||||
0x0020b1 line1
|
||||
0x0020c6 line2
|
||||
0x0020f3 line3
|
||||
0x00210b __init_array_end
|
||||
0x00210b __init_array_start
|
||||
0x00210b __rodata_end
|
||||
0x00a000 __bss_lo16
|
||||
0x00a000 __bss_seg0_lo16
|
||||
0x00a000 __bss_start
|
||||
|
|
@ -107,25 +106,25 @@
|
|||
0x00a00a __bss_end
|
||||
0x00a00a __heap_start
|
||||
0x00bf00 __heap_end
|
||||
CtlStartUp = 0x0012dc
|
||||
DrawString = 0x00139e
|
||||
EMStartUp = 0x0012ec
|
||||
FMStartUp = 0x001322
|
||||
GetNextEvent = 0x00130b
|
||||
LEStartUp = 0x001332
|
||||
LoadOneTool = 0x001342
|
||||
MenuStartUp = 0x001378
|
||||
MoveTo = 0x0013b0
|
||||
NewHandle = 0x001352
|
||||
QDStartUp = 0x001388
|
||||
__absdi_a = 0x001c6c
|
||||
__absdi_b = 0x001c74
|
||||
__ashldi3 = 0x001a7e
|
||||
__ashlhi3 = 0x001789
|
||||
__ashlsi3 = 0x001911
|
||||
__ashrdi3 = 0x001ac4
|
||||
__ashrhi3 = 0x0017a8
|
||||
__ashrsi3 = 0x00193b
|
||||
CtlStartUp = 0x001285
|
||||
DrawString = 0x001347
|
||||
EMStartUp = 0x001295
|
||||
FMStartUp = 0x0012cb
|
||||
GetNextEvent = 0x0012b4
|
||||
LEStartUp = 0x0012db
|
||||
LoadOneTool = 0x0012eb
|
||||
MenuStartUp = 0x001321
|
||||
MoveTo = 0x001359
|
||||
NewHandle = 0x0012fb
|
||||
QDStartUp = 0x001331
|
||||
__absdi_a = 0x001c15
|
||||
__absdi_b = 0x001c1d
|
||||
__ashldi3 = 0x001a27
|
||||
__ashlhi3 = 0x001732
|
||||
__ashlsi3 = 0x0018ba
|
||||
__ashrdi3 = 0x001a6d
|
||||
__ashrhi3 = 0x001751
|
||||
__ashrsi3 = 0x0018e4
|
||||
__bss_bank = 0x000000
|
||||
__bss_end = 0x00a00a
|
||||
__bss_lo16 = 0x00a000
|
||||
|
|
@ -143,57 +142,56 @@ __bss_seg3_lo16 = 0x000000
|
|||
__bss_seg3_size = 0x000000
|
||||
__bss_size = 0x00000a
|
||||
__bss_start = 0x00a000
|
||||
__cmpdi2 = 0x001b7a
|
||||
__divdi3 = 0x001c20
|
||||
__divhi3 = 0x0017d3
|
||||
__divmod_setup = 0x001807
|
||||
__divmoddi4_stash = 0x001a54
|
||||
__divmodsi_setup = 0x001a03
|
||||
__divsi3 = 0x0019b5
|
||||
__cmpdi2 = 0x001b23
|
||||
__divdi3 = 0x001bc9
|
||||
__divhi3 = 0x00177c
|
||||
__divmod_setup = 0x0017b0
|
||||
__divmoddi4_stash = 0x0019fd
|
||||
__divmodsi_setup = 0x0019ac
|
||||
__divsi3 = 0x00195e
|
||||
__heap_end = 0x00bf00
|
||||
__heap_start = 0x00a00a
|
||||
__indirTarget = 0x00a008
|
||||
__init_array_end = 0x002176
|
||||
__init_array_start = 0x002176
|
||||
__jsl_indir = 0x001710
|
||||
__lshrdi3 = 0x001aa1
|
||||
__lshrhi3 = 0x001798
|
||||
__lshrsi3 = 0x001926
|
||||
__moddi3 = 0x001c3f
|
||||
__modhi3 = 0x0017ed
|
||||
__modsi3 = 0x0019dc
|
||||
__muldi3 = 0x001aea
|
||||
__mulhi3 = 0x001713
|
||||
__mulsi3 = 0x001858
|
||||
__negdi_a = 0x001c7c
|
||||
__negdi_b = 0x001c9a
|
||||
__retdi = 0x001a71
|
||||
__rodata_end = 0x002176
|
||||
__rodata_start = 0x002108
|
||||
__init_array_end = 0x00210b
|
||||
__init_array_start = 0x00210b
|
||||
__jsl_indir = 0x0016b9
|
||||
__lshrdi3 = 0x001a4a
|
||||
__lshrhi3 = 0x001741
|
||||
__lshrsi3 = 0x0018cf
|
||||
__moddi3 = 0x001be8
|
||||
__modhi3 = 0x001796
|
||||
__modsi3 = 0x001985
|
||||
__muldi3 = 0x001a93
|
||||
__mulhi3 = 0x0016bc
|
||||
__mulsi3 = 0x001801
|
||||
__negdi_a = 0x001c25
|
||||
__negdi_b = 0x001c43
|
||||
__retdi = 0x001a1a
|
||||
__rodata_end = 0x00210b
|
||||
__rodata_start = 0x0020b1
|
||||
__start = 0x001000
|
||||
__text_end = 0x002108
|
||||
__text_end = 0x0020b1
|
||||
__text_start = 0x001000
|
||||
__ucmpdi2 = 0x001b51
|
||||
__udivdi3 = 0x001bb1
|
||||
__udivhi3 = 0x0017bb
|
||||
__udivmod_core = 0x00183a
|
||||
__udivmoddi_core = 0x001bd3
|
||||
__udivmodsi_core = 0x001955
|
||||
__udivsi3 = 0x00198d
|
||||
__umoddi3 = 0x001bba
|
||||
__umodhi3 = 0x0017c7
|
||||
__umodsi3 = 0x0019a1
|
||||
__umulhisi3 = 0x001732
|
||||
__umulhisi3_qsq = 0x001d0a
|
||||
gChainPath = 0x002108
|
||||
__ucmpdi2 = 0x001afa
|
||||
__udivdi3 = 0x001b5a
|
||||
__udivhi3 = 0x001764
|
||||
__udivmod_core = 0x0017e3
|
||||
__udivmoddi_core = 0x001b7c
|
||||
__udivmodsi_core = 0x0018fe
|
||||
__udivsi3 = 0x001936
|
||||
__umoddi3 = 0x001b63
|
||||
__umodhi3 = 0x001770
|
||||
__umodsi3 = 0x00194a
|
||||
__umulhisi3 = 0x0016db
|
||||
__umulhisi3_qsq = 0x001cb3
|
||||
gDpBase = 0x00a006
|
||||
gDpHandle = 0x00a002
|
||||
gUserId = 0x00a000
|
||||
line1 = 0x00211c
|
||||
line2 = 0x002131
|
||||
line3 = 0x00215e
|
||||
longjmp = 0x001ce0
|
||||
main = 0x0010ba
|
||||
paintDesktopBackdrop = 0x0016de
|
||||
setjmp = 0x001cb8
|
||||
startdesk = 0x0013c0
|
||||
line1 = 0x0020b1
|
||||
line2 = 0x0020c6
|
||||
line3 = 0x0020f3
|
||||
longjmp = 0x001c89
|
||||
main = 0x001063
|
||||
paintDesktopBackdrop = 0x001687
|
||||
setjmp = 0x001c61
|
||||
startdesk = 0x001369
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -39,6 +39,10 @@ cc() {
|
|||
|
||||
asm "$SRC/crt0.s"
|
||||
asm "$SRC/crt0Gsos.s"
|
||||
asm "$SRC/crt0Gno.s"
|
||||
asm "$SRC/gnoKernel.s"
|
||||
asm "$SRC/gnoGsos.s"
|
||||
cc "$SRC/libcGno.c"
|
||||
asm "$SRC/libgcc.s"
|
||||
cc "$SRC/libc.c"
|
||||
cc "$SRC/strtol.c"
|
||||
|
|
|
|||
48
runtime/include/gno/kernel.h
Normal file
48
runtime/include/gno/kernel.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// AUTOGENERATED by scripts/genGnoKernel.py — DO NOT EDIT.
|
||||
// GNO kernel toolset $03 wrappers, callable from C.
|
||||
// Convention: each K* returns the kernel result (or -1 on error);
|
||||
// the last argument is `int *errno` and gets the kernel's errno.
|
||||
//
|
||||
// These are LOW-LEVEL primitives — libc routines in libcGno.c
|
||||
// wrap them into POSIX-named fork/exec/wait/etc.
|
||||
#ifndef GNO_KERNEL_H
|
||||
#define GNO_KERNEL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int Kgetpid(void); // 0x0903
|
||||
extern int Kkill(int a0, int a1, void * a2); // 0x0A03
|
||||
extern int Kfork(void * a0, void * a1); // 0x0B03
|
||||
extern int Kgetppid(void * a0); // 0x4003
|
||||
extern int Kwait(void * a0, void * a1); // 0x1703
|
||||
extern int K_execve(void * a0, void * a1, void * a2); // 0x1D03
|
||||
extern unsigned long Ksignal(int a0, void * a1, void * a2); // 0x1603
|
||||
extern unsigned long Kalarm(void * a0, void * a1); // 0x1E03
|
||||
extern unsigned long Kalarm10(void * a0, void * a1); // 0x4203
|
||||
extern int Ksigpause(void * a0, void * a1); // 0x2103
|
||||
extern unsigned long Ksigsetmask(void * a0, void * a1); // 0x1B03
|
||||
extern unsigned long Ksigblock(void * a0, void * a1); // 0x1C03
|
||||
extern int Kdup(int a0, void * a1); // 0x2203
|
||||
extern int Kdup2(int a0, int a1, void * a2); // 0x2303
|
||||
extern int Kpipe(void * a0, void * a1); // 0x2403
|
||||
extern int Kioctl(int a0, void * a1, void * a2, void * a3); // 0x2603
|
||||
extern int Kstat(void * a0, void * a1, void * a2); // 0x2703
|
||||
extern int Kfstat(int a0, void * a1, void * a2); // 0x2803
|
||||
extern int Klstat(void * a0, void * a1, void * a2); // 0x2903
|
||||
extern int Kgetuid(void * a0); // 0x2A03
|
||||
extern int Kgetgid(void * a0); // 0x2B03
|
||||
extern int Kgeteuid(void * a0); // 0x2C03
|
||||
extern int Kgetegid(void * a0); // 0x2D03
|
||||
extern int Ksetuid(int a0, void * a1); // 0x2E03
|
||||
extern int Ksetgid(int a0, void * a1); // 0x2F03
|
||||
extern int Ktcnewpgrp(int a0, void * a1); // 0x1803
|
||||
extern int Ksettpgrp(int a0, void * a1); // 0x1903
|
||||
extern int Ktctpgrp(int a0, int a1, void * a2); // 0x1A03
|
||||
extern int K_getpgrp(int a0, void * a1); // 0x2503
|
||||
extern int Ksetpgrp(int a0, int a1, void * a2); // 0x3403
|
||||
extern int Kkvm_open(void * a0); // 0x1103
|
||||
extern int Kkvm_close(void * a0, void * a1); // 0x1203
|
||||
extern unsigned long Ktimes(void * a0, void * a1); // 0x3503
|
||||
extern void KSetGNOQuitRec(int a0, void * a1, int a2, void * a3); // 0x4103
|
||||
|
||||
#endif
|
||||
|
|
@ -84,6 +84,9 @@ __start:
|
|||
phb ; save current DBR
|
||||
|
||||
; ---- segment 0 ----
|
||||
; The `sep #0x20` that sets the segment's data bank also puts us in
|
||||
; M=8 for the whole store loop (X stays 16-bit), so we don't flip
|
||||
; SEP/REP per byte; each segment label below re-enters via `rep`.
|
||||
rep #0x20
|
||||
ldx #__bss_seg0_size
|
||||
beq .Lbss_seg1
|
||||
|
|
@ -92,14 +95,11 @@ __start:
|
|||
.byte __bss_seg0_bank
|
||||
pha
|
||||
plb
|
||||
rep #0x20
|
||||
ldx #0
|
||||
.Lbss_loop0:
|
||||
cpx #__bss_seg0_size
|
||||
bcs .Lbss_seg1
|
||||
sep #0x20
|
||||
stz __bss_seg0_lo16, x
|
||||
rep #0x20
|
||||
inx
|
||||
bra .Lbss_loop0
|
||||
.Lbss_seg1:
|
||||
|
|
@ -112,14 +112,11 @@ __start:
|
|||
.byte __bss_seg1_bank
|
||||
pha
|
||||
plb
|
||||
rep #0x20
|
||||
ldx #0
|
||||
.Lbss_loop1:
|
||||
cpx #__bss_seg1_size
|
||||
bcs .Lbss_seg2
|
||||
sep #0x20
|
||||
stz __bss_seg1_lo16, x
|
||||
rep #0x20
|
||||
inx
|
||||
bra .Lbss_loop1
|
||||
.Lbss_seg2:
|
||||
|
|
@ -132,14 +129,11 @@ __start:
|
|||
.byte __bss_seg2_bank
|
||||
pha
|
||||
plb
|
||||
rep #0x20
|
||||
ldx #0
|
||||
.Lbss_loop2:
|
||||
cpx #__bss_seg2_size
|
||||
bcs .Lbss_seg3
|
||||
sep #0x20
|
||||
stz __bss_seg2_lo16, x
|
||||
rep #0x20
|
||||
inx
|
||||
bra .Lbss_loop2
|
||||
.Lbss_seg3:
|
||||
|
|
@ -152,17 +146,15 @@ __start:
|
|||
.byte __bss_seg3_bank
|
||||
pha
|
||||
plb
|
||||
rep #0x20
|
||||
ldx #0
|
||||
.Lbss_loop3:
|
||||
cpx #__bss_seg3_size
|
||||
bcs .Lbss_done
|
||||
sep #0x20
|
||||
stz __bss_seg3_lo16, x
|
||||
rep #0x20
|
||||
inx
|
||||
bra .Lbss_loop3
|
||||
.Lbss_done:
|
||||
rep #0x20 ; back to M=16 after the M=8 store loop
|
||||
plb ; restore caller's DBR
|
||||
|
||||
; Run static constructors. The linker emits
|
||||
|
|
@ -225,8 +217,12 @@ __start:
|
|||
; nothing. After return, A holds the exit code.
|
||||
jsl main
|
||||
|
||||
; Halt via BRK $00. MAME / debuggers catch this as a clean
|
||||
; program termination.
|
||||
.byte 0x00, 0x00
|
||||
; main returned. Bare metal has no OS to return to, so spin.
|
||||
; (Previously a BRK $00 here, but headless MAME mis-vectors BRK to
|
||||
; $0000 and wild-jumps, which reads as a crash. A tight loop is the
|
||||
; conventional bare-metal halt; IRQs are already masked above, so
|
||||
; this just idles.)
|
||||
.Lhalt:
|
||||
bra .Lhalt
|
||||
|
||||
.size __start, . - __start
|
||||
|
|
|
|||
141
runtime/src/crt0Gno.s
Normal file
141
runtime/src/crt0Gno.s
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
; crt0Gno.s — GNO/ME shell command crt0.
|
||||
;
|
||||
; Use this INSTEAD OF crt0.s / crt0Gsos.s when building an OMF intended
|
||||
; to run as a GNO shell command (filetype $B5 EXE, aux 0).
|
||||
;
|
||||
; GNO/ME entry contract for a shell command (per ORCA's ~GNO_COMMAND):
|
||||
; E=0 (native), M=0 (16-bit accumulator), X=0 (16-bit index)
|
||||
; A:X = command line pointer (32-bit; A=low word, X=high word)
|
||||
; Y = user ID (currently unused by us)
|
||||
; DBR = bank of our entry segment (set by GS/OS Loader)
|
||||
; DP = pointer to a Memory-Manager-allocated DP page
|
||||
; The GS/OS Loader's launch frame on the stack is discarded by Quit.
|
||||
;
|
||||
; Differences from crt0Gsos.s:
|
||||
; - The kernel passes a command-line pointer in A:X (not on the stack).
|
||||
; - Instead of QUIT chaining to a hardcoded path, we just QUIT(pcount=0)
|
||||
; so control returns to the GNO shell that launched us.
|
||||
; - main() receives (int argc, char **argv) — crt0 calls a C helper
|
||||
; __gnoStartup(cmdline) which parses the command line and invokes
|
||||
; main(), then falls through to QUIT.
|
||||
|
||||
.text
|
||||
|
||||
.globl __start
|
||||
__start:
|
||||
; GNO entry contract (from kern ~GNO_COMMAND, lib/libc/gno/gnocmd.asm):
|
||||
; A = user ID
|
||||
; Y:X = command-line pointer (Y = low word, X = high word) — a
|
||||
; NUL-terminated C string of the invocation command line.
|
||||
; Stash the cmdline pointer (Y:X) to bank-0 scratch $00:00B0..B3
|
||||
; and the user ID (A) to $00:00B6, BEFORE we switch to DP=0.
|
||||
; Bank-explicit `sta long` so we don't depend on DP/DBR here.
|
||||
rep #0x30
|
||||
.byte 0x8f, 0xb6, 0x00, 0x00 ; sta long $00:00B6 (user ID)
|
||||
tya
|
||||
.byte 0x8f, 0xb0, 0x00, 0x00 ; sta long $00:00B0 (cmdline low word = Y)
|
||||
txa
|
||||
.byte 0x8f, 0xb2, 0x00, 0x00 ; sta long $00:00B2 (cmdline high word = X)
|
||||
|
||||
; Set DBR := PBR (our entry-segment bank) — same Loader-contract
|
||||
; mitigation as crt0Gsos.s.
|
||||
phk
|
||||
plb
|
||||
|
||||
; Save GNO's per-process direct page BEFORE zeroing it. GNO's
|
||||
; GS/OS-call interceptor uses the caller's DP to identify the
|
||||
; calling process (and find its fd table). Our codegen needs
|
||||
; DP=0, so we stash GNO's DP at $00:00B4 and restore it around
|
||||
; GS/OS calls (see __gnoSaveDP / gsosWrite-under-GNO path).
|
||||
rep #0x30
|
||||
tdc ; A = current (GNO) DP
|
||||
.byte 0x8f, 0xb4, 0x00, 0x00 ; sta long $00:00B4 (stash GNO DP word)
|
||||
|
||||
; Set DP=0 — backend assumes DP=0 for `sta dp` / `[dp],y` etc.
|
||||
lda #0
|
||||
tcd
|
||||
|
||||
; Persistent "current data bank" byte at DP $BE = PBR (our bank).
|
||||
; See crt0.s comment for rationale (codegen reads this for the
|
||||
; bank half of `&symbol` 32-bit pointers).
|
||||
sep #0x20
|
||||
phk
|
||||
pla
|
||||
sta 0xbe
|
||||
stz 0xbf ; pad so `lda 0xbe` in 16-bit M reads $00PBR
|
||||
rep #0x20
|
||||
|
||||
; BSS zero-init (DBR-relative byte stores). M is held at 8 across
|
||||
; the whole loop while X stays 16-bit, so we don't flip SEP/REP per
|
||||
; byte (llvm-mc still encodes cpx/ldx as 16-bit X-immediates in M=8).
|
||||
rep #0x30 ; M=16, X=16
|
||||
sep #0x20 ; M=8 for the byte stores; X remains 16-bit
|
||||
ldx #__bss_start
|
||||
.Lbss_loop:
|
||||
cpx #__bss_end
|
||||
bcs .Lbss_done
|
||||
stz 0x0000, x ; 1-byte store (M=8)
|
||||
inx
|
||||
bra .Lbss_loop
|
||||
.Lbss_done:
|
||||
rep #0x20 ; restore M=16
|
||||
|
||||
; Walk .init_array (C++ ctors). Inlined from crt0Gsos.s. The
|
||||
; `jsl __jsl_indir` and `jsl main` operands are relocated by the
|
||||
; GS/OS Loader: omfEmit emits a cRELOC (0xF5) IMM24 site for each
|
||||
; intra-segment JSL, so the Loader patches the full 24-bit operand
|
||||
; (bank included) to the placed address. Non-zero-bank placement is
|
||||
; handled correctly as long as the OMF is built with --relocs (which
|
||||
; demos/buildGno.sh does).
|
||||
rep #0x30
|
||||
ldx #__init_array_start
|
||||
.Linit_loop:
|
||||
cpx #__init_array_end
|
||||
bcs .Linit_done
|
||||
stx 0xe0
|
||||
ldy #0
|
||||
lda (0xe0), y
|
||||
sta __indirTarget
|
||||
phx
|
||||
jsl __jsl_indir
|
||||
plx
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
inx
|
||||
bra .Linit_loop
|
||||
.Linit_done:
|
||||
|
||||
; Reload cmdline ptr from $00:00B0..$00:00B3 into A:X.
|
||||
; Use bank-explicit `lda long` so we don't depend on DBR.
|
||||
rep #0x30
|
||||
.byte 0xaf, 0xb0, 0x00, 0x00 ; lda long $00:00B0 -> A (cmdline lo word)
|
||||
pha ; stash A on stack briefly
|
||||
.byte 0xaf, 0xb2, 0x00, 0x00 ; lda long $00:00B2 -> A (cmdline hi word)
|
||||
tax ; X = cmdline hi
|
||||
pla ; A = cmdline lo
|
||||
|
||||
; Call __gnoStartup(cmdline) — C helper in libcGno.c which:
|
||||
; 1. parses the command line into argc/argv,
|
||||
; 2. calls main(argc, argv),
|
||||
; 3. returns whatever main returned.
|
||||
jsl __gnoStartup
|
||||
|
||||
; ---- Terminate via _exit (libcGno.c) ----
|
||||
; __gnoStartup returned with A = main()'s exit status. _exit issues
|
||||
; GS/OS QUIT through GNO's INLINE dispatch (__gnoGsosCall), which is
|
||||
; REQUIRED under GNO: the old stack-based QUIT here (ldx #$2029 ;
|
||||
; jsl $e100a8 with the pblock pushed) was misread by GNO's OurGSOS
|
||||
; interceptor — it reads the call number + pblock from the inline
|
||||
; bytes after the jsl, not the stack — so the QUIT was mis-dispatched,
|
||||
; the process was left restartable, and GNO RE-RAN main() a second
|
||||
; time (silently draining redirected stdin on the first pass).
|
||||
jsl _exit
|
||||
|
||||
; _exit does not return. If it ever does, spin rather than fall
|
||||
; into a BRK (headless MAME mis-vectors BRK to $0000, which looks
|
||||
; like a wild crash) or off the end of the segment.
|
||||
.Lhang:
|
||||
bra .Lhang
|
||||
|
||||
.size __start, . - __start
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
; - No language-card RAM enable (GS/OS configures memory).
|
||||
; - No stack base reset (GS/OS allocated and set our SP).
|
||||
; - Honors GS/OS's DBR=our-bank, DP=allocated-page setup.
|
||||
; - On main() return, calls GS/OS QUIT(pcount=2) to chain to a
|
||||
; known next application (default: /SYSTEM/START.ORIG which
|
||||
; test setups must save off the original boot launcher to).
|
||||
; - On main() return, calls GS/OS QUIT(pcount=0) to return control to
|
||||
; the launching program (Finder / shell / boot chain) — the standard
|
||||
; GS/OS application exit.
|
||||
;
|
||||
; Entry from the System Loader (per Apple IIgs Toolbox Reference):
|
||||
; E=0 (native), M=0 (16-bit accumulator), X=0 (16-bit index)
|
||||
|
|
@ -33,18 +33,6 @@ __start:
|
|||
; wrong bank without this. PHK + PLB copies PBR into DBR.
|
||||
phk
|
||||
plb
|
||||
; Diagnostic: stash a marker at $00:007F via `sta long` (bank-
|
||||
; explicit, immune to DBR uncertainty) immediately on entry.
|
||||
; Runtime probes use this to detect whether the Loader actually
|
||||
; reached our code or silently rejected the OMF earlier.
|
||||
; The assembler doesn't track SEP/REP state, so the LDA #imm
|
||||
; needs explicit `.byte` form: the standard `lda #$7F` would
|
||||
; assemble as 3 bytes (16-bit imm) and the trailing $00 would
|
||||
; execute as BRK at runtime once M=8.
|
||||
sep #0x20
|
||||
.byte 0xa9, 0x7f ; lda #$7F (8-bit imm)
|
||||
.byte 0x8f, 0x7f, 0x00, 0x00 ; sta long $00:007F
|
||||
rep #0x20
|
||||
|
||||
; Set DP=0. The C compiler assumes DP=0 for all `sta dp` and
|
||||
; `[dp],y`-style accesses; GS/OS hands us a Memory-Manager-
|
||||
|
|
@ -69,44 +57,28 @@ __start:
|
|||
; LDAi16imm_bank expansion)
|
||||
rep #0x20
|
||||
|
||||
; --- Diagnostic markers between crt0 phases. Bank-explicit
|
||||
; `sta long` to $00:007E so they're visible from a host probe
|
||||
; regardless of DBR/PBR.
|
||||
sep #0x20
|
||||
.byte 0xa9, 0x7e ; lda #$7E
|
||||
.byte 0x8f, 0x7e, 0x00, 0x00 ; sta long $00:007E (post-DP)
|
||||
rep #0x20
|
||||
|
||||
; BSS zero-init. With DBR=our bank, `stz abs,X` writes to
|
||||
; ourBank:X — correct as long as __bss_start/__bss_end fit in
|
||||
; the segment's bank.
|
||||
rep #0x30
|
||||
; ourBank:X — correct as long as __bss_start/__bss_end fit in the
|
||||
; segment's bank. M held at 8 across the loop (X stays 16-bit) so
|
||||
; we don't flip SEP/REP per byte.
|
||||
rep #0x30 ; M=16, X=16
|
||||
sep #0x20 ; M=8 for the byte stores; X remains 16-bit
|
||||
ldx #__bss_start
|
||||
.Lbss_loop:
|
||||
cpx #__bss_end
|
||||
bcs .Lbss_done
|
||||
sep #0x20
|
||||
stz 0x0000, x
|
||||
rep #0x20
|
||||
stz 0x0000, x ; 1-byte store (M=8)
|
||||
inx
|
||||
bra .Lbss_loop
|
||||
.Lbss_done:
|
||||
sep #0x20
|
||||
.byte 0xa9, 0x7d ; lda #$7D
|
||||
.byte 0x8f, 0x7d, 0x00, 0x00 ; sta long $00:007D (post-BSS)
|
||||
rep #0x20
|
||||
rep #0x20 ; restore M=16
|
||||
|
||||
; Walk .init_array (C++ ctors).
|
||||
;
|
||||
; ⚠ KNOWN BROKEN under real GS/OS Loader for non-zero-bank
|
||||
; placement: `jsl __jsl_indir` bakes a bank-0 operand at link
|
||||
; time. When the Loader places us at bank $1f or similar, the
|
||||
; JSL targets bank 0 (= GS/OS code) instead of our actual bank
|
||||
; — so this loop crashes if init_array has any entries. Same
|
||||
; applies to `jsl main` below. Closing the gap requires either
|
||||
; RELOC opcode emission in omfEmit (so the Loader patches the
|
||||
; JSL bank bytes at load time) or runtime self-patching of JSL
|
||||
; opcodes in crt0. Tracked separately.
|
||||
; Walk .init_array (C++ ctors). The `jsl __jsl_indir` and the
|
||||
; `jsl main` below are relocated by the GS/OS Loader: omfEmit emits
|
||||
; a cRELOC (0xF5) IMM24 site for each intra-segment JSL, so the
|
||||
; Loader patches the full 24-bit operand (bank included) to the
|
||||
; placed address. Non-zero-bank placement works as long as the OMF
|
||||
; is built with --relocs (demos/build.sh / buildGno.sh do).
|
||||
rep #0x30
|
||||
ldx #__init_array_start
|
||||
.Linit_loop:
|
||||
|
|
@ -127,86 +99,31 @@ __start:
|
|||
bra .Linit_loop
|
||||
.Linit_done:
|
||||
|
||||
; Marker: about to JSL main.
|
||||
sep #0x20
|
||||
.byte 0xa9, 0x7c ; lda #$7C
|
||||
.byte 0x8f, 0x7c, 0x00, 0x00 ; sta long $00:007C (about to call main)
|
||||
rep #0x20
|
||||
|
||||
; Call main. Standard W65816 C ABI: arg0 in A; we pass none.
|
||||
rep #0x30
|
||||
jsl main
|
||||
|
||||
; ---- QUIT (pcount=2) chain to gChainPath ---------------------
|
||||
; Parm block layout in DP $80..$87:
|
||||
; $80,$81 pcount = 2
|
||||
; $82..$85 pathname long ptr (lo, mid, bank, pad)
|
||||
; $86,$87 flags = 0
|
||||
;
|
||||
; The path is a GSString (2-byte length + chars). It must live
|
||||
; in bank-0 memory (GS/OS reads parm fields as bank-0). DP is in
|
||||
; bank 0, so we copy the GSString from our segment into DP $A0.
|
||||
|
||||
; ---- QUIT (pcount=0): return to the launching program ----------
|
||||
; The standard GS/OS application exit. A pcount=0 parm block (just
|
||||
; a zero pcount word) tells QUIT to return control to whoever
|
||||
; launched us (Finder, a shell, the boot chain) with default flags
|
||||
; (non-restartable) — no hardcoded chain path needed. A program
|
||||
; that wants to chain elsewhere can provide its own _exit/crt0.
|
||||
rep #0x30
|
||||
|
||||
; Copy length byte first to compute total bytes to copy.
|
||||
sep #0x20
|
||||
lda gChainPath ; low byte of GSString length
|
||||
clc
|
||||
adc #2 ; +2 for the length word itself
|
||||
tay ; Y = bytes to copy (paths < 256 chars)
|
||||
rep #0x20
|
||||
|
||||
ldx #0
|
||||
.LcopyPath:
|
||||
sep #0x20
|
||||
lda gChainPath, x ; DBR-relative read (DBR = our bank)
|
||||
sta 0xa0, x ; DP write (in bank 0)
|
||||
rep #0x20
|
||||
inx
|
||||
dey
|
||||
bne .LcopyPath
|
||||
|
||||
; Build parm block at DP $80.
|
||||
rep #0x30
|
||||
lda #2
|
||||
sta 0x80 ; pcount
|
||||
|
||||
tdc
|
||||
clc
|
||||
adc #0xa0
|
||||
sta 0x82 ; pathname long-ptr low+mid 16
|
||||
lda #0
|
||||
sta 0x84 ; bank byte (0) + pad byte (0)
|
||||
sta 0x86 ; flags = 0
|
||||
|
||||
; Push 32-bit parm-block pointer (low half + bank-0).
|
||||
stz 0x80 ; pcount = 0 (parm block at DP $0080, bank 0)
|
||||
tdc
|
||||
clc
|
||||
adc #0x80
|
||||
pha
|
||||
pea 0
|
||||
pha ; parm-block ptr: low 16 (offset)
|
||||
pea 0 ; parm-block ptr: high 16 (bank 0)
|
||||
ldx #0x2029 ; QUIT class-1 call number
|
||||
jsl 0xe100a8 ; GS/OS dispatcher
|
||||
|
||||
; QUIT only returns on failure. Clean up + BRK.
|
||||
; QUIT only returns on failure. Clean up the pushed pointer and
|
||||
; spin (don't fall into a BRK, which headless MAME mis-vectors).
|
||||
pla
|
||||
pla
|
||||
.byte 0x00, 0x00
|
||||
.Lhang:
|
||||
bra .Lhang
|
||||
|
||||
.size __start, . - __start
|
||||
|
||||
|
||||
; gChainPath — GSString chain target for QUIT after main(). Default
|
||||
; is "/SYSTEM/START.ORIG" (saved-original boot launcher). Programs
|
||||
; that need a different target must rename this symbol; the linker
|
||||
; resolves whichever def is present.
|
||||
;
|
||||
; GSString: 2-byte length word + N chars. Length here = 18
|
||||
; ("/SYSTEM/START.ORIG").
|
||||
|
||||
.section .rodata,"a"
|
||||
.globl gChainPath
|
||||
gChainPath:
|
||||
.byte 18, 0
|
||||
.ascii "/SYSTEM/START.ORIG"
|
||||
|
|
|
|||
42
runtime/src/gnoGsos.s
Normal file
42
runtime/src/gnoGsos.s
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
; gnoGsos.s — GS/OS calls from inside a GNO/ME process.
|
||||
;
|
||||
; GNO patches GS/OS entry $E100A8 to its interceptor (OurGSOS in
|
||||
; kern/gno/gsos.asm), which reads the call number + parameter-block
|
||||
; pointer from the 6 INLINE bytes after the JSL and bumps the return
|
||||
; address +6 to skip them:
|
||||
;
|
||||
; jsl $E100A8
|
||||
; dc i2 callNum ; 2 bytes
|
||||
; dc i4 pBlockPtr ; 4 bytes (bank : offset)
|
||||
; <-- OurGSOS returns here
|
||||
;
|
||||
; The plain stack-based form (callNum in X, pBlock pushed) that bare
|
||||
; GS/OS accepts does NOT work under GNO. We self-modify the inline
|
||||
; callNum + pBlock operands, then dispatch.
|
||||
;
|
||||
; __gnoGsosCall(void *pBlock, unsigned short callNum) -> u16 error
|
||||
; C ABI: arg0 (pBlock ptr32) in A:X (A=offset, X=bank); arg1
|
||||
; (callNum i16) at (4,s). Returns the GS/OS error in A (0 = OK).
|
||||
|
||||
.text
|
||||
.globl __gnoGsosCall
|
||||
__gnoGsosCall:
|
||||
rep #0x30
|
||||
sta __gnoPBlock ; inline pBlock offset (low 16)
|
||||
txa
|
||||
sta __gnoPBlock+2 ; inline pBlock bank+pad (X = bank : pad)
|
||||
lda 4, s ; callNum from the stack
|
||||
sta __gnoCallNum ; inline callNum
|
||||
lda 0xb4 ; restore GNO's per-process DP
|
||||
tcd
|
||||
jsl 0xe100a8
|
||||
__gnoCallNum:
|
||||
.word 0 ; patched: GS/OS call number
|
||||
__gnoPBlock:
|
||||
.long 0 ; patched: param-block pointer
|
||||
; --- OurGSOS returns here (return addr bumped +6) ---
|
||||
tay ; Y = error (survives DP change)
|
||||
lda #0
|
||||
tcd ; DP := 0 for the C caller
|
||||
tya
|
||||
rtl
|
||||
852
runtime/src/gnoKernel.s
Normal file
852
runtime/src/gnoKernel.s
Normal file
|
|
@ -0,0 +1,852 @@
|
|||
; AUTOGENERATED by scripts/genGnoKernel.py — DO NOT EDIT by hand.
|
||||
;
|
||||
; GNO/ME kernel toolset $03 wrappers.
|
||||
; Dispatcher: JSL $E10000 with LDX #funcId.
|
||||
;
|
||||
; C ABI: arg0 (i16) in A, arg0 (i32) in A:X, arg1+ on stack
|
||||
; (caller-pushed, lo-word first for 32-bit values).
|
||||
; Each wrapper re-pushes args in Pascal order (high-word first
|
||||
; for 32-bit), allocates result space, dispatches, pops result.
|
||||
|
||||
.text
|
||||
|
||||
; Kgetpid(void) -> i16
|
||||
; toolset 3, func 0x0903
|
||||
.section .text.Kgetpid,"ax"
|
||||
.globl Kgetpid
|
||||
Kgetpid:
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
ldx #0x0903
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kkill(i16, i16, i32) -> i16
|
||||
; toolset 3, func 0x0A03
|
||||
.section .text.Kkill,"ax"
|
||||
.globl Kkill
|
||||
Kkill:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (2B) ---
|
||||
lda 8, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x0A03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kfork(i32, i32) -> i16
|
||||
; toolset 3, func 0x0B03
|
||||
.section .text.Kfork,"ax"
|
||||
.globl Kfork
|
||||
Kfork:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
ldx #0x0B03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgetpid_dup(void) -> i16
|
||||
; toolset 3, func 0x0903
|
||||
.section .text.Kgetpid_dup,"ax"
|
||||
.globl Kgetpid_dup
|
||||
Kgetpid_dup:
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
ldx #0x0903
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgetppid(i32) -> i16
|
||||
; toolset 3, func 0x4003
|
||||
.section .text.Kgetppid,"ax"
|
||||
.globl Kgetppid
|
||||
Kgetppid:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x4003
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kwait(i32, i32) -> i16
|
||||
; toolset 3, func 0x1703
|
||||
.section .text.Kwait,"ax"
|
||||
.globl Kwait
|
||||
Kwait:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
ldx #0x1703
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; K_execve(i32, i32, i32) -> i16
|
||||
; toolset 3, func 0x1D03
|
||||
.section .text.K_execve,"ax"
|
||||
.globl K_execve
|
||||
K_execve:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 20, s
|
||||
pha
|
||||
lda 20, s
|
||||
pha
|
||||
ldx #0x1D03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksignal(i16, i32, i32) -> i32
|
||||
; toolset 3, func 0x1603
|
||||
.section .text.Ksignal,"ax"
|
||||
.globl Ksignal
|
||||
Ksignal:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 20, s
|
||||
pha
|
||||
lda 20, s
|
||||
pha
|
||||
ldx #0x1603
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; Kalarm(i32, i32) -> i32
|
||||
; toolset 3, func 0x1E03
|
||||
.section .text.Kalarm,"ax"
|
||||
.globl Kalarm
|
||||
Kalarm:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x1E03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; Kalarm10(i32, i32) -> i32
|
||||
; toolset 3, func 0x4203
|
||||
.section .text.Kalarm10,"ax"
|
||||
.globl Kalarm10
|
||||
Kalarm10:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x4203
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; Ksigpause(i32, i32) -> i16
|
||||
; toolset 3, func 0x2103
|
||||
.section .text.Ksigpause,"ax"
|
||||
.globl Ksigpause
|
||||
Ksigpause:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
ldx #0x2103
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksigsetmask(i32, i32) -> i32
|
||||
; toolset 3, func 0x1B03
|
||||
.section .text.Ksigsetmask,"ax"
|
||||
.globl Ksigsetmask
|
||||
Ksigsetmask:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x1B03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; Ksigblock(i32, i32) -> i32
|
||||
; toolset 3, func 0x1C03
|
||||
.section .text.Ksigblock,"ax"
|
||||
.globl Ksigblock
|
||||
Ksigblock:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x1C03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; Kdup(i16, i32) -> i16
|
||||
; toolset 3, func 0x2203
|
||||
.section .text.Kdup,"ax"
|
||||
.globl Kdup
|
||||
Kdup:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x2203
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kdup2(i16, i16, i32) -> i16
|
||||
; toolset 3, func 0x2303
|
||||
.section .text.Kdup2,"ax"
|
||||
.globl Kdup2
|
||||
Kdup2:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (2B) ---
|
||||
lda 8, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x2303
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kpipe(i32, i32) -> i16
|
||||
; toolset 3, func 0x2403
|
||||
.section .text.Kpipe,"ax"
|
||||
.globl Kpipe
|
||||
Kpipe:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
ldx #0x2403
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kioctl(i16, i32, i32, i32) -> i16
|
||||
; toolset 3, func 0x2603
|
||||
.section .text.Kioctl,"ax"
|
||||
.globl Kioctl
|
||||
Kioctl:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 18, s
|
||||
pha
|
||||
lda 18, s
|
||||
pha
|
||||
; --- arg3 (4B) ---
|
||||
lda 26, s
|
||||
pha
|
||||
lda 26, s
|
||||
pha
|
||||
ldx #0x2603
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kstat(i32, i32, i32) -> i16
|
||||
; toolset 3, func 0x2703
|
||||
.section .text.Kstat,"ax"
|
||||
.globl Kstat
|
||||
Kstat:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 20, s
|
||||
pha
|
||||
lda 20, s
|
||||
pha
|
||||
ldx #0x2703
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kfstat(i16, i32, i32) -> i16
|
||||
; toolset 3, func 0x2803
|
||||
.section .text.Kfstat,"ax"
|
||||
.globl Kfstat
|
||||
Kfstat:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 18, s
|
||||
pha
|
||||
lda 18, s
|
||||
pha
|
||||
ldx #0x2803
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Klstat(i32, i32, i32) -> i16
|
||||
; toolset 3, func 0x2903
|
||||
.section .text.Klstat,"ax"
|
||||
.globl Klstat
|
||||
Klstat:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 20, s
|
||||
pha
|
||||
lda 20, s
|
||||
pha
|
||||
ldx #0x2903
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgetuid(i32) -> i16
|
||||
; toolset 3, func 0x2A03
|
||||
.section .text.Kgetuid,"ax"
|
||||
.globl Kgetuid
|
||||
Kgetuid:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x2A03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgetgid(i32) -> i16
|
||||
; toolset 3, func 0x2B03
|
||||
.section .text.Kgetgid,"ax"
|
||||
.globl Kgetgid
|
||||
Kgetgid:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x2B03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgeteuid(i32) -> i16
|
||||
; toolset 3, func 0x2C03
|
||||
.section .text.Kgeteuid,"ax"
|
||||
.globl Kgeteuid
|
||||
Kgeteuid:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x2C03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kgetegid(i32) -> i16
|
||||
; toolset 3, func 0x2D03
|
||||
.section .text.Kgetegid,"ax"
|
||||
.globl Kgetegid
|
||||
Kgetegid:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x2D03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksetuid(i16, i32) -> i16
|
||||
; toolset 3, func 0x2E03
|
||||
.section .text.Ksetuid,"ax"
|
||||
.globl Ksetuid
|
||||
Ksetuid:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x2E03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksetgid(i16, i32) -> i16
|
||||
; toolset 3, func 0x2F03
|
||||
.section .text.Ksetgid,"ax"
|
||||
.globl Ksetgid
|
||||
Ksetgid:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x2F03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ktcnewpgrp(i16, i32) -> i16
|
||||
; toolset 3, func 0x1803
|
||||
.section .text.Ktcnewpgrp,"ax"
|
||||
.globl Ktcnewpgrp
|
||||
Ktcnewpgrp:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x1803
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksettpgrp(i16, i32) -> i16
|
||||
; toolset 3, func 0x1903
|
||||
.section .text.Ksettpgrp,"ax"
|
||||
.globl Ksettpgrp
|
||||
Ksettpgrp:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x1903
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ktctpgrp(i16, i16, i32) -> i16
|
||||
; toolset 3, func 0x1A03
|
||||
.section .text.Ktctpgrp,"ax"
|
||||
.globl Ktctpgrp
|
||||
Ktctpgrp:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (2B) ---
|
||||
lda 8, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x1A03
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; K_getpgrp(i16, i32) -> i16
|
||||
; toolset 3, func 0x2503
|
||||
.section .text.K_getpgrp,"ax"
|
||||
.globl K_getpgrp
|
||||
K_getpgrp:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 10, s
|
||||
pha
|
||||
lda 10, s
|
||||
pha
|
||||
ldx #0x2503
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ksetpgrp(i16, i16, i32) -> i16
|
||||
; toolset 3, func 0x3403
|
||||
.section .text.Ksetpgrp,"ax"
|
||||
.globl Ksetpgrp
|
||||
Ksetpgrp:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (2B) ---
|
||||
lda 8, s
|
||||
pha
|
||||
; --- arg2 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x3403
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kkvm_open(i32) -> i16
|
||||
; toolset 3, func 0x1103
|
||||
.section .text.Kkvm_open,"ax"
|
||||
.globl Kkvm_open
|
||||
Kkvm_open:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
ldx #0x1103
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Kkvm_close(i32, i32) -> i16
|
||||
; toolset 3, func 0x1203
|
||||
.section .text.Kkvm_close,"ax"
|
||||
.globl Kkvm_close
|
||||
Kkvm_close:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (2 bytes) ---
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 12, s
|
||||
pha
|
||||
lda 12, s
|
||||
pha
|
||||
ldx #0x1203
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
rtl
|
||||
|
||||
; Ktimes(i32, i32) -> i32
|
||||
; toolset 3, func 0x3503
|
||||
.section .text.Ktimes,"ax"
|
||||
.globl Ktimes
|
||||
Ktimes:
|
||||
; --- stash arg0 (in A/X) ---
|
||||
sta 0xE0
|
||||
stx 0xE2
|
||||
; --- result space (4 bytes) ---
|
||||
pea 0
|
||||
pea 0
|
||||
; --- arg0 ---
|
||||
lda 0xE2
|
||||
pha
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
lda 14, s
|
||||
pha
|
||||
ldx #0x3503
|
||||
jsl 0xe10000
|
||||
pla ; result lo -> A
|
||||
plx ; result hi -> X
|
||||
rtl
|
||||
|
||||
; KSetGNOQuitRec(i16, i32, i16, i32) -> void
|
||||
; toolset 3, func 0x4103
|
||||
.section .text.KSetGNOQuitRec,"ax"
|
||||
.globl KSetGNOQuitRec
|
||||
KSetGNOQuitRec:
|
||||
; --- stash arg0 (in A) ---
|
||||
sta 0xE0
|
||||
; --- arg0 ---
|
||||
lda 0xE0
|
||||
pha
|
||||
; --- arg1 (4B) ---
|
||||
lda 8, s
|
||||
pha
|
||||
lda 8, s
|
||||
pha
|
||||
; --- arg2 (2B) ---
|
||||
lda 14, s
|
||||
pha
|
||||
; --- arg3 (4B) ---
|
||||
lda 20, s
|
||||
pha
|
||||
lda 20, s
|
||||
pha
|
||||
ldx #0x4103
|
||||
jsl 0xe10000
|
||||
rtl
|
||||
|
|
@ -51,6 +51,14 @@ typedef struct {
|
|||
u16 refNum;
|
||||
unsigned long position;
|
||||
} __GsosMarkRecGS;
|
||||
typedef struct {
|
||||
u16 pCount;
|
||||
void *pathname;
|
||||
u16 access;
|
||||
u16 fileType;
|
||||
unsigned long auxType;
|
||||
u16 storageType;
|
||||
} __GsosCreateParm;
|
||||
// Weak so programs that never call into the GS/OS file backend don't
|
||||
// drag iigsGsos.o into the link. fopen guards GSOS path on a NULL
|
||||
// check (see __gsosAvailable below).
|
||||
|
|
@ -62,6 +70,7 @@ extern u16 gsosGetEOF (__GsosEOFRecGS *p) __attribute__((weak));
|
|||
extern u16 gsosSetEOF (__GsosEOFRecGS *p) __attribute__((weak));
|
||||
extern u16 gsosSetMark(__GsosMarkRecGS *p) __attribute__((weak));
|
||||
extern u16 gsosGetMark(__GsosMarkRecGS *p) __attribute__((weak));
|
||||
extern u16 gsosCreate (__GsosCreateParm *p) __attribute__((weak));
|
||||
|
||||
static int __gsosAvailable(void) {
|
||||
// gsosOpen is the entry point — if iigsGsos.o is linked, all the
|
||||
|
|
@ -219,7 +228,15 @@ int atoi(const char *s) {
|
|||
// glue, or a console emulator) override this with a strong
|
||||
// definition. Marked `weak` so users can replace it.
|
||||
__attribute__((weak))
|
||||
// Console byte sink. Default writes the IIgs MAME console hook at $E2.
|
||||
// A hosted environment (e.g. GNO/ME) provides a strong __putByte that
|
||||
// routes to its console (see runtime/src/libcGno.c).
|
||||
extern void __putByte(char c) __attribute__((weak));
|
||||
|
||||
int putchar(int c) {
|
||||
if (__putByte)
|
||||
__putByte((char)c);
|
||||
else
|
||||
*(volatile char *)0xE2 = (char)c;
|
||||
return c;
|
||||
}
|
||||
|
|
@ -241,7 +258,14 @@ int puts(const char *s) {
|
|||
//
|
||||
// Callers wanting non-blocking input or Event Manager integration
|
||||
// should call ReadCh/GetNextEvent directly via iigs/toolbox.h.
|
||||
// Console byte source. Default polls the IIgs keyboard at $C000. A
|
||||
// hosted environment (GNO/ME) provides a strong __getByte that reads
|
||||
// its console (returns -1 on EOF).
|
||||
extern int __getByte(void) __attribute__((weak));
|
||||
|
||||
int getchar(void) {
|
||||
if (__getByte)
|
||||
return __getByte();
|
||||
volatile unsigned char *kbd = (volatile unsigned char *)0xC000;
|
||||
volatile unsigned char *strb = (volatile unsigned char *)0xC010;
|
||||
while (((*kbd) & 0x80) == 0) {
|
||||
|
|
@ -926,6 +950,22 @@ clock_t clock(void) {
|
|||
#define FILE_KIND_MEM 3
|
||||
#define FILE_KIND_GSOS 4
|
||||
|
||||
// Console byte sink for stderr. A hosted environment (GNO/ME) provides
|
||||
// a strong __putByteErr that targets the stderr stream (GNO fd 3); when
|
||||
// absent, stderr just shares stdout's sink (the historical behavior).
|
||||
extern void __putByteErr(char c) __attribute__((weak));
|
||||
|
||||
// Write one byte to the stdout (kind 1) or stderr (kind 2) console
|
||||
// stream. Single dispatch point so every stderr write path routes to
|
||||
// the right backend hook without duplicating the test.
|
||||
static int putcharStd(int kind, int c) {
|
||||
if (kind == FILE_KIND_STDERR && __putByteErr) {
|
||||
__putByteErr((char)c);
|
||||
return c;
|
||||
}
|
||||
return putchar(c);
|
||||
}
|
||||
|
||||
typedef struct __sFILE {
|
||||
u8 kind;
|
||||
u8 writable;
|
||||
|
|
@ -1006,7 +1046,7 @@ int mfsUnregister(const char *path) {
|
|||
int fputc(int c, FILE *stream) {
|
||||
if (!stream) return -1;
|
||||
if (stream->kind == FILE_KIND_STDOUT || stream->kind == FILE_KIND_STDERR)
|
||||
return putchar(c);
|
||||
return putcharStd(stream->kind, c);
|
||||
if (stream->kind == FILE_KIND_MEM) {
|
||||
if (!stream->writable) { stream->err = 1; return -1; }
|
||||
if (stream->pos >= stream->cap) { stream->err = 1; return -1; }
|
||||
|
|
@ -1030,7 +1070,7 @@ int fputc(int c, FILE *stream) {
|
|||
int fputs(const char *s, FILE *stream) {
|
||||
if (!stream || !s) return -1;
|
||||
if (stream->kind == FILE_KIND_STDOUT || stream->kind == FILE_KIND_STDERR) {
|
||||
while (*s) { putchar(*s); s++; }
|
||||
while (*s) { putcharStd(stream->kind, *s); s++; }
|
||||
return 0;
|
||||
}
|
||||
if (stream->kind == FILE_KIND_MEM || stream->kind == FILE_KIND_GSOS) {
|
||||
|
|
@ -1083,8 +1123,21 @@ int fprintf(FILE *stream, const char *fmt, ...) {
|
|||
|
||||
int vfprintf(FILE *stream, const char *fmt, va_list ap) {
|
||||
if (!stream) return -1;
|
||||
if (stream->kind == FILE_KIND_STDOUT || stream->kind == FILE_KIND_STDERR)
|
||||
if (stream->kind == FILE_KIND_STDOUT)
|
||||
return vprintf(fmt, ap);
|
||||
if (stream->kind == FILE_KIND_STDERR) {
|
||||
// Route formatted stderr output to the stderr console hook (GNO
|
||||
// fd 3) rather than vprintf's stdout putchar. Format into a
|
||||
// stack buffer, then emit byte-by-byte via putcharStd.
|
||||
char tmp[256];
|
||||
int n = vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||
if (n < 0) return -1;
|
||||
size_t outLen = ((size_t)n < sizeof(tmp) - 1)
|
||||
? (size_t)n : sizeof(tmp) - 1;
|
||||
for (size_t i = 0; i < outLen; i++)
|
||||
putcharStd(FILE_KIND_STDERR, tmp[i]);
|
||||
return n;
|
||||
}
|
||||
if (stream->kind == FILE_KIND_GSOS) {
|
||||
// Format into a stack buffer, then push to GS/OS via fwrite.
|
||||
// 256 bytes covers most format-string outputs; longer strings
|
||||
|
|
@ -1269,6 +1322,16 @@ FILE *fopen(const char *path, const char *mode) {
|
|||
// → NULL.
|
||||
if (!__gsosAvailable()) return (FILE *)0;
|
||||
if (__buildGSString(path) < 0) return (FILE *)0;
|
||||
// For write/append modes, Create the file first (GS/OS Open does
|
||||
// not create). A "duplicate filename" ($47) result is fine — the
|
||||
// file already exists. Guarded on the weak gsosCreate so bare
|
||||
// builds without it keep the old write-existing-only behavior.
|
||||
if (wantWrite && gsosCreate) {
|
||||
// access $C3 (destroy/rename/write/read), fileType $04 (TXT),
|
||||
// auxType 0, storageType 1 (seedling — GS/OS grows as needed).
|
||||
__GsosCreateParm cp = { 5, &__gsosPathBuf, 0xC3, 0x04, 0, 1 };
|
||||
(void)gsosCreate(&cp); // ignore result; Open reports real errors
|
||||
}
|
||||
// pCount=3 covers refNum + pathname + requestAccess. GS/OS 6.0.2
|
||||
// Open ($2010) requires requestAccess to be non-zero for any actual
|
||||
// open; passing only pCount=2 (refNum + pathname) leaves the access
|
||||
|
|
@ -1372,7 +1435,7 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
|||
if (stream->kind == FILE_KIND_STDOUT || stream->kind == FILE_KIND_STDERR) {
|
||||
size_t items = 0;
|
||||
while (items < nmemb) {
|
||||
for (size_t b = 0; b < size; b++) putchar(*in++);
|
||||
for (size_t b = 0; b < size; b++) putcharStd(stream->kind, *in++);
|
||||
items++;
|
||||
}
|
||||
return items;
|
||||
|
|
|
|||
295
runtime/src/libcGno.c
Normal file
295
runtime/src/libcGno.c
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
// libcGno.c — GNO/ME backend for our libc.
|
||||
//
|
||||
// Two roles:
|
||||
// 1. The GNO half of stdio: provides the GS/OS class-1 call wrappers
|
||||
// (gsosOpen/Read/Write/Close/...) that libc.c's FILE* layer calls
|
||||
// via weak externs, using GNO's INLINE GS/OS dispatch — so fopen /
|
||||
// fread / fwrite / fprintf / fgets to real GS/OS files Just Work.
|
||||
// Also provides the __putByte / __getByte console hooks libc.c
|
||||
// uses for putchar / getchar, routing them to the GNO console.
|
||||
// 2. POSIX process glue: __gnoStartup (argv parse + main), _exit, and
|
||||
// the fork/exec/wait/etc. wrappers over the K* kernel primitives.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gno/kernel.h>
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
// GS/OS class-1 paramblock shapes (layout-matched to libc.c's).
|
||||
typedef struct {
|
||||
uint16_t pCount;
|
||||
uint16_t refNum;
|
||||
void *dataBuffer;
|
||||
unsigned long requestCount;
|
||||
unsigned long transferCount;
|
||||
} GnoIORec;
|
||||
typedef struct { uint16_t pCount; uint16_t refNum; void *pathname; uint16_t requestAccess; } GnoOpenParm;
|
||||
typedef struct { uint16_t pCount; uint16_t refNum; } GnoRefNumRec;
|
||||
typedef struct { uint16_t pCount; uint16_t refNum; unsigned long val; } GnoEOFRec;
|
||||
typedef struct { uint16_t pCount; uint16_t refNum; unsigned long val; } GnoMarkRec;
|
||||
typedef struct { uint16_t pCount; void *pathname; uint16_t access; uint16_t fileType; unsigned long auxType; uint16_t storageType; } GnoCreateParm;
|
||||
|
||||
// GS/OS class-1 call numbers.
|
||||
#define GSOS_CREATE 0x2001
|
||||
#define GSOS_OPEN 0x2010
|
||||
#define GSOS_READ 0x2012
|
||||
#define GSOS_WRITE 0x2013
|
||||
#define GSOS_CLOSE 0x2014
|
||||
#define GSOS_SETMARK 0x2016
|
||||
#define GSOS_GETMARK 0x2017
|
||||
#define GSOS_SETEOF 0x2018
|
||||
#define GSOS_GETEOF 0x2019
|
||||
|
||||
// Generic inline-form GS/OS dispatch (asm helper, runtime/src/gnoGsos.s).
|
||||
// GNO's $E100A8 interceptor reads callNum + pBlock from the inline bytes
|
||||
// after the JSL; the helper self-modifies them and restores GNO's
|
||||
// process DP around the call. Returns the GS/OS error (0 = OK).
|
||||
extern uint16_t __gnoGsosCall(void *pBlock, unsigned short callNum);
|
||||
|
||||
|
||||
// ---- GS/OS file-call wrappers (override libc.c's weak externs) -------
|
||||
// libc.c's FILE* layer (fopen with FILE_KIND_GSOS, fread/fwrite/fgetc/
|
||||
// fputc/fclose) calls these. Routing them through GNO's inline dispatch
|
||||
// makes the whole buffered-stdio surface work for real GS/OS files.
|
||||
uint16_t gsosCreate(GnoCreateParm *p){ return __gnoGsosCall(p, GSOS_CREATE); }
|
||||
uint16_t gsosOpen(GnoOpenParm *p) { return __gnoGsosCall(p, GSOS_OPEN); }
|
||||
uint16_t gsosRead(GnoIORec *p) { return __gnoGsosCall(p, GSOS_READ); }
|
||||
uint16_t gsosWrite(GnoIORec *p) { return __gnoGsosCall(p, GSOS_WRITE); }
|
||||
uint16_t gsosClose(GnoRefNumRec *p) { return __gnoGsosCall(p, GSOS_CLOSE); }
|
||||
uint16_t gsosGetEOF(GnoEOFRec *p) { return __gnoGsosCall(p, GSOS_GETEOF); }
|
||||
uint16_t gsosSetEOF(GnoEOFRec *p) { return __gnoGsosCall(p, GSOS_SETEOF); }
|
||||
uint16_t gsosSetMark(GnoMarkRec *p) { return __gnoGsosCall(p, GSOS_SETMARK); }
|
||||
uint16_t gsosGetMark(GnoMarkRec *p) { return __gnoGsosCall(p, GSOS_GETMARK); }
|
||||
|
||||
|
||||
// ---- console hooks (override libc.c's weak __putByte/__getByte) ------
|
||||
// GNO fds are 1-based GS/OS refNums mapped through the per-process
|
||||
// open-files table by the kernel's GS/OS interceptor (GNORdWr,
|
||||
// kern/gno/gsos.asm:1794): stdin = 1, stdout = 2, stderr = 3
|
||||
// (include/unistd.h:51-53; main.c:388-390). A GS/OS Read/Write with
|
||||
// that refNum is the exact mechanism GNO's own libc read()/write() use
|
||||
// (lib/libc/sys/syscall.c:756/1271) -- the interceptor routes it to the
|
||||
// file ('<'), pipe ('|'), or TTY behind the fd, so redirection is
|
||||
// honored transparently. putchar/getchar in libc.c route here; the
|
||||
// rest of stdio (puts/printf/fgets/...) builds on them.
|
||||
//
|
||||
// GNO 1-based fd indices for the inherited standard streams.
|
||||
#define GNO_FD_STDIN 1
|
||||
#define GNO_FD_STDOUT 2
|
||||
#define GNO_FD_STDERR 3
|
||||
|
||||
// GS/OS error returned at end-of-file ($4C). GNO's read() treats this
|
||||
// as a successful (possibly short) transfer, not a hard error
|
||||
// (syscall.c:765; texttool.asm:2250).
|
||||
#define GSOS_ERR_EOF 0x4C
|
||||
|
||||
void __putByte(char c) {
|
||||
if (c == '\n') c = '\r'; // GNO console (Apple II TTY) wants CR
|
||||
GnoIORec r = { 4, GNO_FD_STDOUT, &c, 1, 0 };
|
||||
__gnoGsosCall(&r, GSOS_WRITE);
|
||||
}
|
||||
|
||||
// Strong override for stderr (libc.c routes FILE_KIND_STDERR here).
|
||||
// stderr is fd 3 -- distinct from stdout so '2>file' redirection works.
|
||||
void __putByteErr(char c) {
|
||||
if (c == '\n') c = '\r';
|
||||
GnoIORec r = { 4, GNO_FD_STDERR, &c, 1, 0 };
|
||||
__gnoGsosCall(&r, GSOS_WRITE);
|
||||
}
|
||||
|
||||
int __getByte(void) {
|
||||
unsigned char c;
|
||||
GnoIORec r = { 4, GNO_FD_STDIN, &c, 1, 0 };
|
||||
uint16_t err = __gnoGsosCall(&r, GSOS_READ);
|
||||
// Match GNO's read(): err 0 OR $4C is a valid transfer; only a
|
||||
// zero-byte transfer is genuine EOF. Reading refNum 1 reaches the
|
||||
// live inherited stdin -- the file behind '<', the pipe behind '|',
|
||||
// or the console TTY -- via the kernel's GNORdWr interceptor.
|
||||
if ((err != 0 && err != GSOS_ERR_EOF) || r.transferCount != 1)
|
||||
return -1; // EOF / error
|
||||
return (int)c;
|
||||
}
|
||||
|
||||
|
||||
// ---- raw POSIX read/write (used by demos that want fd-level I/O) -----
|
||||
// POSIX callers pass Unix 0/1/2; GNO's fd table is 1-based (stdin = 1),
|
||||
// so translate 0/1/2 -> 1/2/3 in one place. Any other fd is assumed to
|
||||
// already be a GNO 1-based fd (e.g. from pipe()/dup()) and passed
|
||||
// straight through.
|
||||
static uint16_t gnoFd(int fd) {
|
||||
if (fd >= 0 && fd <= 2)
|
||||
return (uint16_t)(fd + 1);
|
||||
return (uint16_t)fd;
|
||||
}
|
||||
|
||||
|
||||
long write(int fd, const void *buf, unsigned long n) {
|
||||
GnoIORec r = { 4, gnoFd(fd), (void *)buf, n, 0 };
|
||||
if (__gnoGsosCall(&r, GSOS_WRITE) != 0) return -1;
|
||||
return (long)r.transferCount;
|
||||
}
|
||||
|
||||
long read(int fd, void *buf, unsigned long n) {
|
||||
GnoIORec r = { 4, gnoFd(fd), buf, n, 0 };
|
||||
uint16_t err = __gnoGsosCall(&r, GSOS_READ);
|
||||
if (err != 0 && err != GSOS_ERR_EOF) return -1;
|
||||
return (long)r.transferCount;
|
||||
}
|
||||
|
||||
|
||||
// Tokenize cmdline in-place using simple whitespace rules. GNO's
|
||||
// shell does proper quote handling — we'll match that once we have a
|
||||
// test harness to drive it. For the initial hello-world the cmdline
|
||||
// is just the program name (no args), so a degenerate parser suffices.
|
||||
//
|
||||
// Writes into the static argv[] and writable copy buf[]. Caps argc
|
||||
// at 31; longer command lines have their tail args silently dropped.
|
||||
#define ARG_MAX 32
|
||||
#define CMD_MAX 256
|
||||
|
||||
static char argBuf[CMD_MAX];
|
||||
static char *argVec[ARG_MAX];
|
||||
|
||||
|
||||
static int parseCmdline(const char *cmd, char ***argvOut) {
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
// Copy cmdline into our writable buffer up to CMD_MAX-1.
|
||||
while (i < CMD_MAX - 1 && cmd[i]) {
|
||||
argBuf[i] = cmd[i];
|
||||
i++;
|
||||
}
|
||||
argBuf[i] = 0;
|
||||
|
||||
// Tokenize on whitespace. Replace separator runs with NULs,
|
||||
// record argv entries pointing at the first non-NUL char of each
|
||||
// run.
|
||||
char *p = argBuf;
|
||||
while (n < ARG_MAX - 1 && *p) {
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
if (!*p)
|
||||
break;
|
||||
argVec[n++] = p;
|
||||
while (*p && *p != ' ' && *p != '\t')
|
||||
p++;
|
||||
if (*p)
|
||||
*p++ = 0;
|
||||
}
|
||||
argVec[n] = 0;
|
||||
*argvOut = argVec;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// crt0Gno.s entry point. Receives the command-line pointer the kernel
|
||||
// handed us (Y:X on entry; crt0 forwards it as a ptr32 arg here).
|
||||
// GNO prepends an 8-byte "BYTEWRKS" signature to the command line
|
||||
// (kern/gno/sys.c builds child->args = "BYTEWRKS" + name; ~GNO_PARSEARG
|
||||
// skips it with `add4 commandline,#8`). Skip those 8 bytes, parse into
|
||||
// argc/argv, invoke main(), and return to crt0 for the QUIT call.
|
||||
int __gnoStartup(const char *cmdline) {
|
||||
char **argv;
|
||||
int argc;
|
||||
if (cmdline) cmdline += 8; // skip "BYTEWRKS" prefix
|
||||
argc = parseCmdline(cmdline, &argv);
|
||||
return main(argc, argv);
|
||||
}
|
||||
|
||||
|
||||
// GS/OS QUIT ($2029) paramblock. pCount=0 => plain QUIT: GNO's
|
||||
// CommonQuit reaps the process and returns control to the launcher (gsh).
|
||||
typedef struct { uint16_t pCount; } GnoQuitParm;
|
||||
|
||||
#define GSOS_QUIT 0x2029
|
||||
|
||||
// _exit: GNO/ME program termination via GS/OS QUIT, issued through the
|
||||
// SAME inline GS/OS dispatch (__gnoGsosCall) as every other call here.
|
||||
//
|
||||
// Critical: this MUST use the inline form, not the stack-based form
|
||||
// (`ldx #$2029 ; jsl $e100a8` with the pblock pushed). GNO patches
|
||||
// $E100A8 to OurGSOS, which reads the call number + pblock from the 6
|
||||
// inline bytes AFTER the jsl. The stack form leaves those inline bytes
|
||||
// as whatever opcode follows, so OurGSOS mis-dispatches the QUIT and the
|
||||
// process is left restartable — GNO then RE-RUNS main() (observed:
|
||||
// main executes twice, silently draining redirected stdin on the first
|
||||
// pass). Routing QUIT through __gnoGsosCall (inline form + process-DP
|
||||
// restore) terminates cleanly, so main() runs exactly once.
|
||||
__attribute__((noreturn))
|
||||
void _exit(int status) {
|
||||
(void)status;
|
||||
GnoQuitParm q = { 0 }; // pCount=0 — plain QUIT to launcher
|
||||
__gnoGsosCall(&q, GSOS_QUIT); // inline dispatch; does not return
|
||||
for (;;) { } // unreachable
|
||||
}
|
||||
|
||||
|
||||
// Stubs for the K*-wrapped POSIX surface. These mirror what
|
||||
// runtime/src/gnoKernel.s already provides; we just rename them.
|
||||
// Errno handling: each K* takes a `int *errno` arg; on failure the
|
||||
// kernel writes the errno value there and returns -1. Our wrappers
|
||||
// stash it into the global `errno` variable.
|
||||
//
|
||||
// Only the minimum needed for the demo is non-trivial — the rest
|
||||
// are scaffold-only and will be filled in as we add tests.
|
||||
|
||||
extern int errno; // defined in libc.c
|
||||
|
||||
|
||||
int fork(void) {
|
||||
int err = 0;
|
||||
int r = Kfork(0, &err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int kill(int pid, int sig) {
|
||||
int err = 0;
|
||||
int r = Kkill(pid, sig, &err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int getpid(void) {
|
||||
return Kgetpid();
|
||||
}
|
||||
|
||||
|
||||
int getppid(void) {
|
||||
int err = 0;
|
||||
int r = Kgetppid(&err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int dup(int oldfd) {
|
||||
int err = 0;
|
||||
int r = Kdup(oldfd, &err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int dup2(int oldfd, int newfd) {
|
||||
int err = 0;
|
||||
int r = Kdup2(oldfd, newfd, &err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int pipe(int fds[2]) {
|
||||
int err = 0;
|
||||
int r = Kpipe(fds, &err);
|
||||
if (r < 0) errno = err;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
unsigned long alarm(unsigned long seconds) {
|
||||
int err = 0;
|
||||
return Kalarm((void *)seconds, &err);
|
||||
}
|
||||
|
|
@ -204,9 +204,6 @@ static void emitDouble(double v, int prec, char spec) {
|
|||
|
||||
|
||||
// fmt is arg0 (A register); see banner comment for why the order matters.
|
||||
// Previously optnone (slot-alias bug under p:16:16; see
|
||||
// feedback_snprintf_va_arg_slot_alias.md). Re-enabled greedy under
|
||||
// ptr32 — testing whether the bug recurs.
|
||||
static int format(const char *fmt, va_list ap) {
|
||||
while (*fmt) {
|
||||
char c = *fmt++;
|
||||
|
|
|
|||
236
scripts/genGnoKernel.py
Normal file
236
scripts/genGnoKernel.py
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
#!/usr/bin/env python3
|
||||
# genGnoKernel.py — generate wrappers for the GNO kernel toolset.
|
||||
#
|
||||
# The GNO kernel is implemented as Apple IIgs user toolset $03. Each
|
||||
# kernel function is identified by a 16-bit number $XX03 where XX is
|
||||
# the function index and 03 is the toolset. The dispatcher is the
|
||||
# standard IIgs tool dispatcher at $E10000.
|
||||
#
|
||||
# Function list is hard-coded from include/gno/kerntool.h in the GNO
|
||||
# Consortium source (https://github.com/GnoConsortium/gno). The
|
||||
# canonical ORCA-style signature is preserved in a comment.
|
||||
#
|
||||
# Output: runtime/src/gnoKernel.s — asm wrappers callable from our C
|
||||
# ABI (arg0 in A, arg0 i32 in A:X, rest pushed RTL on stack). Each
|
||||
# wrapper re-pushes args in toolbox/Pascal order (high-word first for
|
||||
# 32-bit values), allocates result space, JSLs $E10000, pops the
|
||||
# result back into A:X if non-void.
|
||||
#
|
||||
# Run after editing the function table:
|
||||
# python3 scripts/genGnoKernel.py
|
||||
#
|
||||
# The libc layer in runtime/src/libcGno.c wraps these K* primitives
|
||||
# into POSIX names (fork, exec, wait, etc.).
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
OUT_ASM = Path("/home/scott/claude/llvm816/runtime/src/gnoKernel.s")
|
||||
OUT_HEADER = Path("/home/scott/claude/llvm816/runtime/include/gno/kernel.h")
|
||||
|
||||
# Each entry: (funcId, name, retSize, [argSize, ...])
|
||||
# Sizes in bytes (2 = i16, 4 = i32 / ptr32). Names follow ORCA's K* prefix.
|
||||
#
|
||||
# Pulled from include/gno/kerntool.h in the GNO Consortium repo.
|
||||
SYSCALLS = [
|
||||
# ---- Process control ----
|
||||
(0x0903, "Kgetpid", 2, []), # () -> int
|
||||
(0x0A03, "Kkill", 2, [2, 2, 4]), # (pid, sig, *errno) -> int
|
||||
(0x0B03, "Kfork", 2, [4, 4]), # (*subr, *errno) -> int
|
||||
(0x0903, "Kgetpid_dup", 2, []), # alias kept for sanity check
|
||||
(0x4003, "Kgetppid", 2, [4]), # (*errno) -> int
|
||||
(0x1703, "Kwait", 2, [4, 4]), # (*status, *errno) -> int
|
||||
(0x1D03, "K_execve", 2, [4, 4, 4]), # (*file, *cmdline, *err) -> int
|
||||
(0x1603, "Ksignal", 4, [2, 4, 4]), # (sig, func_ptr, *err) -> sig_t
|
||||
(0x1E03, "Kalarm", 4, [4, 4]), # (seconds, *errno) -> longword
|
||||
(0x4203, "Kalarm10", 4, [4, 4]), # (seconds-tenths, *errno) -> longword
|
||||
(0x2103, "Ksigpause", 2, [4, 4]), # (mask, *errno) -> int
|
||||
(0x1B03, "Ksigsetmask", 4, [4, 4]), # (mask, *errno) -> longword
|
||||
(0x1C03, "Ksigblock", 4, [4, 4]), # (mask, *errno) -> longword
|
||||
|
||||
# ---- File descriptors ----
|
||||
(0x2203, "Kdup", 2, [2, 4]), # (oldfd, *errno) -> int
|
||||
(0x2303, "Kdup2", 2, [2, 2, 4]), # (oldfd, newfd, *errno) -> int
|
||||
(0x2403, "Kpipe", 2, [4, 4]), # (*fildes[2], *errno) -> int
|
||||
(0x2603, "Kioctl", 2, [2, 4, 4, 4]), # (fd, req:ulong, *ptr, *errno) -> int
|
||||
|
||||
# ---- stat ----
|
||||
(0x2703, "Kstat", 2, [4, 4, 4]), # (*path, *sbuf, *errno) -> int
|
||||
(0x2803, "Kfstat", 2, [2, 4, 4]), # (fd, *sbuf, *errno) -> int
|
||||
(0x2903, "Klstat", 2, [4, 4, 4]), # (*path, *sbuf, *errno) -> int
|
||||
|
||||
# ---- IDs ----
|
||||
(0x2A03, "Kgetuid", 2, [4]), # (*errno) -> int
|
||||
(0x2B03, "Kgetgid", 2, [4]), # (*errno) -> int
|
||||
(0x2C03, "Kgeteuid", 2, [4]), # (*errno) -> int
|
||||
(0x2D03, "Kgetegid", 2, [4]), # (*errno) -> int
|
||||
(0x2E03, "Ksetuid", 2, [2, 4]), # (uid, *errno) -> int
|
||||
(0x2F03, "Ksetgid", 2, [2, 4]), # (gid, *errno) -> int
|
||||
|
||||
# ---- Process groups / TTY ----
|
||||
(0x1803, "Ktcnewpgrp", 2, [2, 4]), # (fdtty, *errno) -> int
|
||||
(0x1903, "Ksettpgrp", 2, [2, 4]), # (fdtty, *errno) -> int
|
||||
(0x1A03, "Ktctpgrp", 2, [2, 2, 4]), # (fdtty, pid, *err) -> int
|
||||
(0x2503, "K_getpgrp", 2, [2, 4]), # (pid, *errno) -> pid_t
|
||||
(0x3403, "Ksetpgrp", 2, [2, 2, 4]), # (pid, pgrp, *errno) -> int
|
||||
|
||||
# ---- Kernel VM (process inspection) ----
|
||||
(0x1103, "Kkvm_open", 2, [4]), # (*errno) -> int
|
||||
(0x1203, "Kkvm_close", 2, [4, 4]), # (kvmt, *errno) -> int
|
||||
|
||||
# ---- Misc ----
|
||||
(0x3503, "Ktimes", 4, [4, 4]), # (*tms, *errno) -> clock_t
|
||||
|
||||
# ---- Quit setup ----
|
||||
(0x4103, "KSetGNOQuitRec", 0, [2, 4, 2, 4]), # (pCount, GSStringPtr, flags, *err) -> void
|
||||
]
|
||||
|
||||
DISPATCHER = 0xE10000
|
||||
|
||||
|
||||
def emitWrapper(funcId, name, retSize, argSizes):
|
||||
"""Emit one .s function body for the given GNO kernel call."""
|
||||
lines = []
|
||||
argTypes = [f"i{size*8}" for size in argSizes]
|
||||
lines.append(f"; {name}({', '.join(argTypes) or 'void'}) -> "
|
||||
f"{'void' if retSize == 0 else f'i{retSize*8}'}")
|
||||
lines.append(f"; toolset 3, func 0x{funcId:04X}")
|
||||
lines.append(f"\t.section .text.{name},\"ax\"")
|
||||
lines.append(f"\t.globl {name}")
|
||||
lines.append(f"{name}:")
|
||||
|
||||
scratchDP = 0xE0
|
||||
firstArgIs32 = bool(argSizes) and argSizes[0] == 4
|
||||
|
||||
# Stash arg0 if any args. arg0 in A (i16) or A:X (i32).
|
||||
if argSizes:
|
||||
lines.append(f"\t; --- stash arg0 (in A{'/X' if firstArgIs32 else ''}) ---")
|
||||
lines.append(f"\tsta 0x{scratchDP:02X}")
|
||||
if firstArgIs32:
|
||||
lines.append(f"\tstx 0x{scratchDP + 2:02X}")
|
||||
|
||||
# Result space (rounded up to whole words).
|
||||
resultWords = (retSize + 1) // 2
|
||||
if resultWords > 0:
|
||||
lines.append(f"\t; --- result space ({retSize} bytes) ---")
|
||||
for _ in range(resultWords):
|
||||
lines.append("\tpea 0")
|
||||
|
||||
# Push args in Pascal order (high-word first for 32-bit).
|
||||
pushedBytes = resultWords * 2
|
||||
|
||||
# arg0.
|
||||
if argSizes:
|
||||
lines.append("\t; --- arg0 ---")
|
||||
if firstArgIs32:
|
||||
lines.append(f"\tlda 0x{scratchDP + 2:02X}")
|
||||
lines.append("\tpha")
|
||||
pushedBytes += 2
|
||||
lines.append(f"\tlda 0x{scratchDP:02X}")
|
||||
lines.append("\tpha")
|
||||
pushedBytes += 2
|
||||
|
||||
# arg1+.
|
||||
stackArgOffset = 4 # caller's first stack arg (after 3-byte JSL ret addr)
|
||||
for i, size in enumerate(argSizes[1:], start=1):
|
||||
lines.append(f"\t; --- arg{i} ({size}B) ---")
|
||||
if size <= 2:
|
||||
lines.append(f"\tlda {stackArgOffset + pushedBytes}, s")
|
||||
lines.append("\tpha")
|
||||
pushedBytes += 2
|
||||
stackArgOffset += 2
|
||||
elif size == 4:
|
||||
# High word first. Caller pushed low-word-first, so HI is at
|
||||
# caller offset +2. After PHA, the LO becomes accessible at
|
||||
# the SAME stack-rel offset (PHA shifted SP by 2).
|
||||
lines.append(f"\tlda {stackArgOffset + pushedBytes + 2}, s")
|
||||
lines.append("\tpha")
|
||||
pushedBytes += 2
|
||||
lines.append(f"\tlda {stackArgOffset + pushedBytes}, s")
|
||||
lines.append("\tpha")
|
||||
pushedBytes += 2
|
||||
stackArgOffset += 4
|
||||
else:
|
||||
raise RuntimeError(f"unhandled arg size {size} in {name}")
|
||||
|
||||
# Dispatch.
|
||||
lines.append(f"\tldx #0x{funcId:04X}")
|
||||
lines.append(f"\tjsl 0x{DISPATCHER:x}")
|
||||
|
||||
# Pop result.
|
||||
if resultWords > 0:
|
||||
lines.append("\tpla ; result lo -> A")
|
||||
if resultWords == 2:
|
||||
lines.append("\tplx ; result hi -> X")
|
||||
lines.append("\trtl")
|
||||
lines.append("")
|
||||
return lines
|
||||
|
||||
|
||||
def emitHeader():
|
||||
"""Generate a C header with extern decls for use by libc."""
|
||||
hLines = [
|
||||
"// AUTOGENERATED by scripts/genGnoKernel.py — DO NOT EDIT.",
|
||||
"// GNO kernel toolset $03 wrappers, callable from C.",
|
||||
"// Convention: each K* returns the kernel result (or -1 on error);",
|
||||
"// the last argument is `int *errno` and gets the kernel's errno.",
|
||||
"//",
|
||||
"// These are LOW-LEVEL primitives — libc routines in libcGno.c",
|
||||
"// wrap them into POSIX-named fork/exec/wait/etc.",
|
||||
"#ifndef GNO_KERNEL_H",
|
||||
"#define GNO_KERNEL_H",
|
||||
"",
|
||||
"#include <stdint.h>",
|
||||
"",
|
||||
]
|
||||
for funcId, name, retSize, argSizes in SYSCALLS:
|
||||
# Skip the sanity-check duplicate.
|
||||
if name.endswith("_dup"):
|
||||
continue
|
||||
retC = "void" if retSize == 0 else (
|
||||
"int" if retSize == 2 else "unsigned long")
|
||||
argC = []
|
||||
for i, size in enumerate(argSizes):
|
||||
t = "int" if size == 2 else "void *"
|
||||
argC.append(f"{t} a{i}")
|
||||
hLines.append(f"extern {retC} {name}({', '.join(argC) or 'void'});"
|
||||
f" // 0x{funcId:04X}")
|
||||
hLines.append("")
|
||||
hLines.append("#endif")
|
||||
hLines.append("")
|
||||
return hLines
|
||||
|
||||
|
||||
def main():
|
||||
asmLines = [
|
||||
"; AUTOGENERATED by scripts/genGnoKernel.py — DO NOT EDIT by hand.",
|
||||
";",
|
||||
"; GNO/ME kernel toolset $03 wrappers.",
|
||||
"; Dispatcher: JSL $E10000 with LDX #funcId.",
|
||||
";",
|
||||
"; C ABI: arg0 (i16) in A, arg0 (i32) in A:X, arg1+ on stack",
|
||||
"; (caller-pushed, lo-word first for 32-bit values).",
|
||||
"; Each wrapper re-pushes args in Pascal order (high-word first",
|
||||
"; for 32-bit), allocates result space, dispatches, pops result.",
|
||||
"",
|
||||
"\t.text",
|
||||
"",
|
||||
]
|
||||
seen = set()
|
||||
for funcId, name, retSize, argSizes in SYSCALLS:
|
||||
if name in seen:
|
||||
continue
|
||||
seen.add(name)
|
||||
asmLines.extend(emitWrapper(funcId, name, retSize, argSizes))
|
||||
|
||||
OUT_ASM.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT_ASM.write_text("\n".join(asmLines))
|
||||
print(f"wrote {OUT_ASM} ({len(asmLines)} lines, "
|
||||
f"{len(seen) - 1} wrappers)")
|
||||
|
||||
OUT_HEADER.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT_HEADER.write_text("\n".join(emitHeader()))
|
||||
print(f"wrote {OUT_HEADER}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
171
scripts/runInGno.sh
Executable file
171
scripts/runInGno.sh
Executable file
|
|
@ -0,0 +1,171 @@
|
|||
#!/usr/bin/env bash
|
||||
# runInGno.sh — run a llvm816-built shell command under real GNO/ME in MAME.
|
||||
#
|
||||
# Boots GS/OS 6.0.4 + GNO/ME 2.0.6, logs in as root, runs the given
|
||||
# program at the gsh prompt, and polls bank-2 memory for a signature.
|
||||
#
|
||||
# Usage:
|
||||
# runInGno.sh <program.omf> [--check addr=hexval ...] [--snapshots]
|
||||
#
|
||||
# <program.omf> a GS/OS-loadable OMF (NOT a flat link816 .bin).
|
||||
# Build it through omfEmit — see demos/buildGno.sh.
|
||||
# --check A=V after the program runs, assert mem[A] (16-bit) == V.
|
||||
# --snapshots save PNGs of each boot/login/run stage to
|
||||
# $GNO_SNAP_DIR (default /tmp/gnosnaps) for headless
|
||||
# debugging.
|
||||
#
|
||||
# The program is placed on the disk as /bin/<name> (lowercased) and as
|
||||
# /HELLO, so it can be invoked by bare name at the gsh prompt.
|
||||
#
|
||||
# Boot timeline (frame numbers tuned against MAME apple2gs; override
|
||||
# via the GNO_*_FRAMES env vars if your MAME build differs):
|
||||
# ~3600 GS/OS Finder ready, GNO + System Disk icons visible
|
||||
# 3800 select GNO volume, Open Apple+O to open it
|
||||
# 4600 select KERN, Open Apple+O to launch the GNO kernel
|
||||
# ~16000 getty shows "login:" prompt
|
||||
# 16200 type "root\n" (root has empty password)
|
||||
# ~18000 gsh "% " prompt
|
||||
# 18800 type "<name>\n" to run the program
|
||||
# 19500+ poll bank-2 markers
|
||||
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
PROG="${1:-}"
|
||||
shift || true
|
||||
[ -n "$PROG" ] || { echo "usage: $0 <program.omf> [--check A=V ...] [--snapshots]" >&2; exit 2; }
|
||||
[ -f "$PROG" ] || { echo "program not found: $PROG" >&2; exit 2; }
|
||||
|
||||
CADIUS="$ROOT/tools/cadius/cadius"
|
||||
SYSDISK="$ROOT/tools/gsos/6.0.4 - System.Disk.po"
|
||||
BASE="$ROOT/tools/gno/gnobase.po"
|
||||
|
||||
[ -x "$CADIUS" ] || { echo "cadius missing" >&2; exit 1; }
|
||||
[ -f "$SYSDISK" ] || { echo "GS/OS System Disk missing: $SYSDISK" >&2; exit 1; }
|
||||
[ -f "$BASE" ] || { echo "GNO base disk missing — run tools/gno/buildDisk.sh" >&2; exit 1; }
|
||||
|
||||
SNAPSHOTS=0
|
||||
CHECK_LUA=""
|
||||
ADDR_LIST=(); EXPECT_LIST=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--snapshots) SNAPSHOTS=1; shift;;
|
||||
--check)
|
||||
shift
|
||||
while [ $# -gt 0 ] && [[ "$1" != "--"* ]]; do
|
||||
a="${1%=*}"; v="${1#*=}"
|
||||
ADDR_LIST+=("$a"); EXPECT_LIST+=("$v")
|
||||
shift
|
||||
done;;
|
||||
*) echo "unknown arg: $1" >&2; exit 2;;
|
||||
esac
|
||||
done
|
||||
|
||||
WORK=$(mktemp -d -t gno-run.XXXXXX)
|
||||
trap 'rm -rf "$WORK"' EXIT
|
||||
DATA="$WORK/data.po"
|
||||
cp "$BASE" "$DATA"
|
||||
|
||||
NAME=$(basename "$PROG" | sed 's/\.[^.]*$//' | tr '[:upper:]' '[:lower:]' | cut -c1-15)
|
||||
cp "$PROG" "$WORK/${NAME}#B50100"
|
||||
cp "$PROG" "$WORK/HELLO#B50100"
|
||||
"$CADIUS" ADDFILE "$DATA" /GNO.BOOT/bin "$WORK/${NAME}#B50100" >/dev/null
|
||||
"$CADIUS" ADDFILE "$DATA" /GNO.BOOT "$WORK/HELLO#B50100" >/dev/null
|
||||
# Optional: drop an extra TXT file in /home/root (the login cwd) for
|
||||
# stdin-redirect tests. Reference it relatively or as /home/root/<name>.
|
||||
if [ -n "${GNO_ADDFILE:-}" ] && [ -f "${GNO_ADDFILE}" ]; then
|
||||
cp "${GNO_ADDFILE}" "$WORK/$(basename "${GNO_ADDFILE}")#040000"
|
||||
"$CADIUS" ADDFILE "$DATA" /GNO.BOOT/home/root "$WORK/$(basename "${GNO_ADDFILE}")#040000" >/dev/null
|
||||
fi
|
||||
|
||||
SNAPDIR="${GNO_SNAP_DIR:-/tmp/gnosnaps}"
|
||||
if [ "$SNAPSHOTS" = 1 ]; then
|
||||
mkdir -p "$SNAPDIR"; rm -rf "$SNAPDIR/apple2gs"/* 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Frame tuning.
|
||||
F_VOL=${GNO_VOL_FRAMES:-3800}
|
||||
F_KERN=${GNO_KERN_FRAMES:-4600}
|
||||
F_LOGIN=${GNO_LOGIN_FRAMES:-16200}
|
||||
F_RUN=${GNO_RUN_FRAMES:-18800}
|
||||
F_POLL=${GNO_POLL_FRAMES:-20000}
|
||||
F_END=${GNO_END_FRAMES:-21000}
|
||||
SECS=${MAME_SECS:-380}
|
||||
|
||||
# Optional: inject a line into the console after the program launches
|
||||
# (for testing interactive stdin reads). GNO_STDIN is the text; it is
|
||||
# posted with a trailing newline at frame F_RUN + GNO_STDIN_DELAY.
|
||||
STDIN_STEP=""
|
||||
if [ -n "${GNO_STDIN:-}" ]; then
|
||||
STDIN_STEP="{$((F_RUN + ${GNO_STDIN_DELAY:-1600})), function() nat:post(\"${GNO_STDIN}\\n\") end},"
|
||||
fi
|
||||
|
||||
# Build the bank-2 probe Lua for each --check.
|
||||
for i in "${!ADDR_LIST[@]}"; do
|
||||
CHECK_LUA="$CHECK_LUA print(string.format('MAME-READ addr=0x%06x val=0x%04x', ${ADDR_LIST[$i]}, mem:read_u16(${ADDR_LIST[$i]})))"$'\n'
|
||||
done
|
||||
|
||||
LUA="$WORK/gno.lua"
|
||||
cat > "$LUA" <<EOF
|
||||
local nat = manager.machine.natkeyboard
|
||||
local frame = 0
|
||||
local idx = 1
|
||||
local function gf(p, n) local x = manager.machine.ioport.ports[p]; return x and x.fields[n] end
|
||||
local key_cmd = gf(":macadb:KEY3", "Command / Open Apple")
|
||||
local function press(f) if f then f:set_value(1) end end
|
||||
local function release(f) if f then f:set_value(0) end end
|
||||
local snaps = $SNAPSHOTS
|
||||
local function snap(t) if snaps == 1 then manager.machine.video:snapshot() end; print("MAME-STAGE "..t.." frame="..frame) end
|
||||
|
||||
local steps = {
|
||||
{$F_VOL, function() nat:post("G") end},
|
||||
{$F_VOL + 200, function() press(key_cmd) end},
|
||||
{$F_VOL + 206, function() nat:post("o") end},
|
||||
{$F_VOL + 260, function() release(key_cmd) end},
|
||||
{$F_VOL + 400, function() snap("vol-open") end},
|
||||
{$F_KERN, function() nat:post("K") end},
|
||||
{$F_KERN + 200, function() press(key_cmd) end},
|
||||
{$F_KERN + 206, function() nat:post("o") end},
|
||||
{$F_KERN + 260, function() release(key_cmd) end},
|
||||
{$F_LOGIN - 200,function() snap("login") end},
|
||||
{$F_LOGIN, function() nat:post("root\n") end},
|
||||
{$F_RUN - 200, function() snap("shell") end},
|
||||
{$F_RUN, function() nat:post("${GNO_RUNCMD:-$NAME}\n") end},
|
||||
${STDIN_STEP}
|
||||
{$F_POLL, function() snap("running") end},
|
||||
}
|
||||
emu.register_frame_done(function()
|
||||
frame = frame + 1
|
||||
while idx <= #steps and frame >= steps[idx][1] do steps[idx][2](); idx = idx + 1 end
|
||||
if frame == $F_POLL then
|
||||
local mem = manager.machine.devices[":maincpu"].spaces["program"]
|
||||
$CHECK_LUA
|
||||
end
|
||||
if frame > $F_END then manager.machine:exit() end
|
||||
end)
|
||||
EOF
|
||||
|
||||
OUT=$(SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy timeout "${MAME_WALL:-120}" mame apple2gs \
|
||||
-rompath "$ROOT/tools/mame/roms" \
|
||||
-flop3 "$SYSDISK" -flop4 "$DATA" \
|
||||
-snapshot_directory "$SNAPDIR" \
|
||||
-autoboot_script "$LUA" \
|
||||
-video none -sound none -nothrottle -seconds_to_run "$SECS" 2>&1)
|
||||
|
||||
echo "$OUT" | grep -E "^MAME-" || true
|
||||
|
||||
rc=0
|
||||
for i in "${!ADDR_LIST[@]}"; do
|
||||
a="${ADDR_LIST[$i]}"; exp="${EXPECT_LIST[$i]}"
|
||||
got=$(echo "$OUT" | awk -v a="$a" 'index($0, "addr=" a) { print $NF }' | tail -1)
|
||||
got="${got#val=}"
|
||||
want="0x$(printf '%04x' "0x$exp")"
|
||||
if [ "$got" = "$want" ]; then
|
||||
echo "[llvm816] GNO check OK: $a = $got"
|
||||
else
|
||||
echo "[llvm816 FAIL] GNO check $a: expected $want got ${got:-(none)}"
|
||||
rc=1
|
||||
fi
|
||||
done
|
||||
exit $rc
|
||||
|
|
@ -363,7 +363,14 @@ static void applyReloc(std::vector<uint8_t> &buf, uint32_t off,
|
|||
if (gRecordSites) {
|
||||
uint32_t targetBank = target & 0xFF0000;
|
||||
uint32_t baseBank = gTextBaseForSites & 0xFF0000;
|
||||
if (targetBank == baseBank) {
|
||||
// A target below the text base is never an intra-segment
|
||||
// relocatable site: it is an undefined-weak symbol (resolveSym
|
||||
// resolves those to 0) or an absolute address. Recording a
|
||||
// cRELOC for it would (a) underflow offsetRef = target - textBase
|
||||
// (omfEmit rejects it as out-of-range) and (b) make the Loader
|
||||
// rewrite a genuine null to segPlacedBase, breaking the
|
||||
// `if (weakFn) weakFn()` null test that the null is meant to fail.
|
||||
if (targetBank == baseBank && target >= gTextBaseForSites) {
|
||||
Imm24Site s;
|
||||
s.patchOff = patchAddr - gTextBaseForSites;
|
||||
s.offsetRef = target - gTextBaseForSites;
|
||||
|
|
@ -386,7 +393,9 @@ static void applyReloc(std::vector<uint8_t> &buf, uint32_t off,
|
|||
if (gRecordSites) {
|
||||
uint32_t targetBank = target & 0xFF0000;
|
||||
uint32_t baseBank = gTextBaseForSites & 0xFF0000;
|
||||
if (targetBank == baseBank) {
|
||||
// See R_W65816_IMM16: skip undefined-weak/absolute targets
|
||||
// below the text base (no valid intra-segment cRELOC).
|
||||
if (targetBank == baseBank && target >= gTextBaseForSites) {
|
||||
Imm24Site s;
|
||||
s.patchOff = patchAddr - gTextBaseForSites;
|
||||
s.offsetRef = target - gTextBaseForSites;
|
||||
|
|
@ -413,7 +422,9 @@ static void applyReloc(std::vector<uint8_t> &buf, uint32_t off,
|
|||
// and shouldn't be relocated by the Loader.
|
||||
uint32_t targetBank = target & 0xFF0000;
|
||||
uint32_t baseBank = gTextBaseForSites & 0xFF0000;
|
||||
if (targetBank == baseBank) {
|
||||
// See R_W65816_IMM16: skip undefined-weak/absolute targets
|
||||
// below the text base (no valid intra-segment cRELOC).
|
||||
if (targetBank == baseBank && target >= gTextBaseForSites) {
|
||||
Imm24Site s;
|
||||
s.patchOff = patchAddr - gTextBaseForSites;
|
||||
s.offsetRef = target - gTextBaseForSites;
|
||||
|
|
@ -464,6 +475,15 @@ struct Linker {
|
|||
uint32_t segmentCap = 0;
|
||||
uint32_t segmentBankBase = 0x040000;
|
||||
std::string manifestPath;
|
||||
// ProDOS file metadata for the resulting OMF. Set via --filetype /
|
||||
// --aux. Used by disk-image builders (e.g. cppo, Cadius) to set
|
||||
// the on-disk filetype/aux when copying the .bin onto a 2mg.
|
||||
// For GS/OS apps: filetype=$B3 (S16), aux=0.
|
||||
// For GNO shell commands: filetype=$B5 (EXE), aux=0 (or $DC00 for
|
||||
// non-compliant programs that bypass GNO's keyboard buffer).
|
||||
// -1 sentinel = "not set" (caller hasn't asked for a sidecar).
|
||||
int32_t fileType = -1;
|
||||
int32_t auxType = -1;
|
||||
|
||||
// Per-section identity: (object index, section index within obj).
|
||||
using SecID = std::pair<size_t, uint32_t>;
|
||||
|
|
@ -1433,12 +1453,20 @@ static void usage(const char *argv0) {
|
|||
"usage: %s -o <output> [--text-base ADDR] [--rodata-base ADDR]\n"
|
||||
" [--bss-base ADDR] [--map FILE] [--debug-out FILE]\n"
|
||||
" [--reloc-out FILE] [--no-gc-sections]\n"
|
||||
" [--filetype N] [--aux N]\n"
|
||||
" <input.o> ...\n"
|
||||
"\n"
|
||||
" --reloc-out FILE write IMM24 relocation site list (binary:\n"
|
||||
" <count:u32><patchOff:u32 offsetRef:u32>...)\n"
|
||||
" consumed by omfEmit --relocs to emit cRELOC\n"
|
||||
" opcodes for runtime bank-byte fixup.\n",
|
||||
" opcodes for runtime bank-byte fixup.\n"
|
||||
" --filetype N ProDOS filetype (0..0xFF) for the OMF. $B3=S16\n"
|
||||
" (GS/OS app), $B5=EXE (GNO shell command). Writes\n"
|
||||
" <output>.meta sidecar consumed by disk-image\n"
|
||||
" builders.\n"
|
||||
" --aux N ProDOS auxtype (0..0xFFFF). Typically 0 for\n"
|
||||
" compliant programs; $DC00 = GNO non-compliant\n"
|
||||
" (bypasses interrupt-driven keyboard buffer).\n",
|
||||
argv0);
|
||||
std::exit(2);
|
||||
}
|
||||
|
|
@ -1497,6 +1525,16 @@ int main(int argc, char **argv) {
|
|||
} else if (a == "--manifest") {
|
||||
if (++i >= argc) usage(argv[0]);
|
||||
linker.manifestPath = argv[i++];
|
||||
} else if (a == "--filetype") {
|
||||
if (++i >= argc) usage(argv[0]);
|
||||
linker.fileType = (int32_t)parseInt(argv[i++]);
|
||||
if (linker.fileType < 0 || linker.fileType > 0xFF)
|
||||
die("--filetype must be 0..0xFF");
|
||||
} else if (a == "--aux") {
|
||||
if (++i >= argc) usage(argv[0]);
|
||||
linker.auxType = (int32_t)parseInt(argv[i++]);
|
||||
if (linker.auxType < 0 || linker.auxType > 0xFFFF)
|
||||
die("--aux must be 0..0xFFFF");
|
||||
} else if (a == "-h" || a == "--help") {
|
||||
usage(argv[0]);
|
||||
} else if (!a.empty() && a[0] == '-') {
|
||||
|
|
@ -1523,6 +1561,21 @@ int main(int argc, char **argv) {
|
|||
if (!f) die("cannot open '" + outPath + "' for writing");
|
||||
f.write(reinterpret_cast<const char *>(image.data()), image.size());
|
||||
|
||||
// ProDOS filetype/aux sidecar. Emit as `<output>.meta` — simple
|
||||
// line-oriented `key: 0xVALUE` format consumed by the disk-image
|
||||
// builder (cppo/Cadius/our scripts). Default filetype if not
|
||||
// specified: 0xB3 (S16) for single-segment, the multi-segment
|
||||
// builder writes 0xB3 anyway.
|
||||
if (linker.fileType >= 0 || linker.auxType >= 0) {
|
||||
std::string metaPath = outPath + ".meta";
|
||||
std::ofstream mf(metaPath);
|
||||
if (!mf) die("cannot open '" + metaPath + "' for writing");
|
||||
if (linker.fileType >= 0)
|
||||
mf << "filetype: 0x" << std::hex << linker.fileType << "\n";
|
||||
if (linker.auxType >= 0)
|
||||
mf << "aux: 0x" << std::hex << linker.auxType << "\n";
|
||||
}
|
||||
|
||||
if (!mapPath.empty()) linker.writeMap(mapPath);
|
||||
if (!debugOutPath.empty()) linker.writeDebugSidecar(debugOutPath);
|
||||
if (!relocOutPath.empty()) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "TargetInfo/W65816TargetInfo.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
|
|
@ -311,12 +312,30 @@ void W65816AsmPrinter::emitInstruction(const MachineInstr *MI) {
|
|||
// first; the Loader's cRELOC `BitShift=16` mechanism doesn't track
|
||||
// the placed bank (segPlacedBase appears 16-bit-only in the formula
|
||||
// it actually uses). `lda $BE` is also 2 bytes vs 3 for `lda #imm`
|
||||
// so this is a size win too. The symbol operand on the pseudo is
|
||||
// ignored — only the SDNode's value-type matters, which is i16
|
||||
// bank|pad.
|
||||
// so this is a size win too.
|
||||
//
|
||||
// EXCEPTION — external-weak symbols: a `&weakfn` whose definition may
|
||||
// be absent at link time must be representable as NULL. If we emit
|
||||
// `lda $BE` for its bank, the runtime PBR (non-zero when GS/OS loads
|
||||
// the segment in a non-zero bank) makes the pointer always non-null,
|
||||
// so `if (weakfn) weakfn()` is always taken and jumps to the
|
||||
// unresolved (=0) target — a crash. For an external-weak global the
|
||||
// bank must be a literal 0 instead, so an undefined-weak ref is a
|
||||
// genuine null and a strong link-time def still works (its low16 is
|
||||
// non-zero so the null test passes and the direct call uses the
|
||||
// symbol's own reloc, not this bank byte). Defined/normal globals
|
||||
// and compiler external symbols (libgcc helpers) keep `lda $BE`.
|
||||
const MachineOperand &Sym = MI->getOperand(1);
|
||||
bool WeakUndef = Sym.isGlobal() &&
|
||||
Sym.getGlobal()->hasExternalWeakLinkage();
|
||||
MCInst Lda;
|
||||
if (WeakUndef) {
|
||||
Lda.setOpcode(W65816::LDA_Imm16);
|
||||
Lda.addOperand(MCOperand::createImm(0));
|
||||
} else {
|
||||
Lda.setOpcode(W65816::LDA_DP);
|
||||
Lda.addOperand(MCOperand::createImm(0xBE));
|
||||
}
|
||||
EmitToStreamer(*OutStreamer, Lda);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -884,6 +884,14 @@ bool W65816StackSlotCleanup::runOnMachineFunction(MachineFunction &MF) {
|
|||
// real test and a flag-using branch.
|
||||
return Opc == W65816::LDAi16imm ||
|
||||
Opc == W65816::LDAi8imm ||
|
||||
// LDAi16imm_bank lowers to `lda $BE` (LDA_DP of the program-
|
||||
// bank byte). Under GNO/ME the program bank is non-zero, so
|
||||
// this load sets N/Z != the CMP's result. Between a CMP and a
|
||||
// BEQ/BNE (e.g. the bank half of an i32 `select`/`if(!p)`
|
||||
// pointer pick), it corrupts the test and the wrong half is
|
||||
// selected -- the `%s`-of-stack-string garbling bug. Plain
|
||||
// LDAi16imm was already listed; its _bank sibling must be too.
|
||||
Opc == W65816::LDAi16imm_bank ||
|
||||
Opc == W65816::LDXi16imm ||
|
||||
Opc == W65816::LDA_StackRel ||
|
||||
Opc == W65816::LDA_StackRelIndY ||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue