aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2024-04-12 13:56:41 +0300
committerJan Tuomi <jan@jantuomi.fi>2024-04-12 13:56:41 +0300
commit0603e19435b4304fabd91f840325a153ce31cae2 (patch)
tree6128a15ef56b23cc62317cbfa319a9f4c73a5dea /test
parent92de76627baf7c239a517316d85150149403f0c9 (diff)
Finish calli/callr/return, add test code
Diffstat (limited to 'test')
-rw-r--r--test/e2e/bootstrap.atk16 (renamed from test/e2e/emulation_speed/bootstrap.atk16)0
-rw-r--r--test/e2e/call_stack/lib.atk1642
-rw-r--r--test/e2e/call_stack/run_fact.atk1611
-rw-r--r--test/e2e/call_stack/run_mul.atk1618
-rw-r--r--test/e2e/call_stack/test_call_stack.py65
-rw-r--r--test/e2e/emulation_speed/long_loop.atk162
-rw-r--r--test/e2e/fibo/bootstrap.atk1678
-rw-r--r--test/e2e/fibo/fibo.atk162
8 files changed, 138 insertions, 80 deletions
diff --git a/test/e2e/emulation_speed/bootstrap.atk16 b/test/e2e/bootstrap.atk16
index 9b024e6..9b024e6 100644
--- a/test/e2e/emulation_speed/bootstrap.atk16
+++ b/test/e2e/bootstrap.atk16
diff --git a/test/e2e/call_stack/lib.atk16 b/test/e2e/call_stack/lib.atk16
new file mode 100644
index 0000000..39672e0
--- /dev/null
+++ b/test/e2e/call_stack/lib.atk16
@@ -0,0 +1,42 @@
+@label mul
+ ; multiply a signed/unsigned (a) and an unsigned number (b)
+ ; parameters RA = a
+ ; RB = b
+ ; return RG = a * b
+
+ stack_stash RA RB
+ ; initialize return value in RG to 0
+ ldi 0 RG
+@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
+ stack_restore RA RB
+ 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/test/e2e/call_stack/run_fact.atk16 b/test/e2e/call_stack/run_fact.atk16
new file mode 100644
index 0000000..06ad59c
--- /dev/null
+++ b/test/e2e/call_stack/run_fact.atk16
@@ -0,0 +1,11 @@
+; bootstrap code (must be called to setup mandatory data)
+; will jump to label main
+@include ../bootstrap
+@include lib
+
+@let INPUT %INPUT% ; value replaced by test driver code
+
+@label main
+ ldi INPUT RA
+ calli fact
+ hlt
diff --git a/test/e2e/call_stack/run_mul.atk16 b/test/e2e/call_stack/run_mul.atk16
new file mode 100644
index 0000000..feaabe7
--- /dev/null
+++ b/test/e2e/call_stack/run_mul.atk16
@@ -0,0 +1,18 @@
+; bootstrap code (must be called to setup mandatory data)
+; will jump to label main
+@include ../bootstrap
+@include lib
+
+; values replaced by test driver code
+@label INPUT_A
+ %INPUT_A%
+@label INPUT_B
+ %INPUT_B%
+
+@label main
+ ldi INPUT_A RA
+ ldr RA RA
+ ldi INPUT_B RB
+ ldr RB RB
+ calli mul
+ hlt
diff --git a/test/e2e/call_stack/test_call_stack.py b/test/e2e/call_stack/test_call_stack.py
new file mode 100644
index 0000000..3895f5c
--- /dev/null
+++ b/test/e2e/call_stack/test_call_stack.py
@@ -0,0 +1,65 @@
+import time
+from atk16_asm import assemble
+from atk16_emu import Machine
+from test.utils import pad_bytearray
+
+def run_mul(a: int, b: int) -> int:
+ filename = "test/e2e/call_stack/run_mul.atk16"
+ with open(filename, "r") as f:
+ source = f.read()
+
+ source = source.replace("%INPUT_A%", str(a))
+ source = source.replace("%INPUT_B%", str(b))
+
+ obj = assemble(source, filename)
+ rom_image = pad_bytearray(obj.program)
+
+ machine = Machine()
+ machine.load_rom_image(rom_image)
+ machine.reset()
+ machine.run_until_halted()
+
+ return machine.rg.value
+
+def test_mul_1():
+ expected = 30
+ received = run_mul(5, 6)
+
+ assert expected == received
+
+def test_mul_2():
+ a = -100
+ b = 200
+ expected = a * b
+ received = run_mul(a, b)
+
+ assert expected == received
+
+def run_fact(n: int) -> int:
+ filename = "test/e2e/call_stack/run_fact.atk16"
+ with open(filename, "r") as f:
+ source = f.read()
+
+ source = source.replace("%INPUT%", str(n))
+ obj = assemble(source, filename)
+ rom_image = pad_bytearray(obj.program)
+
+ machine = Machine()
+ machine.load_rom_image(rom_image)
+ machine.reset()
+ machine.run_until_halted()
+
+ return machine.rg.value
+
+def test_fact_0():
+ expected = 1
+ received = run_fact(0)
+
+ assert expected == received
+
+def test_fact_6():
+ expected = 720
+ received = run_fact(6)
+
+ assert expected == received
+
diff --git a/test/e2e/emulation_speed/long_loop.atk16 b/test/e2e/emulation_speed/long_loop.atk16
index 2303311..5447256 100644
--- a/test/e2e/emulation_speed/long_loop.atk16
+++ b/test/e2e/emulation_speed/long_loop.atk16
@@ -1,6 +1,6 @@
; bootstrap code (must be called to setup mandatory data)
; will jump to label main
-@include bootstrap
+@include ../bootstrap
@label iters
10000
diff --git a/test/e2e/fibo/bootstrap.atk16 b/test/e2e/fibo/bootstrap.atk16
deleted file mode 100644
index 9b024e6..0000000
--- a/test/e2e/fibo/bootstrap.atk16
+++ /dev/null
@@ -1,78 +0,0 @@
-@let SP RH
-
-; vector table fields
-@let vector_table 0x10
-@let vt_ISR0 0x10 ; ISR0
-@let vt_ISR1 0x11 ; ISR1
-@let vt_ISR2 0x12 ; ISR2
-@let vt_ISR3 0x13 ; ISR3
-@let vt_stack_addr 0x14 ; Stack address
-@let vt_term_pp_addr 0x15 ; Terminal peripheral address
-@let vt_kb_pp_addr 0x16 ; Keyboard peripheral address
-@let vt_gr_mode_addr 0x17 ; Graphics mode setting address
-@let vt_sprite_mem 0x18 ; Sprite memory address
-@let vt_text_mem 0x19 ; Text memory buffer address
-
-; memory segments
-@let stack_segment 0x8000
-@let mmio_segment 0xE000
-@let terminal_addr 0xE000
-@let keyboard_addr 0xE001
-@let gr_mode_addr 0xE002
-@let sprite_mem 0xE800
-@let text_mem 0xF800 ; to 0xFFFF
-; note: sprite memory & text memory can use the same space
-; since they are never used at the same time
-
-; graphics mode settings
-@let gr_disabled_mode 0b00
-@let gr_text_mode 0b01
-@let gr_sprite_mode 0b10
-
-@address vector_table
- keyboard_isr ; 0x10
- hlt_isr ; 0x11
- hlt_isr ; 0x12
- hlt_isr ; 0x13
- stack_segment ; 0x14
- terminal_addr ; 0x15
- keyboard_addr ; 0x16
- gr_mode_addr ; 0x17
- sprite_mem ; 0x18
- text_mem ; 0x19
-
-@label hlt_isr
- ldi 0x55 RE
- hlt
-
-@label keyboard_isr
- spu RA
- spu RB
- ldi vt_kb_pp_addr RA ; RA := Keyboard peripheral address pointer
- ldr RA RA ; RA := Keyboard peripheral address deref
- ldr RA RA ; RA := <16-bit keyboard character code> from MMIO register
- ldi vt_term_pp_addr RB ; RB := Terminal peripheral address pointer
- ldr RB RB ; RB := Terminal peripheral address deref
- str RA RB ; terminal <- character code (ASCII?)
- mov RA RE ; RE := character code (for debugging)
- spo RB
- spo RA
- rti
-@label program_segment
-
-; define short prelude that sets up vital instructions
-; NOTE: must be shorter than the vector table offset
-@address 0x0
-; set up stack pointer to point to beginning of stack segment
- ldi vt_stack_addr RA
- ldr RA SP
- jpi program_segment
-
-@address program_segment
-; set graphics mode to disabled
- ldi vt_gr_mode_addr RA
- ldr RA RA
- ldi gr_disabled_mode RB
- str RB RA
-; jump to main (user defined)
- jpi main
diff --git a/test/e2e/fibo/fibo.atk16 b/test/e2e/fibo/fibo.atk16
index 2cf3d20..2546f43 100644
--- a/test/e2e/fibo/fibo.atk16
+++ b/test/e2e/fibo/fibo.atk16
@@ -1,6 +1,6 @@
; bootstrap code (must be called to setup mandatory data)
; will jump to label main
-@include bootstrap
+@include ../bootstrap
@label iters
51