aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atk16_asm/builtin_asm/bootstrap.atk168
-rw-r--r--atk16_asm/builtin_asm/std_alloc.atk160
-rw-r--r--atk16_asm/builtin_asm/std_math.atk1692
-rw-r--r--atk16_emu/emu.py10
-rw-r--r--resources/asm/ast_compiler_bootstrap.atk168
-rw-r--r--resources/asm/test_py_src.atk168
6 files changed, 109 insertions, 17 deletions
diff --git a/atk16_asm/builtin_asm/bootstrap.atk16 b/atk16_asm/builtin_asm/bootstrap.atk16
index 94eed4c..e0fddfa 100644
--- a/atk16_asm/builtin_asm/bootstrap.atk16
+++ b/atk16_asm/builtin_asm/bootstrap.atk16
@@ -2,10 +2,10 @@
; memory segments
@let stack_segment 0x8000
-@let mmio_segment 0xE000
-@let terminal_addr 0xE000
-@let keyboard_addr 0xE001
-@let gr_mode_addr 0xE002
+@let mmio_segment 0xE7F0
+@let terminal_addr 0xE7F0
+@let keyboard_addr 0xE7F1
+@let gr_mode_addr 0xE7F2
@let sprite_mem 0xE800
@let text_mem 0xF800 ; to 0xFFFF
; note: sprite memory & text memory can use the same space
diff --git a/atk16_asm/builtin_asm/std_alloc.atk16 b/atk16_asm/builtin_asm/std_alloc.atk16
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/atk16_asm/builtin_asm/std_alloc.atk16
diff --git a/atk16_asm/builtin_asm/std_math.atk16 b/atk16_asm/builtin_asm/std_math.atk16
new file mode 100644
index 0000000..58b9cdb
--- /dev/null
+++ b/atk16_asm/builtin_asm/std_math.atk16
@@ -0,0 +1,92 @@
+@label mul_sign_mask
+ ${2 ** 15}
+@label mul_not_mask
+ 0xFFFF
+
+@label mul
+ ; multiply a signed (a) and a signed (b)
+ ; parameters RA = a
+ ; RB = b
+ ; return RG = a * b
+
+ stack_stash RA RB RC RD
+ ldi 0 RG ; initialize return value in RG to 0
+
+ ldi mul_sign_mask RD
+ ldr RD RD ; RD := 2 ** 16
+ and RA RD RC ; RC := 2 ** 16 if a is negative, 0 otherwise
+ and RB RD RD ; RD := 2 ** 16 if b is negative, 0 otherwise
+ xor RC RD RC ; RC := 2 ** 16 if exactly one of a or b is negative, 0 otherwise
+
+ ldi mul_not_mask RD
+ ldr RD RD ; RD := 0xFFFF
+
+ ; RA := abs(a)
+ subi RA 0 RA
+ bri sign mul_a_negative
+ jpi mul_a_negative_done
+@label mul_a_negative
+ xor RA RD RA ; RA := ~a
+ inc RA ; negate twos complement a
+@label mul_a_negative_done
+
+ ; RB := abs(b)
+ subi RB 0 RB
+ bri sign mul_b_negative
+ jpi mul_b_negative_done
+@label mul_b_negative
+ xor RB RD RB ; RB := ~b
+ inc RB ; negate twos complement b
+@label mul_b_negative_done
+
+ ; the algorithms iterates b times, adding a to RG each time
+ ; so b should be as small as possible
+ sub RB RA RD ; if a <= b, swap a and b
+ bri sign mul_loop
+
+ mov RA RD
+ mov RB RA
+ mov RD RB
+@label mul_loop
+ ; if b == 0, we are done
+ subi RB 0 RB
+ bri zero mul_done
+ ; RG += RA
+ add RA RG RG
+ dec RB
+ jpi mul_loop
+@label mul_done
+ ; set the most significant bit to the precomputed sign
+ subi RC 0 RC
+ bri sign mul_negate_result
+ jpi mul_return
+@label mul_negate_result
+ ldi mul_not_mask RD
+ ldr RD RD ; RD := 0xFFFF
+ xor RG RD RG
+ inc RG
+@label mul_return
+ stack_restore RA RB RC RD
+ return
+
+; Recursive impl of the factorial
+; Calling convention is that arguments are in registers RA..RG (max 7 arguments since RH = SP)
+; and the return value is in RG (note: overwriting arg in RG)
+
+@label fact
+ ; parameters RA = n
+ ; return RG = factorial(n)
+ subi RA 0 RA
+ bri zero fact_basecase
+@label fact_reccase
+ stack_stash RA RB
+ mov RA RB ; RB := n
+ subi RA 1 RA ; RA := n - 1
+ calli fact ; RG := fact(n - 1)
+ mov RG RA ; RA := fact(n - 1)
+ calli mul ; RG := n * fact(n - 1)
+ stack_restore RA RB
+ return
+@label fact_basecase
+ ldi 1 RG
+ return
diff --git a/atk16_emu/emu.py b/atk16_emu/emu.py
index 43dfdf1..0b4e675 100644
--- a/atk16_emu/emu.py
+++ b/atk16_emu/emu.py
@@ -196,7 +196,7 @@ class Machine:
if addr < 2 ** 15:
return self.rom.read(addr & 0x7FFF)
else:
- if addr == 0xE001:
+ if addr == 0xE7F1:
return self.peripherals.keyboard.read()
else:
return self.ram.read(addr & 0x7FFF)
@@ -205,15 +205,15 @@ class Machine:
if addr < 2 ** 15:
raise ValueError(f"Cannot write to ROM, addr: 0x{addr:>04x}")
else:
- if addr == 0xE002 and value == 0b00:
+ if addr == 0xE7F2 and value == 0b00:
self.peripherals.graphics.deactivate()
- elif addr == 0xE002 and value == 0b01:
+ elif addr == 0xE7F2 and value == 0b01:
self.peripherals.graphics.activate_tpu()
- elif addr == 0xE002 and value == 0b10:
+ elif addr == 0xE7F2 and value == 0b10:
self.peripherals.graphics.activate_ppu()
elif 0xF800 <= addr <= 0xFFFF:
self.peripherals.graphics.write(addr, value)
- elif addr == 0xE000:
+ elif addr == 0xE7F0:
self.peripherals.terminal.write(value)
else:
self.ram.write(addr & 0x7FFF, value)
diff --git a/resources/asm/ast_compiler_bootstrap.atk16 b/resources/asm/ast_compiler_bootstrap.atk16
index 2e112eb..b38e5f5 100644
--- a/resources/asm/ast_compiler_bootstrap.atk16
+++ b/resources/asm/ast_compiler_bootstrap.atk16
@@ -18,10 +18,10 @@
@let vt_text_mem 0x19 ; Text memory buffer address
@let stack_segment 0x8000
-@let mmio_segment 0xE000
-@let terminal_addr 0xE000
-@let keyboard_addr 0xE001
-@let gr_mode_addr 0xE002
+@let mmio_segment 0xE7F0
+@let terminal_addr 0xE7F0
+@let keyboard_addr 0xE7F1
+@let gr_mode_addr 0xE7F2
@let sprite_mem 0xE800
@let text_mem 0xF800
diff --git a/resources/asm/test_py_src.atk16 b/resources/asm/test_py_src.atk16
index c38d1ca..bd1d93f 100644
--- a/resources/asm/test_py_src.atk16
+++ b/resources/asm/test_py_src.atk16
@@ -18,10 +18,10 @@
@let vt_text_mem 0x19 ; Text memory buffer address
@let stack_segment 0x8000
-@let mmio_segment 0xE000
-@let terminal_addr 0xE000
-@let keyboard_addr 0xE001
-@let gr_mode_addr 0xE002
+@let mmio_segment 0xE7F0
+@let terminal_addr 0xE7F0
+@let keyboard_addr 0xE7F1
+@let gr_mode_addr 0xE7F2
@let sprite_mem 0xE800
@let text_mem 0xF800