aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2023-11-13 23:12:05 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2023-11-13 23:12:05 +0200
commit14d8401c721fae8367fa24db20af4e344faafdd4 (patch)
tree58931d22d9c903a15bbe137c571dd76c7a98799b
parente2b7385b03a6dc9c8c39dde5c049cd74b0768bd1 (diff)
Fix calling issues
-rw-r--r--asm/ast_compiler_bootstrap.atk165
-rw-r--r--asm/test_py_src.atk16285
-rw-r--r--asm/test_py_src.atk16_optimized202
-rw-r--r--asm/test_py_src.py9
-rw-r--r--digital/atk16.dig108
-rw-r--r--digital/atk16_mem.dig2
-rw-r--r--src/ast_compiler.py255
7 files changed, 310 insertions, 556 deletions
diff --git a/asm/ast_compiler_bootstrap.atk16 b/asm/ast_compiler_bootstrap.atk16
index 7036291..18a345a 100644
--- a/asm/ast_compiler_bootstrap.atk16
+++ b/asm/ast_compiler_bootstrap.atk16
@@ -2,7 +2,9 @@
@use ext_std:*
-@let sp RH
+@let sp RH ; stack pointer (points to empty slot at top of stack)
+@let fp RG ; frame pointer (points to base of currently active frame)
+
@let vector_table 0x10
@let vt_ISR0 0x10 ; ISR0
@let vt_ISR1 0x11 ; ISR1
@@ -30,6 +32,7 @@
@address 0x0
ldi vt_stack_addr RA
ldr RA SP
+ mov SP FP
jpi program_segment
@address vector_table
diff --git a/asm/test_py_src.atk16 b/asm/test_py_src.atk16
index 2d8e311..b605dad 100644
--- a/asm/test_py_src.atk16
+++ b/asm/test_py_src.atk16
@@ -2,7 +2,9 @@
@use ext_std:*
-@let sp RH
+@let sp RH ; stack pointer (points to empty slot at top of stack)
+@let fp RG ; frame pointer (points to base of currently active frame)
+
@let vector_table 0x10
@let vt_ISR0 0x10 ; ISR0
@let vt_ISR1 0x11 ; ISR1
@@ -30,6 +32,7 @@
@address 0x0
ldi vt_stack_addr RA
ldr RA SP
+ mov SP FP
jpi program_segment
@address vector_table
@@ -77,47 +80,39 @@
23
@label text_mem_addr_p
25
-@label int_1
+@label int_0
65
-@label int_5
+@label int_6
26
-; <ast.FunctionDef object at 0x1048ce500>
+; <ast.FunctionDef object at 0x104f1f370>
@label nth_letter
; stack frame with offsets
-; return_address_0 3
-; n 4
-; <ast.Return object at 0x1048ce440>
-; <ast.Add object at 0x1045f6ad0>
-; BinOp lhs <ast.BinOp object at 0x1048ce410>
-; <ast.Name object at 0x1048ce3e0> (n)
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 4 RB
- add RA RB RA
- ldr RA RA
- spu RA
-; BinOp rhs <ast.BinOp object at 0x1048ce410>
-; <ast.Constant object at 0x1048ce3b0>
- ldi int_1 RA
- ldr RA RA
- spu RA
- spo RB
- spo RA
- add RA RB RA
- spu RA
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 3 RB
- add RA RB RA
-; stack address of return address is stored in reg RA
- spo RB
-; return value is stored in reg RB
- mov RA SP
- ldr RA RA
- spu RB
+; n 0
+; <ast.Return object at 0x104f1f430>
+; <ast.Add object at 0x104ed2c20>
+; BinOp lhs <ast.BinOp object at 0x1051b52a0>
+; <ast.Call object at 0x1051b5270>
+; Builtin call ord [<ast.Constant object at 0x1051b51e0>]
+; <ast.Constant object at 0x1051b51e0>
+ ldi int_0 RC
+ ldr RC RC ; int_0 = 65
+ spu RC
+; BinOp rhs <ast.BinOp object at 0x1051b52a0>
+; <ast.Name object at 0x1051b51b0> (n)
+ ldi 0 RC
+ add FP RC RC
+ ldr RC RC
+ spu RC
+ spo RD
+ spo RC
+ add RC RD RC
+ spu RC
+; return value is on top of stack
; return from function
- jpr RA
+ subi FP 1 FP
+ ldr FP RB
+ jpr RB
@label main
; stack frame with offsets
@@ -125,186 +120,182 @@
; text_mem_addr 1
; i 2
addi SP 3 SP
-; <ast.Assign object at 0x1048ce860>
-; assigning graphics_mode_addr at stack segment + 0
+; <ast.Assign object at 0x104f1ffd0>
+; assigning graphics_mode_addr at FP + 0
; evaluating value to be assigned
-; <ast.Call object at 0x1048ce800>
-; Builtin call load [<ast.Name object at 0x1048ce770>]
-; <ast.Name object at 0x1048ce770> (GRAPHICS_MODE_ADDR_P)
+; <ast.Call object at 0x104f1fa00>
+; Builtin call load [<ast.Name object at 0x104f1f970>]
+; <ast.Name object at 0x104f1f970> (GRAPHICS_MODE_ADDR_P)
ldi graphics_mode_addr_p RC
ldr RC RC
spu RC
+; (load) dereferencing top of stack
spo RC
ldr RC RC
spu RC
-; assigning value to stack segment + 0
- ldi vt_stack_addr RA
- ldr RA RA
+; assigning stack address (FP + 0) := top of stack
+ spo RA
ldi 0 RB
- add RA RB RA
- spo RB
- str RB RA
-; <ast.Assign object at 0x1048ce740>
-; assigning text_mem_addr at stack segment + 1
+ add RB FP RB
+ str RA RB
+; <ast.Assign object at 0x104f1f940>
+; assigning text_mem_addr at FP + 1
; evaluating value to be assigned
-; <ast.Call object at 0x1048ce6e0>
-; Builtin call load [<ast.Name object at 0x1048ce650>]
-; <ast.Name object at 0x1048ce650> (TEXT_MEM_ADDR_P)
+; <ast.Call object at 0x104f1f610>
+; Builtin call load [<ast.Name object at 0x104f1f550>]
+; <ast.Name object at 0x104f1f550> (TEXT_MEM_ADDR_P)
ldi text_mem_addr_p RC
ldr RC RC
spu RC
+; (load) dereferencing top of stack
spo RC
ldr RC RC
spu RC
-; assigning value to stack segment + 1
- ldi vt_stack_addr RA
- ldr RA RA
+; assigning stack address (FP + 1) := top of stack
+ spo RA
ldi 1 RB
- add RA RB RA
- spo RB
- str RB RA
-; <ast.Call object at 0x1048ce5f0>
-; Builtin call store [<ast.Name object at 0x1048ce560>, <ast.Name object at 0x1048ce530>]
-; <ast.Name object at 0x1048ce560> (graphics_mode_addr)
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 0 RB
- add RA RB RA
+ add RB FP RB
+ str RA RB
+; <ast.Call object at 0x104f1f4f0>
+; Builtin call store [<ast.Name object at 0x104f1f3d0>, <ast.Name object at 0x104f1f3a0>]
+; <ast.Name object at 0x104f1f3d0> (graphics_mode_addr)
+ ldi 0 RA
+ add FP RA RA
ldr RA RA
spu RA
-; <ast.Name object at 0x1048ce530> (TEXT_MODE)
+; <ast.Name object at 0x104f1f3a0> (TEXT_MODE)
ldi text_mode RA
ldr RA RA
spu RA
spo RB
spo RA
str RB RA
-; <ast.Assign object at 0x1048ce350>
-; assigning i at stack segment + 2
+ ldi 0 RA
+ spu RA
+; popping free-standing Expr result from stack
+ spo RA
+; <ast.Assign object at 0x1051b5150>
+; assigning i at FP + 2
; evaluating value to be assigned
-; <ast.Constant object at 0x1048ce2f0>
+; <ast.Constant object at 0x1051b50f0>
ldi 0 RC
spu RC
-; assigning value to stack segment + 2
- ldi vt_stack_addr RA
- ldr RA RA
+; assigning stack address (FP + 2) := top of stack
+ spo RA
ldi 2 RB
- add RA RB RA
- spo RB
- str RB RA
-; <ast.Call object at 0x1048ce290>
-; Builtin call asm [<ast.Constant object at 0x1048ce200>]
- ldi 0b111111111 RG
-; <ast.While object at 0x1048ce1d0>
-@label while_test_2
-; <ast.Name object at 0x1048ce170> (i)
- ldi vt_stack_addr RB
- ldr RB RB
- ldi 2 RC
- add RB RC RB
+ add RB FP RB
+ str RA RB
+; <ast.While object at 0x1051b50c0>
+@label while_test_1
+; <ast.Compare object at 0x1051b5090>
+; <ast.Name object at 0x1051b5060> (i)
+ ldi 2 RB
+ add FP RB RB
ldr RB RB
spu RB
-; <ast.Constant object at 0x1048ce140>
- ldi int_5 RB
- ldr RB RB
+; <ast.Constant object at 0x1051b5030>
+ ldi int_6 RB
+ ldr RB RB ; int_6 = 26
spu RB
+; Comparing <ast.Name object at 0x1051b5060> <ast.Lt object at 0x104ed2470> <ast.Constant object at 0x1051b5030>
spo RC
spo RB
sub RB RC RB
- bri carry Compare_true_6
+ bri carry Compare_true_4
ldi 0 RB
spu RB
- jpi Compare_end_7
-@label compare_true_6
+ jpi Compare_end_5
+@label compare_true_4
ldi 1 RB
spu RB
-@label compare_end_7
+@label compare_end_5
spo RA
addi RA 0 RA
- bri zero While_else_3
-; <ast.Call object at 0x1048ce0e0>
-; Builtin call store [<ast.BinOp object at 0x1048ce050>, <ast.Call object at 0x1048cdd80>]
-; <ast.Add object at 0x1045f6ad0>
-; BinOp lhs <ast.BinOp object at 0x1048ce050>
-; <ast.Name object at 0x1048ce020> (text_mem_addr)
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 1 RB
- add RA RB RA
+ bri zero While_else_2
+; <ast.Call object at 0x1051b4fd0>
+; Builtin call store [<ast.BinOp object at 0x1051b4f40>, <ast.Call object at 0x1051b4eb0>]
+; <ast.Add object at 0x104ed2c20>
+; BinOp lhs <ast.BinOp object at 0x1051b4f40>
+; <ast.Name object at 0x1051b4f10> (text_mem_addr)
+ ldi 1 RA
+ add FP RA RA
ldr RA RA
spu RA
-; BinOp rhs <ast.BinOp object at 0x1048ce050>
-; <ast.Name object at 0x1048cdff0> (i)
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
+; BinOp rhs <ast.BinOp object at 0x1051b4f40>
+; <ast.Name object at 0x1051b4ee0> (i)
+ ldi 2 RA
+ add FP RA RA
ldr RA RA
spu RA
spo RB
spo RA
add RA RB RA
spu RA
-; <ast.Call object at 0x1048cdd80>
+; <ast.Call object at 0x1051b4eb0>
; Call function nth_letter
+ spu FP
ldi 0 RA
spu RA
-; <ast.Name object at 0x1048cdd20> (i)
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
+; <ast.Name object at 0x1051b4e50> (i)
+ ldi 2 RA
+ add FP RA RA
ldr RA RA
spu RA
+ subi SP 2 FP
; set up return address and jump to subroutine
- subi SP 2 RA
- lpc RB
- addi RB 3 RB
- str RB RA
+ lpc RA
+ addi RA 4 RA
+ str RA FP
+ addi FP 1 FP
jpi nth_letter
+ spo RA
+ mov FP SP
+ spo FP
+ spu RA
spo RB
spo RA
str RB RA
-; <ast.Assign object at 0x1048ccc70>
-; assigning i at stack segment + 2
+ ldi 0 RA
+ spu RA
+; popping free-standing Expr result from stack
+ spo RA
+; <ast.Assign object at 0x1051b4e20>
+; assigning i at FP + 2
; evaluating value to be assigned
-; <ast.Add object at 0x1045f6ad0>
-; BinOp lhs <ast.BinOp object at 0x1048cda50>
-; <ast.Name object at 0x1048cd750> (i)
- ldi vt_stack_addr RC
- ldr RC RC
- ldi 2 RD
- add RC RD RC
+; <ast.Add object at 0x104ed2c20>
+; BinOp lhs <ast.BinOp object at 0x1051b4dc0>
+; <ast.Name object at 0x1051b4d90> (i)
+ ldi 2 RC
+ add FP RC RC
ldr RC RC
spu RC
-; BinOp rhs <ast.BinOp object at 0x1048cda50>
-; <ast.Constant object at 0x1048cd720>
+; BinOp rhs <ast.BinOp object at 0x1051b4dc0>
+; <ast.Constant object at 0x1051b4d60>
ldi 1 RC
spu RC
spo RD
spo RC
add RC RD RC
spu RC
-; assigning value to stack segment + 2
- ldi vt_stack_addr RA
- ldr RA RA
+; assigning stack address (FP + 2) := top of stack
+ spo RA
ldi 2 RB
- add RA RB RA
- spo RB
- str RB RA
- jpi While_test_2
-@label while_else_3
-@label while_end_4
-; <ast.While object at 0x1048cd0f0>
-@label while_test_8
-; <ast.Constant object at 0x1048cd060>
+ add RB FP RB
+ str RA RB
+ jpi While_test_1
+@label while_else_2
+@label while_end_3
+; <ast.While object at 0x1051b4d30>
+@label while_test_7
+; <ast.Constant object at 0x1051b4d00>
ldi 1 RB
spu RB
spo RA
addi RA 0 RA
- bri zero While_else_9
-; <ast.Pass object at 0x1048ccfa0>
- jpi While_test_8
-@label while_else_9
-@label while_end_10
- subi SP 3 SP
+ bri zero While_else_8
+; <ast.Pass object at 0x1051b4cd0>
+ jpi While_test_7
+@label while_else_8
+@label while_end_9
+ mov FP SP
+ hlt
diff --git a/asm/test_py_src.atk16_optimized b/asm/test_py_src.atk16_optimized
deleted file mode 100644
index f526853..0000000
--- a/asm/test_py_src.atk16_optimized
+++ /dev/null
@@ -1,202 +0,0 @@
-@use ext_std:*
-@let sp RH
-@let vector_table 0x10
-@let vt_ISR0 0x10
-@let vt_ISR1 0x11
-@let vt_ISR2 0x12
-@let vt_ISR3 0x13
-@let vt_stack_addr 0x14
-@let vt_term_pp_addr 0x15
-@let vt_kb_pp_addr 0x16
-@let vt_gr_mode_addr 0x17
-@let vt_sprite_mem 0x18
-@let vt_text_mem 0x19
-@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
-@let gr_disabled_mode 0b00
-@let gr_text_mode 0b01
-@let gr_sprite_mode 0b10
-@address 0x0
- ldi vt_stack_addr RA
- ldr RA SP
- jpi program_segment
-@address vector_table
- keyboard_isr
- hlt_isr
- hlt_isr
- hlt_isr
- stack_segment
- terminal_addr
- keyboard_addr
- gr_mode_addr
- sprite_mem
- text_mem
-@label hlt_isr
- ldi 0x55 RE
- hlt
-@label keyboard_isr
- spu RA
- spu RB
- ldi vt_kb_pp_addr RA
- ldr RA RA
- ldr RA RA
- ldi vt_term_pp_addr RB
- ldr RB RB
- str RA RB
- spo RB
- spo RA
- rti
-@label program_segment
- ldi vt_gr_mode_addr RA
- ldr RA RA
- ldi gr_disabled_mode RB
- str RB RA
- jpi main
-@label text_mode
- 1
-@label graphics_mode_addr_p
- 23
-@label text_mem_addr_p
- 25
-@label int_1
- 65
-@label int_5
- 26
-@label nth_letter
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 4 RB
- add RA RB RA
- ldr RA RA
- ldi int_1 RB
- ldr RB RB
- add RA RB RA
- spu RA
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 3 RB
- add RA RB RA
- spo RB
- mov RA SP
- ldr RA RA
- spu RB
- jpr RA
-@label main
- addi SP 3 SP
- ldi graphics_mode_addr_p RC
- ldr RC RC
- ldr RC RC
- spu RC
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 0 RB
- add RA RB RA
- spo RB
- str RB RA
- ldi text_mem_addr_p RC
- ldr RC RC
- ldr RC RC
- spu RC
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 1 RB
- add RA RB RA
- spo RB
- str RB RA
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 0 RB
- add RA RB RA
- ldr RA RA
- ldi text_mode RB
- ldr RB RB
- str RB RA
- ldi 0 RC
- spu RC
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
- spo RB
- str RB RA
- ldi 0b111111111 RG
-@label while_test_2
- ldi vt_stack_addr RB
- ldr RB RB
- ldi 2 RC
- add RB RC RB
- ldr RB RB
- ldi int_5 RC
- ldr RC RC
- sub RB RC RB
- bri carry Compare_true_6
- ldi 0 RB
- spu RB
- jpi Compare_end_7
-@label compare_true_6
- ldi 1 RB
- spu RB
-@label compare_end_7
- spo RA
- addi RA 0 RA
- bri zero While_else_3
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 1 RB
- add RA RB RA
- ldr RA RA
- spu RA
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
- ldr RA RB
- spo RA
- add RA RB RA
- spu RA
- ldi 0 RA
- spu RA
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
- ldr RA RA
- spu RA
- subi SP 2 RA
- lpc RB
- addi RB 3 RB
- str RB RA
- jpi nth_letter
- spo RB
- spo RA
- str RB RA
- ldi vt_stack_addr RC
- ldr RC RC
- ldi 2 RD
- add RC RD RC
- ldr RC RC
- ldi 1 RD
- add RC RD RC
- spu RC
- ldi vt_stack_addr RA
- ldr RA RA
- ldi 2 RB
- add RA RB RA
- spo RB
- str RB RA
- jpi While_test_2
-@label while_else_3
-@label while_end_4
-@label while_test_8
- ldi 1 RA
- addi RA 0 RA
- bri zero While_else_9
- jpi While_test_8
-@label while_else_9
-@label while_end_10
- subi SP 3 SP \ No newline at end of file
diff --git a/asm/test_py_src.py b/asm/test_py_src.py
index 74ea60d..ec17ddc 100644
--- a/asm/test_py_src.py
+++ b/asm/test_py_src.py
@@ -1,6 +1,5 @@
import atk16
-
TEXT_MODE: atk16.ConstInt = 1
GRAPHICS_MODE_ADDR_P: atk16.ConstInt = 0x17
TEXT_MEM_ADDR_P: atk16.ConstInt = 0x19
@@ -10,18 +9,12 @@ text_mem_addr = atk16.load(TEXT_MEM_ADDR_P)
atk16.store(graphics_mode_addr, TEXT_MODE)
-
def nth_letter(n: int) -> int:
- return n + 65
+ return atk16.ord('A') + n
i = 0
-atk16.asm("ldi 0b111111111 RG")
while i < 26:
- # bug: stack frame offset for nth_letter is calculated
- # one off because text_mem_addr + i takes up one
- # stack slot
atk16.store(text_mem_addr + i, nth_letter(i))
- #atk16.store(text_mem_addr + i, i + 65)
i = i + 1
while True:
diff --git a/digital/atk16.dig b/digital/atk16.dig
index c028bd7..87f7ddb 100644
--- a/digital/atk16.dig
+++ b/digital/atk16.dig
@@ -413,20 +413,6 @@
<pos x="-140" y="180"/>
</visualElement>
<visualElement>
- <elementName>Tunnel</elementName>
- <elementAttributes>
- <entry>
- <string>rotation</string>
- <rotation rotation="2"/>
- </entry>
- <entry>
- <string>NetName</string>
- <string>US_RS</string>
- </entry>
- </elementAttributes>
- <pos x="-280" y="220"/>
- </visualElement>
- <visualElement>
<elementName>VDD</elementName>
<elementAttributes>
<entry>
@@ -456,21 +442,6 @@
<pos x="-240" y="200"/>
</visualElement>
<visualElement>
- <elementName>Reset</elementName>
- <elementAttributes>
- <entry>
- <string>invertOutput</string>
- <boolean>false</boolean>
- </entry>
- </elementAttributes>
- <pos x="-260" y="260"/>
- </visualElement>
- <visualElement>
- <elementName>Or</elementName>
- <elementAttributes/>
- <pos x="-220" y="220"/>
- </visualElement>
- <visualElement>
<elementName>Driver</elementName>
<elementAttributes>
<entry>
@@ -1741,11 +1712,6 @@
<pos x="400" y="740"/>
</visualElement>
<visualElement>
- <elementName>Break</elementName>
- <elementAttributes/>
- <pos x="880" y="280"/>
- </visualElement>
- <visualElement>
<elementName>Tunnel</elementName>
<elementAttributes>
<entry>
@@ -1773,6 +1739,40 @@
</elementAttributes>
<pos x="680" y="1020"/>
</visualElement>
+ <visualElement>
+ <elementName>Tunnel</elementName>
+ <elementAttributes>
+ <entry>
+ <string>rotation</string>
+ <rotation rotation="2"/>
+ </entry>
+ <entry>
+ <string>NetName</string>
+ <string>US_RS</string>
+ </entry>
+ </elementAttributes>
+ <pos x="-360" y="240"/>
+ </visualElement>
+ <visualElement>
+ <elementName>Reset</elementName>
+ <elementAttributes>
+ <entry>
+ <string>invertOutput</string>
+ <boolean>false</boolean>
+ </entry>
+ </elementAttributes>
+ <pos x="-340" y="280"/>
+ </visualElement>
+ <visualElement>
+ <elementName>Or</elementName>
+ <elementAttributes/>
+ <pos x="-300" y="240"/>
+ </visualElement>
+ <visualElement>
+ <elementName>Break</elementName>
+ <elementAttributes/>
+ <pos x="-200" y="260"/>
+ </visualElement>
</visualElements>
<wires>
<wire>
@@ -1808,10 +1808,6 @@
<p2 x="960" y="640"/>
</wire>
<wire>
- <p1 x="-260" y="260"/>
- <p2 x="-220" y="260"/>
- </wire>
- <wire>
<p1 x="420" y="260"/>
<p2 x="440" y="260"/>
</wire>
@@ -1828,6 +1824,14 @@
<p2 x="280" y="260"/>
</wire>
<wire>
+ <p1 x="-240" y="260"/>
+ <p2 x="-220" y="260"/>
+ </wire>
+ <wire>
+ <p1 x="-220" y="260"/>
+ <p2 x="-200" y="260"/>
+ </wire>
+ <wire>
<p1 x="680" y="900"/>
<p2 x="700" y="900"/>
</wire>
@@ -1960,8 +1964,8 @@
<p2 x="700" y="280"/>
</wire>
<wire>
- <p1 x="860" y="280"/>
- <p2 x="880" y="280"/>
+ <p1 x="-340" y="280"/>
+ <p2 x="-300" y="280"/>
</wire>
<wire>
<p1 x="680" y="920"/>
@@ -2348,14 +2352,6 @@
<p2 x="740" y="-220"/>
</wire>
<wire>
- <p1 x="-160" y="220"/>
- <p2 x="-140" y="220"/>
- </wire>
- <wire>
- <p1 x="-280" y="220"/>
- <p2 x="-220" y="220"/>
- </wire>
- <wire>
<p1 x="60" y="220"/>
<p2 x="80" y="220"/>
</wire>
@@ -2372,6 +2368,10 @@
<p2 x="860" y="220"/>
</wire>
<wire>
+ <p1 x="-220" y="220"/>
+ <p2 x="-140" y="220"/>
+ </wire>
+ <wire>
<p1 x="680" y="220"/>
<p2 x="760" y="220"/>
</wire>
@@ -2496,6 +2496,10 @@
<p2 x="280" y="240"/>
</wire>
<wire>
+ <p1 x="-360" y="240"/>
+ <p2 x="-300" y="240"/>
+ </wire>
+ <wire>
<p1 x="-20" y="240"/>
<p2 x="80" y="240"/>
</wire>
@@ -2632,12 +2636,8 @@
<p2 x="280" y="-100"/>
</wire>
<wire>
- <p1 x="860" y="220"/>
- <p2 x="860" y="280"/>
- </wire>
- <wire>
- <p1 x="-160" y="220"/>
- <p2 x="-160" y="240"/>
+ <p1 x="-220" y="220"/>
+ <p2 x="-220" y="260"/>
</wire>
<wire>
<p1 x="480" y="0"/>
diff --git a/digital/atk16_mem.dig b/digital/atk16_mem.dig
index 629a6af..5f5e2e6 100644
--- a/digital/atk16_mem.dig
+++ b/digital/atk16_mem.dig
@@ -34,7 +34,7 @@
</entry>
<entry>
<string>Data</string>
- <data>4014,2e00,6028,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,001c,001a,001a,001a,8000,e000,e001,e002,e800,f800,4855,f000,31c0,1fc8,31c8,1fc8,4016,2000,2000,4215,2240,3040,1fc9,23c0,1fc9,21c0,e000,4017,2000,4200,3008,601a,0001,0017,0019,0041,001a,4014,2000,4204,0008,2000,4233,2240,0008,31c0,1fc8,4014,2000,4203,0008,1fc9,23c0,1e00,2000,31c8,1fc8,5000,1fd8,4431,2480,2480,31d0,1fc8,4014,2000,4200,0008,1fc9,23c0,3008,4432,2480,2480,31d0,1fc8,4014,2000,4201,0008,1fc9,23c0,3008,4014,2000,4200,0008,2000,4230,2240,3008,4400,31d0,1fc8,4014,2000,4202,0008,1fc9,23c0,3008,4dff,4214,2240,4402,0250,2240,4434,2480,0251,8004,4200,31c8,1fc8,6003,4201,31c8,1fc8,1fc9,21c0,1000,8436,4014,2000,4201,0008,2000,31c0,1fc8,4014,2000,4202,0008,2200,1fc9,21c0,0008,31c0,1fc8,4000,31c0,1fc8,4014,2000,4202,0008,2000,31c0,1fc8,11d1,9200,1258,3008,618b,1fc9,23c0,1fc9,21c0,3008,4414,2480,4602,0498,2480,4601,0498,31d0,1fc8,4014,2000,4202,0008,1fc9,23c0,3008,61b6,4001,1000,8401,61fc,1fd9</data>
+ <data>4014,2e00,1dc0,6027,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,8000,001c,001a,001a,001a,8000,e000,e001,e002,e800,f800,4855,f000,31c0,1fc8,31c8,1fc8,4016,2000,2000,4215,2240,3040,1fc9,23c0,1fc9,21c0,e000,4017,2000,4200,3008,6018,0001,0017,0019,0041,001a,4433,2480,31d0,1fc8,4400,0590,2480,31d0,1fc8,1fc9,27c0,1fc9,25c0,0498,31d0,1fc8,1d89,2380,5040,1fd8,4431,2480,31d0,1fc8,1fc9,25c0,2480,31d0,1fc8,1fc9,21c0,4200,0270,3040,4432,2480,31d0,1fc8,1fc9,25c0,2480,31d0,1fc8,1fc9,21c0,4201,0270,3040,4000,0180,2000,31c0,1fc8,4030,2000,31c0,1fc8,1fc9,23c0,1fc9,21c0,3008,4000,31c0,1fc8,1fc9,21c0,4400,31d0,1fc8,1fc9,21c0,4202,0270,3040,4202,0388,2240,31c8,1fc8,4234,2240,31c8,1fc8,1fc9,25c0,1fc9,23c0,0251,8004,4200,31c8,1fc8,6003,4201,31c8,1fc8,1fc9,21c0,1000,8447,4001,0180,2000,31c0,1fc8,4002,0180,2000,31c0,1fc8,1fc9,23c0,1fc9,21c0,0008,31c0,1fc8,31f0,1fc8,4000,31c0,1fc8,4002,0180,2000,31c0,1fc8,1dd1,9000,1020,3180,1d88,617a,1fc9,21c0,1f80,1fc9,2dc0,31c0,1fc8,1fc9,23c0,1fc9,21c0,3008,4000,31c0,1fc8,1fc9,21c0,4402,0590,2480,31d0,1fc8,4401,31d0,1fc8,1fc9,27c0,1fc9,25c0,0498,31d0,1fc8,1fc9,21c0,4202,0270,3040,619f,4201,31c8,1fc8,1fc9,21c0,1000,8401,61f8,1f80,f000</data>
</entry>
</elementAttributes>
<pos x="740" y="100" />
diff --git a/src/ast_compiler.py b/src/ast_compiler.py
index d3fd70e..4dfcf8e 100644
--- a/src/ast_compiler.py
+++ b/src/ast_compiler.py
@@ -28,8 +28,11 @@ class Reg():
return f"R{self.reg}"
ALL_REGS: list[RegChar] = ["A", "B", "C", "D", "E", "F", "G", "H"]
-STACK_POINTER_REG = "H"
-SPECIAL_REGS: list[RegChar] = [STACK_POINTER_REG]
+FRAME_POINTER_REG_CHAR: RegChar = "G" # points to base of stack frame
+FRAME_POINTER_REG = Reg(FRAME_POINTER_REG_CHAR)
+STACK_POINTER_REG_CHAR: RegChar = "H"
+STACK_POINTER_REG = Reg(STACK_POINTER_REG_CHAR)
+SPECIAL_REGS: list[RegChar] = [FRAME_POINTER_REG_CHAR, STACK_POINTER_REG_CHAR]
GENERIC_REGS: OrderedDict[RegChar, None] = OrderedDict()
for char in ALL_REGS:
if char not in SPECIAL_REGS:
@@ -41,38 +44,6 @@ def format_asm_row(asm: str) -> str:
else:
return asm
-@dataclass
-class Frame:
- names: list[str]
- bindings: dict[str, Label | StackOffset]
-
- def size(self) -> int:
- return len(self.names)
-
-class FrameStack:
- def __init__(self, stack: list[Frame] = []):
- self.stack: list[Frame] = stack
-
- def push(self, frame: Frame):
- self.stack.append(frame)
-
- def pop(self) -> Frame | None:
- if len(self.stack) == 0: return None
- return self.stack.pop()
-
- def peek(self) -> Frame:
- return self.stack[self.size() - 1]
-
- def size(self) -> int:
- return len(self.stack)
-
- def total_offset(self) -> int:
- total: int = 0
- for frame in self.stack:
- total += frame.size()
-
- return total
-
class Compiler(ast.NodeVisitor):
def __init__(self):
self.const_asm: list[str] = []
@@ -82,8 +53,8 @@ class Compiler(ast.NodeVisitor):
self.function_def_asms: list[str] = []
self.currently_emitting_asm_list = self.program_asm
- self.frame_stack = FrameStack()
- self.tmp_stack_values_n: int = 0
+ self.local_bindings: dict[str, StackOffset] = {}
+ self.const_bindings: dict[str, Label] = {}
self.unique_name_counter = 0
self.latest_break_target: Label | None = None
@@ -102,8 +73,7 @@ class Compiler(ast.NodeVisitor):
self.emit_label(name)
self.emit(f"{value}")
- frame = self.frame_stack.peek()
- frame.bindings[name] = name
+ self.const_bindings[name] = name
self.currently_emitting_asm_list = prev_currently_emitting_asm_list
@@ -113,14 +83,6 @@ class Compiler(ast.NodeVisitor):
self.currently_emitting_asm_list.append(asm)
- def emit_stack_push(self, reg: str):
- self.tmp_stack_values_n += 1
- self.emit(f"spu {reg}")
-
- def emit_stack_pop(self, reg: str):
- self.tmp_stack_values_n -= 1
- self.emit(f"spo {reg}")
-
def emit_label(self, label_name: str):
label_name = label_name.lower()
self.emit(f"@label {label_name}")
@@ -176,6 +138,11 @@ class Compiler(ast.NodeVisitor):
case [ast.Constant(str(value))]:
self.emit(value)
+ # return None
+ with self.allocated_reg() as arg:
+ self.emit(f"ldi 0 {arg}")
+ self.emit(f"spu {arg}")
+
case other: raise Exception(f"asm: invalid args: {other}")
case "store":
@@ -191,12 +158,17 @@ class Compiler(ast.NodeVisitor):
self.emit(f"spo {arg1}")
self.emit(f"str {arg2} {arg1}")
+ # return None
+ self.emit(f"ldi 0 {arg1}")
+ self.emit(f"spu {arg1}")
+
case "load":
if len(args) != 1:
raise Exception("Invalid number of arguments to load: " + str(len(args)))
self.visit(args[0])
+ self.emit("; (load) dereferencing top of stack")
with self.allocated_reg() as arg:
self.emit(f"spo {arg}")
self.emit(f"ldr {arg} {arg}")
@@ -219,7 +191,7 @@ class Compiler(ast.NodeVisitor):
name = self.get_unique_name("int")
self.assign_const(name, value)
self.emit(f"ldi {name} {reg}")
- self.emit(f"ldr {reg} {reg}")
+ self.emit(f"ldr {reg} {reg} ; {name} = {value}")
self.emit(f"spu {reg}")
@@ -228,20 +200,11 @@ class Compiler(ast.NodeVisitor):
frame_names = self.collect_local_variables(stmts)
self.emit("; stack frame with offsets")
-
- frame_bindings: dict[str, Label | StackOffset] = {}
- for idx, name in enumerate(frame_names):
- offset = self.frame_stack.total_offset() + idx
- frame_bindings[name] = offset
-
+ for offset, name in enumerate(frame_names):
+ self.local_bindings[name] = offset
self.emit(f"; {name} {offset}")
- frame = Frame(
- names = frame_names,
- bindings = frame_bindings,
- )
- self.frame_stack.push(frame)
- self.emit(f"addi SP {len(frame.names)} SP")
+ self.emit(f"addi SP {len(frame_names)} SP")
for stmt in stmts:
if type(stmt) == ast.Expr and type(stmt.value) != ast.Call:
@@ -250,16 +213,20 @@ class Compiler(ast.NodeVisitor):
self.visit(stmt)
- self.frame_stack.pop()
- self.emit(f"subi SP {len(frame.names)} SP")
+ self.emit(f"mov FP SP")
+ self.emit("hlt")
def visit_Expr(self, expr: ast.Expr):
- # if self.frame_stack.size == 1 and type(expr.value) != ast.Call:
+ # if type(expr.value) != ast.Call:
# self.emit("; NOP top-level expression")
# return
self.visit(expr.value)
+ with self.allocated_reg() as reg:
+ self.emit("; popping free-standing Expr result from stack")
+ self.emit(f"spo {reg}")
+
def visit_UnaryOp(self, node: ast.UnaryOp):
self.emit(f"; {node.op}")
self.visit(node.operand)
@@ -410,6 +377,8 @@ class Compiler(ast.NodeVisitor):
self.emit_label(label_end)
def visit_Compare(self, node: ast.Compare):
+ self.emit(f"; {node}")
+
if len(node.ops) > 1:
raise Exception("Multiple compare ops not supported")
@@ -420,12 +389,13 @@ class Compiler(ast.NodeVisitor):
left = node.left
right = node.comparators[0]
- self.visit(left)
- self.visit(right)
-
label_true = self.get_unique_name("Compare_true")
label_end = self.get_unique_name("Compare_end")
+ self.visit(left)
+ self.visit(right)
+
+ self.emit(f"; Comparing {left} {op} {right}")
with self.allocated_reg() as reg_lhs, self.allocated_reg() as reg_rhs:
match op:
case ast.Lt(): # lhs < rhs
@@ -539,67 +509,42 @@ class Compiler(ast.NodeVisitor):
raise Exception("Only simple positional args are supported for now in function definitions.")
self.emit_label(fn_name)
- return_address_name = self.get_unique_name("return_address")
local_var_names = self.collect_local_variables(fn_stmts)
- frame_names = [return_address_name] + fn_params + local_var_names
+ frame_names = fn_params + local_var_names
# Move stack pointer to accommodate local variables
if len(local_var_names) > 0:
self.emit(f"addi SP {len(local_var_names)} SP")
+ prev_local_bindings = self.local_bindings
+ self.local_bindings = {}
self.emit("; stack frame with offsets")
- frame_bindings: dict[str, Label | StackOffset] = {}
- for idx, name in enumerate(frame_names):
- offset = self.frame_stack.total_offset() + idx
- frame_bindings[name] = offset
-
+ for offset, name in enumerate(frame_names):
+ self.local_bindings[name] = offset
self.emit(f"; {name} {offset}")
- frame = Frame(
- names = frame_names,
- bindings = frame_bindings
- )
- self.frame_stack.push(frame)
-
for stmt in fn_stmts:
self.visit(stmt)
- self.frame_stack.pop()
+ self.local_bindings = prev_local_bindings
self.currently_emitting_asm_list = prev_currently_emitting_asm_list
def visit_Return(self, node: ast.Return):
self.emit(f"; {node}")
- if self.frame_stack.size() <= 1:
- raise Exception("Encountered return in the top level stack frame")
-
- frame = self.frame_stack.peek()
-
- ret = node.value
- if ret is not None:
- self.visit(ret)
-
with self.allocated_reg() as reg1, self.allocated_reg() as reg2:
- ret_addr_offset = self.frame_stack.total_offset() - frame.size()
- self.emit(f"ldi vt_stack_addr {reg1}") # vector table address of stack segment address
- self.emit(f"ldr {reg1} {reg1}") # stack segment address
- self.emit(f"ldi {ret_addr_offset} {reg2}") # stack offset
- self.emit(f"add {reg1} {reg2} {reg1}") # stack address of return address = stack segment start + stack offset
- self.emit(f"; stack address of return address is stored in reg {reg1}")
-
- if ret is not None:
- self.emit(f"spo {reg2}")
+ if node.value is not None:
+ self.visit(node.value)
else:
- self.emit(f"ldi 0 {reg2}")
-
- self.emit(f"; return value is stored in reg {reg2}")
+ self.emit(f"ldi 0 {reg1}")
+ self.emit(f"spu {reg1}")
- self.emit(f"mov {reg1} SP") # reset stack pointer to return address position (i.e. start of stack frame)
- self.emit(f"ldr {reg1} {reg1}") # return address
+ self.emit(f"; return value is on top of stack")
- self.emit(f"spu {reg2}")
self.emit(f"; return from function")
- self.emit(f"jpr {reg1}")
+ self.emit(f"subi FP 1 FP")
+ self.emit(f"ldr FP {reg2}")
+ self.emit(f"jpr {reg2}")
def visit_Call(self, node: ast.Call):
self.emit(f"; {node}")
@@ -610,7 +555,12 @@ class Compiler(ast.NodeVisitor):
case ast.Name(name):
self.emit(f"; Call function {name}")
+ # Push the current FP
+ self.emit("spu FP")
+ #self.emit("mov SP FP") # BUG: FP needs to be moved AFTER EVALING ARGS! args depend on FP in calling frame if there are names to resolve!
+
# Reserve a stack slot for the return address
+ # FP will point to this slot
with self.allocated_reg() as reg:
self.emit(f"ldi 0 {reg}")
self.emit(f"spu {reg}")
@@ -619,30 +569,31 @@ class Compiler(ast.NodeVisitor):
for arg in node.args:
self.visit(arg)
- with self.allocated_reg() as reg1, self.allocated_reg() as reg2:
+ self.emit(f"subi SP {1 + len(node.args)} FP")
+
+ with self.allocated_reg() as reg:
self.emit("; set up return address and jump to subroutine")
- self.emit(f"subi SP {len(node.args) + 1} {reg1}")
- self.emit(f"lpc {reg2}")
- self.emit(f"addi {reg2} 3 {reg2}")
- self.emit(f"str {reg2} {reg1}")
+ self.emit(f"lpc {reg}")
+ self.emit(f"addi {reg} 4 {reg}") # imm must equal number of primitive instrs from lpc until jpi
+ self.emit(f"str {reg} FP")
+ self.emit(f"addi FP 1 FP")
self.emit(f"jpi {name}")
+ # ...after return from call...
+ self.emit(f"spo {reg}")
+
+ self.emit("mov FP SP") # move stack pointer to base of stack frame, i.e. top of previous frame
+ self.emit("spo FP") # restore FP of previous frame
+ self.emit(f"spu {reg}")
case other:
raise NotImplementedError(f"Unhandled Call: {other}")
def resolve_name(self, name: str) -> Label | StackOffset:
- frames = FrameStack(self.frame_stack.stack.copy())
+ if name in self.local_bindings:
+ return self.local_bindings[name]
- while frames.size() > 0:
- frame = cast(Frame, frames.pop())
-
- if name in frame.bindings:
- addr = frame.bindings[name]
- match addr:
- case Label(value):
- return value
- case StackOffset(value):
- return value
+ if name in self.const_bindings:
+ return self.const_bindings[name]
raise Exception(f"{name} is unbound")
@@ -652,20 +603,18 @@ class Compiler(ast.NodeVisitor):
name = node.id.lower()
addr = self.resolve_name(name)
- with self.allocated_reg() as reg1, self.allocated_reg() as reg2:
+ with self.allocated_reg() as reg:
match addr:
case Label(label):
- self.emit(f"ldi {label} {reg1}")
+ self.emit(f"ldi {label} {reg}")
case StackOffset(offset):
- self.emit(f"ldi vt_stack_addr {reg1}")
- self.emit(f"ldr {reg1} {reg1}")
- self.emit(f"ldi {offset} {reg2}")
- self.emit(f"add {reg1} {reg2} {reg1}")
+ self.emit(f"ldi {offset} {reg}")
+ self.emit(f"add FP {reg} {reg}")
case other:
raise Exception(f"Unsupported addr value: {other}")
- self.emit(f"ldr {reg1} {reg1}")
- self.emit(f"spu {reg1}")
+ self.emit(f"ldr {reg} {reg}")
+ self.emit(f"spu {reg}")
def visit_Assign(self, node: ast.Assign):
self.emit(f"; {node}")
@@ -679,18 +628,17 @@ class Compiler(ast.NodeVisitor):
if type(offset) != StackOffset:
raise Exception(f"Invalid address {offset} for name {name}. Can only assign to stack offsets.")
- self.emit(f"; assigning {name} at stack segment + {offset}")
+ self.emit(f"; assigning {name} at FP + {offset}")
with self.allocated_reg() as reg1, self.allocated_reg() as reg2:
self.emit(f"; evaluating value to be assigned")
self.visit(value)
- self.emit(f"; assigning value to stack segment + {offset}")
- self.emit(f"ldi vt_stack_addr {reg1}")
- self.emit(f"ldr {reg1} {reg1}")
+ self.emit(f"; assigning stack address (FP + {offset}) := top of stack")
+ self.emit(f"spo {reg1}") # value
+
self.emit(f"ldi {offset} {reg2}")
- self.emit(f"add {reg1} {reg2} {reg1}") # address
- self.emit(f"spo {reg2}") # value
- self.emit(f"str {reg2} {reg1}")
+ self.emit(f"add {reg2} FP {reg2}") # address
+ self.emit(f"str {reg1} {reg2}")
case other:
raise Exception(f"Unsupported assign targets: {other}")
@@ -728,10 +676,19 @@ class Optimizer:
asm = [row for row in asm if not len(row) == 0]
asm = [tokenize(row, retain_curlies=True) for row in asm]
asm = self.compact_spu_spo_pattern(asm)
- asm = self.compact_target_mov_pattern(asm)
- asm = self.compact_target_mov_pattern(asm)
- asm = self.compact_mov_source_pattern(asm)
- asm = self.compact_mov_source_pattern(asm)
+
+ # TODO: not safe when setting loading SP and FP
+ # ldr RA SP
+ # mov RA FP
+ # gets optimized to
+ # ldr RA FP
+ #asm = self.compact_target_mov_pattern(asm)
+ #asm = self.compact_target_mov_pattern(asm)
+
+ # TODO: not safe at all. E.g. breaks a while True: pass loop
+ #asm = self.compact_mov_source_pattern(asm)
+ #asm = self.compact_mov_source_pattern(asm)
+
asm = self.compact_spu_load_spo_pattern(asm)
# asm = self.convert_alr_to_ali(asm)
result = "\n".join([format_asm_row(" ".join(row)) for row in asm])
@@ -758,15 +715,27 @@ class Optimizer:
continue
if current[0] == "spu" and next[0] == "spo":
+ print("=== compact_spu_spo_pattern")
+ print(current)
+ print(next)
+
arg_current = current[1]
arg_next = next[1]
+ print("=== arg_current:", arg_current)
+ print("=== arg_next:", arg_next)
+
if arg_current == arg_next:
+ print("=== pass")
pass # remove both spu and spo
else:
+ print("=== mov")
mov = ["mov", arg_current, arg_next]
result.append(mov)
+ print("=== mov:", mov)
+ print("=== last of result:", result[len(result) - 1])
+ print()
i += 1
continue
@@ -890,11 +859,11 @@ asm_out = compiler.compile(
source_py,
)
-optimizer = Optimizer()
-asm_out_optimized = optimizer.optimize(asm_out)
+# optimizer = Optimizer()
+# asm_out_optimized = optimizer.optimize(asm_out)
with open(outfile_path, "w") as f:
f.write(asm_out)
-with open(f"{outfile_path}_optimized", "w") as f:
- f.write(asm_out_optimized)
+# with open(f"{outfile_path}_optimized", "w") as f:
+# f.write(asm_out_optimized)