diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-13 23:12:05 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2023-11-13 23:12:05 +0200 |
| commit | 14d8401c721fae8367fa24db20af4e344faafdd4 (patch) | |
| tree | 58931d22d9c903a15bbe137c571dd76c7a98799b | |
| parent | e2b7385b03a6dc9c8c39dde5c049cd74b0768bd1 (diff) | |
Fix calling issues
| -rw-r--r-- | asm/ast_compiler_bootstrap.atk16 | 5 | ||||
| -rw-r--r-- | asm/test_py_src.atk16 | 285 | ||||
| -rw-r--r-- | asm/test_py_src.atk16_optimized | 202 | ||||
| -rw-r--r-- | asm/test_py_src.py | 9 | ||||
| -rw-r--r-- | digital/atk16.dig | 108 | ||||
| -rw-r--r-- | digital/atk16_mem.dig | 2 | ||||
| -rw-r--r-- | src/ast_compiler.py | 255 |
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) |
