From 8e7441fdb353fb79a2b779464afbd61441b4e9af Mon Sep 17 00:00:00 2001 From: PleegWat Date: Sat, 5 Sep 2026 15:30:06 +0200 Subject: [PATCH 1/4] Add ISA definitions for symphony Adds both a 'stock' ISA (copied from the game) and one modified for test code --- isa/README.md | 43 ++++++ isa/default.isa | 316 ++++++++++++++++++++++++++++++++++++++++++ isa/test.isa | 358 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 717 insertions(+) create mode 100644 isa/README.md create mode 100644 isa/default.isa create mode 100644 isa/test.isa diff --git a/isa/README.md b/isa/README.md new file mode 100644 index 0000000..592b680 --- /dev/null +++ b/isa/README.md @@ -0,0 +1,43 @@ +Symphony ISA specs for use in stdlib + +# `default.isa` +The stock game ISA. Production code must comply to this. Taken from `symphony_11_functions` in game version 2.1.330A + +# `test.isa` +ISA with additional instructions. These additional instructions may be used in +the tests directory only. Some of these instructions require hardware changes. + +## Labels in more instructions + +`cmp`, `load`, and `store` instructions (but not `pload` and `pstore`) now also accept labels. + +## `qcall %a(label)` +Performs a jump-and-link function call, with label size up to 32 bits. + +_HARDWARE:_ Store PC+4 in the result register when in jump mode. + +## `li %a(register) %b:U32(immediate | label)` +Loads an immediate up to 32 bits long + +_HARDWARE:_ No requirements + +## `halt%c(condition)` +Halts if `flags` matches the condition. + +_HARDWARE:_ Halt if instruction bit 31 is set AND the condition block is true. + +``` +condition +"" 1000 +".all" 1000 +".e" 0001 +".ne" 1001 +".b" 0010 +".ae" 1010 +".be" 0011 +".a" 1011 +".l" 0100 +".ge" 1100 +".le" 0101 +".g" 1101 +``` diff --git a/isa/default.isa b/isa/default.isa new file mode 100644 index 0000000..f9514c8 --- /dev/null +++ b/isa/default.isa @@ -0,0 +1,316 @@ +[settings] +name = "Symphony" + +[fields] + +register +zr 0000 +r1 0001 +r2 0010 +r3 0011 +r4 0100 +r5 0101 +r6 0110 +r7 0111 +r8 1000 +r9 1001 +r10 1010 +r11 1011 +r12 1100 +r13 1101 +sp 1110 +flags 1111 + +[instructions] + +nop +00000000 00000000 00000000 00000000 +# (31337_88272577071256, `Does nothing.`) + +in %a(register) +00000001 aaaa0000 00000000 00000000 +# (31337_44524771082050, `Loads an input and stores it in %a.`) + +out %b(register) +00000010 00000000 0000bbbb 00000000 +# (31337_18254089726214, `Sends %b to output.`) + +out %a:U16(immediate) +00010010 00000000 aaaaaaaa aaaaaaaa +# (31337_15915531259935, `Sends %a to output.`) + +keyboard %a(register) +00000011 aaaa0000 00000000 00000000 +# (31337_27868418224252, `Loads keyboard input and stores it to %a.`) + +screen %a(register), %b(register) +00000100 0000aaaa 0000bbbb 00000000 +# (31337_39857449355186, `Stores the value of %b in screen setting %a.`) + +screen %a(register), %b:U16(immediate) +00010100 0000aaaa bbbbbbbb bbbbbbbb +# (31337_12835125621741, `Stores the value of %b in screen setting %a.`) + +time_0 %a(register) +00000101 aaaa0000 00000000 00000000 +# (31337_72551400437977, `Loads the lower four bytes of the time value and stores it to %a.`) + +time_1 %a(register) +00000110 aaaa0000 00000000 00000000 +# (31337_68219187873304, `Loads the upper four bytes of the time value and stores it to %a.`) + +counter %a(register) +00000111 aaaa0000 00000000 00000000 +# (31337_67376584796076, `Loads the counter value and stores it to %a.`) + + + +nand %a(register), %b(register), %c(register) +00100000 aaaabbbb 0000cccc 00000000 +# (31337_86705346481666, `NAND %b and %c and stores the result in %a.`) + +or %a(register), %b(register), %c(register) +00100001 aaaabbbb 0000cccc 00000000 +# (31337_40732211165530, `OR %b and %c and stores the result in %a.`) + +and %a(register), %b(register), %c(register) +00100010 aaaabbbb 0000cccc 00000000 +# (31337_85679146831122, `AND %b and %c and stores the result in %a.`) + +nor %a(register), %b(register), %c(register) +00100011 aaaabbbb 0000cccc 00000000 +# (31337_37333076617857, `NOR %b and %c and stores the result in %a.`) + +add %a(register), %b(register), %c(register) +00100100 aaaabbbb 0000cccc 00000000 +# (31337_51030225266712, `ADD %b and %c and stores the result in %a.`) + +sub %a(register), %b(register), %c(register) +00100101 aaaabbbb 0000cccc 00000000 +# (31337_28652904157569, `SUB %b and %c and stores the result in %a.`) + +xor %a(register), %b(register), %c(register) +00100110 aaaabbbb 0000cccc 00000000 +# (31337_46967848572964, `XOR %b and %c and stores the result in %a.`) + +lsl %a(register), %b(register), %c(register) +00100111 aaaabbbb 0000cccc 00000000 +# (31337_13576771671264, `Logical shifts left %b by %c and stores the result in %a.`) + +lsr %a(register), %b(register), %c(register) +00101000 aaaabbbb 0000cccc 00000000 +# (31337_67019902294705, `Logical shifts right %b by %c and stores the result in %a.`) + +asr %a(register), %b(register), %c(register) +00101001 aaaabbbb 0000cccc 00000000 +# (31337_42626144645228, `Arithmetic shift right %b by %c and stores the result in %a.`) + +cmp %a(register), %b(register) +00101010 1111aaaa 0000bbbb 00000000 +# (31337_54565380946620, `Compares %a and %b and stores the result in the 'flags' register.`) + + +nand %a(register), %b(register), %c:U16(immediate | label) +00110000 aaaabbbb cccccccc cccccccc +# (31337_75302656449127, `NAND %b and %c and stores the result in %a.`) + +or %a(register), %b(register), %c:U16(immediate | label) +00110001 aaaabbbb cccccccc cccccccc +# (31337_30574433901064, `OR %b and %c and stores the result in %a.`) + +nor %a(register), %b(register), %c:U16(immediate | label) +00110011 aaaabbbb cccccccc cccccccc +# (31337_46087142860391, `NOR %b and %c and stores the result in %a.`) + +and %a(register), %b(register), %c:U16(immediate | label) +00110010 aaaabbbb cccccccc cccccccc +# (31337_86713121915282, `AND %b and %c and stores the result in %a.`) + +add %a(register), %b(register), %c:U16(immediate | label) +00110100 aaaabbbb cccccccc cccccccc +# (31337_23349431010010, `ADD %b and %c and stores the result in %a.`) + +sub %a(register), %b(register), %c:U16(immediate | label) +00110101 aaaabbbb cccccccc cccccccc +# (31337_67495552371225, `SUB %b and %c and stores the result in %a.`) + +xor %a(register), %b(register), %c:U16(immediate | label) +00110110 aaaabbbb cccccccc cccccccc +# (31337_66785854415645, `XOR %b and %c and stores the result in %a.`) + +lsl %a(register), %b(register), %c:U16(immediate | label) +00110111 aaaabbbb cccccccc cccccccc +# (31337_54577249258785, `Logical shifts left %b by %c and stores the result in %a.`) + +lsr %a(register), %b(register), %c:U16(immediate | label) +00111000 aaaabbbb cccccccc cccccccc +# (31337_16685334571248, `Logical shifts right %b by %c and stores the result in %a.`) + +asr %a(register), %b(register), %c:U16(immediate | label) +00111001 aaaabbbb cccccccc cccccccc +# (31337_55551510150818, `Arithmetic shifts right %b and %c and stores the result in %a.`) + +cmp %a(register), %b:U16(immediate) +00111010 1111aaaa bbbbbbbb bbbbbbbb +# (31337_37102964808364, `Compares %a and %b and stores the result in the 'flags' register.`) + + +jmp %a(register) +01001000 00001111 0000aaaa 00000000 +# (31337_74148826866592, `Jumps to %a.`) + + +jmp %a:U16(immediate | label) +01011000 00001111 aaaaaaaa aaaaaaaa +# (31337_90876214388280, `Jumps to %a.`) + +je %a:U16(immediate | label) +01010001 00001111 aaaaaaaa aaaaaaaa +# (31337_88180305667389, `Jumps to %a if the values were equal (reading results from 'flags').`) + +jne %a:U16(immediate | label) +01011001 00001111 aaaaaaaa aaaaaaaa +# (31337_67178948469318, `Jumps to %a if the values were not equal (reading results from 'flags').`) + + +jb %a:U16(immediate | label) +01010010 00001111 aaaaaaaa aaaaaaaa +# (31337_31763492459833, `Jumps to %a if the first value was below (unsigned) the second (reading results from 'flags').`) + +jae %a:U16(immediate | label) +01011010 00001111 aaaaaaaa aaaaaaaa +# (31337_82087388048746, `Jumps to %a if the first value was above (unsigned) or equal to the second (reading results from 'flags').`) + +jbe %a:U16(immediate | label) +01010011 00001111 aaaaaaaa aaaaaaaa +# (31337_26183125927881, `Jumps to %a if the First value was below (unsigned) or equal to the second (reading results from 'flags').`) + +ja %a:U16(immediate | label) +01011011 00001111 aaaaaaaa aaaaaaaa +# (31337_11626177279992, `Jumps to %a if the first value was above (unsigned) the second (reading results from 'flags').`) + + +jl %a:U16(immediate | label) +01010100 00001111 aaaaaaaa aaaaaaaa +# (31337_71637103729391, `Jumps to %a if the first value was less (signed) than the second (reading results from 'flags').`) + +jge %a:U16(immediate | label) +01011100 00001111 aaaaaaaa aaaaaaaa +# (31337_53499765587663, `Jumps to %a if the first value was greater (signed) or equal to the second (reading results from 'flags').`) + +jle %a:U16(immediate | label) +01010101 00001111 aaaaaaaa aaaaaaaa +# (31337_77040234358389, `Jumps to %a if the first value was less (signed) or equal to the second (reading results from 'flags').`) + +jg %a:U16(immediate | label) +01011101 00001111 aaaaaaaa aaaaaaaa +# (31337_71317192057126, `Jumps to %a if the first value was greater (signed) than the second (reading results from 'flags').`) + + + +load_8 %dest(register), [%adr(register)] +01100000 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_8 %dest(register), [%adr:U16(immediate)] +01110000 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_16 %dest(register), [%adr(register)] +01100001 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_16 %dest(register), [%adr:U16(immediate)] +01110001 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_32 %dest(register), [%adr(register)] +01100010 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_32 %dest(register), [%adr:U16(immediate)] +01110010 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +pload %dest(register), [%adr(register)] +01100011 dddd0000 0000aaaa 00000000 +# (31337_89257021109854, `Loads address %adr from persistent memory and stores it to %dest.`) + +pload %dest(register), [%adr:U16(immediate)] +01110011 dddd0000 aaaaaaaa aaaaaaaa +# (31337_89257021109854, `Loads address %adr from persistent memory and stores it to %dest.`) + +store_8 [%adr(register)], %value(register) +01100100 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_8 [%adr:U16(immediate)], %value(register) +01110100 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_16 [%adr(register)], %value(register) +01100101 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_16 [%adr:U16(immediate)], %value(register) +01110101 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_32 [%adr(register)], %value(register) +01100110 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_32 [%adr:U16(immediate)], %value(register) +01110110 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +pstore [%adr(register)], %value(register) +01100111 0000vvvv 0000aaaa 00000000 +# (31337_13110303123442, `Stores %value to address %adr in persistent memory.`) + +pstore [%adr:U16(immediate)], %value(register) +01110111 0000vvvv aaaaaaaa aaaaaaaa +# (31337_13110303123442, `Stores %value to address %adr in persistent memory.`) + + +mov %a(register), %b(register) +00100001 aaaa0000 0000bbbb 00000000 +# (31337_53941960758392, `Moves a value to %a from %b.`) + +mov %a(register), %b:U16(immediate | label) +00110001 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_34859363394334, `Moves a value to %a.`) + +neg %a(register), %b(register) +00100101 aaaa0000 0000bbbb 00000000 +# (31337_72894099288447, `Negates a %b and stores it in %a.`) + +neg %a(register), %b:U16(immediate | label) +00110101 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_57504570243305, `Negates a value and stores it in %a.`) + +not %a(register), %b(register) +00100011 aaaa0000 0000bbbb 00000000 +# (31337_55357258069734, `Toggles the bits of %b and stores it in %a.`) + +not %a(register), %b:U16(immediate | label) +00110011 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_40508048121543, `Toggles the bits of a value and stores it in %a.`) + + +push %a(register) +00110101 11101110 00000000 00000100 01100110 0000aaaa 00001110 00000000 +# (31337_28545157055801, `Pushes %a onto the stack. This instruction is a synonym for: sub sp, sp, 4 store_32 [sp], %a`) + +pop %a(register) +01100010 aaaa0000 00001110 00000000 00110100 11101110 00000000 00000100 +# (31337_54469754973269, `Pops %a off the stack. This instruction is a synonym for: load_32 %a, [sp] add sp, sp, 4`) + +call %a(label) +00000111 11110000 00000000 00000000 00110100 11111111 00000000 00010100 00110101 11101110 00000000 00000100 01100110 00001111 00001110 00000000 01011000 00001111 aaaaaaaa aaaaaaaa +# (31337_57788320241950, `Calls %a. Overwrites the flag register. This instruction is a synonym for: counter flags add flags, flags, 20 sub sp, sp, 4 store_32 [sp], flags jmp %a`) + +ret +01100010 11110000 00001110 00000000 00110100 11101110 00000000 00000100 01001000 00001111 00001111 00000000 +# (31337_48332460366102, `Returns from the last function call. Overwrites the flag register. This instruction is a synonym for: load_32 flags, [sp] add sp, sp, 4 jmp flags`) + diff --git a/isa/test.isa b/isa/test.isa new file mode 100644 index 0000000..5aca729 --- /dev/null +++ b/isa/test.isa @@ -0,0 +1,358 @@ +[settings] +name = "Symphony" + +[fields] + +register +zr 0000 +r1 0001 +r2 0010 +r3 0011 +r4 0100 +r5 0101 +r6 0110 +r7 0111 +r8 1000 +r9 1001 +r10 1010 +r11 1011 +r12 1100 +r13 1101 +sp 1110 +flags 1111 + +condition +"" 1000 +".all" 1000 +".e" 0001 +".ne" 1001 +".b" 0010 +".ae" 1010 +".be" 0011 +".a" 1011 +".l" 0100 +".ge" 1100 +".le" 0101 +".g" 1101 + +[instructions] + +nop +00000000 00000000 00000000 00000000 +# (31337_88272577071256, `Does nothing.`) + +in %a(register) +00000001 aaaa0000 00000000 00000000 +# (31337_44524771082050, `Loads an input and stores it in %a.`) + +out %b(register) +00000010 00000000 0000bbbb 00000000 +# (31337_18254089726214, `Sends %b to output.`) + +out %a:U16(immediate) +00010010 00000000 aaaaaaaa aaaaaaaa +# (31337_15915531259935, `Sends %a to output.`) + +keyboard %a(register) +00000011 aaaa0000 00000000 00000000 +# (31337_27868418224252, `Loads keyboard input and stores it to %a.`) + +screen %a(register), %b(register) +00000100 0000aaaa 0000bbbb 00000000 +# (31337_39857449355186, `Stores the value of %b in screen setting %a.`) + +screen %a(register), %b:U16(immediate) +00010100 0000aaaa bbbbbbbb bbbbbbbb +# (31337_12835125621741, `Stores the value of %b in screen setting %a.`) + +time_0 %a(register) +00000101 aaaa0000 00000000 00000000 +# (31337_72551400437977, `Loads the lower four bytes of the time value and stores it to %a.`) + +time_1 %a(register) +00000110 aaaa0000 00000000 00000000 +# (31337_68219187873304, `Loads the upper four bytes of the time value and stores it to %a.`) + +counter %a(register) +00000111 aaaa0000 00000000 00000000 +# (31337_67376584796076, `Loads the counter value and stores it to %a.`) + + + +nand %a(register), %b(register), %c(register) +00100000 aaaabbbb 0000cccc 00000000 +# (31337_86705346481666, `NAND %b and %c and stores the result in %a.`) + +or %a(register), %b(register), %c(register) +00100001 aaaabbbb 0000cccc 00000000 +# (31337_40732211165530, `OR %b and %c and stores the result in %a.`) + +and %a(register), %b(register), %c(register) +00100010 aaaabbbb 0000cccc 00000000 +# (31337_85679146831122, `AND %b and %c and stores the result in %a.`) + +nor %a(register), %b(register), %c(register) +00100011 aaaabbbb 0000cccc 00000000 +# (31337_37333076617857, `NOR %b and %c and stores the result in %a.`) + +add %a(register), %b(register), %c(register) +00100100 aaaabbbb 0000cccc 00000000 +# (31337_51030225266712, `ADD %b and %c and stores the result in %a.`) + +sub %a(register), %b(register), %c(register) +00100101 aaaabbbb 0000cccc 00000000 +# (31337_28652904157569, `SUB %b and %c and stores the result in %a.`) + +xor %a(register), %b(register), %c(register) +00100110 aaaabbbb 0000cccc 00000000 +# (31337_46967848572964, `XOR %b and %c and stores the result in %a.`) + +lsl %a(register), %b(register), %c(register) +00100111 aaaabbbb 0000cccc 00000000 +# (31337_13576771671264, `Logical shifts left %b by %c and stores the result in %a.`) + +lsr %a(register), %b(register), %c(register) +00101000 aaaabbbb 0000cccc 00000000 +# (31337_67019902294705, `Logical shifts right %b by %c and stores the result in %a.`) + +asr %a(register), %b(register), %c(register) +00101001 aaaabbbb 0000cccc 00000000 +# (31337_42626144645228, `Arithmetic shift right %b by %c and stores the result in %a.`) + +cmp %a(register), %b(register) +00101010 1111aaaa 0000bbbb 00000000 +# (31337_54565380946620, `Compares %a and %b and stores the result in the 'flags' register.`) + + +nand %a(register), %b(register), %c:U16(immediate | label) +00110000 aaaabbbb cccccccc cccccccc +# (31337_75302656449127, `NAND %b and %c and stores the result in %a.`) + +or %a(register), %b(register), %c:U16(immediate | label) +00110001 aaaabbbb cccccccc cccccccc +# (31337_30574433901064, `OR %b and %c and stores the result in %a.`) + +nor %a(register), %b(register), %c:U16(immediate | label) +00110011 aaaabbbb cccccccc cccccccc +# (31337_46087142860391, `NOR %b and %c and stores the result in %a.`) + +and %a(register), %b(register), %c:U16(immediate | label) +00110010 aaaabbbb cccccccc cccccccc +# (31337_86713121915282, `AND %b and %c and stores the result in %a.`) + +add %a(register), %b(register), %c:U16(immediate | label) +00110100 aaaabbbb cccccccc cccccccc +# (31337_23349431010010, `ADD %b and %c and stores the result in %a.`) + +sub %a(register), %b(register), %c:U16(immediate | label) +00110101 aaaabbbb cccccccc cccccccc +# (31337_67495552371225, `SUB %b and %c and stores the result in %a.`) + +xor %a(register), %b(register), %c:U16(immediate | label) +00110110 aaaabbbb cccccccc cccccccc +# (31337_66785854415645, `XOR %b and %c and stores the result in %a.`) + +lsl %a(register), %b(register), %c:U16(immediate | label) +00110111 aaaabbbb cccccccc cccccccc +# (31337_54577249258785, `Logical shifts left %b by %c and stores the result in %a.`) + +lsr %a(register), %b(register), %c:U16(immediate | label) +00111000 aaaabbbb cccccccc cccccccc +# (31337_16685334571248, `Logical shifts right %b by %c and stores the result in %a.`) + +asr %a(register), %b(register), %c:U16(immediate | label) +00111001 aaaabbbb cccccccc cccccccc +# (31337_55551510150818, `Arithmetic shifts right %b and %c and stores the result in %a.`) + +cmp %a(register), %b:U16(immediate | label) +00111010 1111aaaa bbbbbbbb bbbbbbbb +# (31337_37102964808364, `Compares %a and %b and stores the result in the 'flags' register.`) + + +jmp %a(register) +01001000 00001111 0000aaaa 00000000 +# (31337_74148826866592, `Jumps to %a.`) + + +jmp %a:U16(immediate | label) +01011000 00001111 aaaaaaaa aaaaaaaa +# (31337_90876214388280, `Jumps to %a.`) + +je %a:U16(immediate | label) +01010001 00001111 aaaaaaaa aaaaaaaa +# (31337_88180305667389, `Jumps to %a if the values were equal (reading results from 'flags').`) + +jne %a:U16(immediate | label) +01011001 00001111 aaaaaaaa aaaaaaaa +# (31337_67178948469318, `Jumps to %a if the values were not equal (reading results from 'flags').`) + + +jb %a:U16(immediate | label) +01010010 00001111 aaaaaaaa aaaaaaaa +# (31337_31763492459833, `Jumps to %a if the first value was below (unsigned) the second (reading results from 'flags').`) + +jae %a:U16(immediate | label) +01011010 00001111 aaaaaaaa aaaaaaaa +# (31337_82087388048746, `Jumps to %a if the first value was above (unsigned) or equal to the second (reading results from 'flags').`) + +jbe %a:U16(immediate | label) +01010011 00001111 aaaaaaaa aaaaaaaa +# (31337_26183125927881, `Jumps to %a if the First value was below (unsigned) or equal to the second (reading results from 'flags').`) + +ja %a:U16(immediate | label) +01011011 00001111 aaaaaaaa aaaaaaaa +# (31337_11626177279992, `Jumps to %a if the first value was above (unsigned) the second (reading results from 'flags').`) + + +jl %a:U16(immediate | label) +01010100 00001111 aaaaaaaa aaaaaaaa +# (31337_71637103729391, `Jumps to %a if the first value was less (signed) than the second (reading results from 'flags').`) + +jge %a:U16(immediate | label) +01011100 00001111 aaaaaaaa aaaaaaaa +# (31337_53499765587663, `Jumps to %a if the first value was greater (signed) or equal to the second (reading results from 'flags').`) + +jle %a:U16(immediate | label) +01010101 00001111 aaaaaaaa aaaaaaaa +# (31337_77040234358389, `Jumps to %a if the first value was less (signed) or equal to the second (reading results from 'flags').`) + +jg %a:U16(immediate | label) +01011101 00001111 aaaaaaaa aaaaaaaa +# (31337_71317192057126, `Jumps to %a if the first value was greater (signed) than the second (reading results from 'flags').`) + + + +load_8 %dest(register), [%adr(register)] +01100000 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_8 %dest(register), [%adr:U16(immediate | label)] +01110000 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_16 %dest(register), [%adr(register)] +01100001 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_16 %dest(register), [%adr:U16(immediate | label)] +01110001 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_32 %dest(register), [%adr(register)] +01100010 dddd0000 0000aaaa 00000000 +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +load_32 %dest(register), [%adr:U16(immediate | label)] +01110010 dddd0000 aaaaaaaa aaaaaaaa +# (31337_57200935026773, `Loads address %adr from main memory and stores it to %dest.`) + +pload %dest(register), [%adr(register)] +01100011 dddd0000 0000aaaa 00000000 +# (31337_89257021109854, `Loads address %adr from persistent memory and stores it to %dest.`) + +pload %dest(register), [%adr:U16(immediate)] +01110011 dddd0000 aaaaaaaa aaaaaaaa +# (31337_89257021109854, `Loads address %adr from persistent memory and stores it to %dest.`) + +store_8 [%adr(register)], %value(register) +01100100 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_8 [%adr:U16(immediate | label)], %value(register) +01110100 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_16 [%adr(register)], %value(register) +01100101 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_16 [%adr:U16(immediate | label)], %value(register) +01110101 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_32 [%adr(register)], %value(register) +01100110 0000vvvv 0000aaaa 00000000 +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +store_32 [%adr:U16(immediate | label)], %value(register) +01110110 0000vvvv aaaaaaaa aaaaaaaa +# (31337_61040780958703, `Stores %value to address %adr in main memory.`) + +pstore [%adr(register)], %value(register) +01100111 0000vvvv 0000aaaa 00000000 +# (31337_13110303123442, `Stores %value to address %adr in persistent memory.`) + +pstore [%adr:U16(immediate)], %value(register) +01110111 0000vvvv aaaaaaaa aaaaaaaa +# (31337_13110303123442, `Stores %value to address %adr in persistent memory.`) + + +mov %a(register), %b(register) +00100001 aaaa0000 0000bbbb 00000000 +# (31337_53941960758392, `Moves a value to %a from %b.`) + +mov %a(register), %b:U16(immediate | label) +00110001 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_34859363394334, `Moves a value to %a.`) + +neg %a(register), %b(register) +00100101 aaaa0000 0000bbbb 00000000 +# (31337_72894099288447, `Negates a %b and stores it in %a.`) + +neg %a(register), %b:U16(immediate | label) +00110101 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_57504570243305, `Negates a value and stores it in %a.`) + +not %a(register), %b(register) +00100011 aaaa0000 0000bbbb 00000000 +# (31337_55357258069734, `Toggles the bits of %b and stores it in %a.`) + +not %a(register), %b:U16(immediate | label) +00110011 aaaa0000 bbbbbbbb bbbbbbbb +# (31337_40508048121543, `Toggles the bits of a value and stores it in %a.`) + + +push %a(register) +00110101 11101110 00000000 00000100 01100110 0000aaaa 00001110 00000000 +# (31337_28545157055801, `Pushes %a onto the stack. This instruction is a synonym for: sub sp, sp, 4 store_32 [sp], %a`) + +pop %a(register) +01100010 aaaa0000 00001110 00000000 00110100 11101110 00000000 00000100 +# (31337_54469754973269, `Pops %a off the stack. This instruction is a synonym for: load_32 %a, [sp] add sp, sp, 4`) + +call %a(label) +00000111 11110000 00000000 00000000 00110100 11111111 00000000 00010100 00110101 11101110 00000000 00000100 01100110 00001111 00001110 00000000 01011000 00001111 aaaaaaaa aaaaaaaa +# (31337_57788320241950, `Calls %a. Overwrites the flag register. This instruction is a synonym for: counter flags add flags, flags, 20 sub sp, sp, 4 store_32 [sp], flags jmp %a`) + +ret +01100010 11110000 00001110 00000000 00110100 11101110 00000000 00000100 01001000 00001111 00001111 00000000 +# (31337_48332460366102, `Returns from the last function call. Overwrites the flag register. This instruction is a synonym for: load_32 flags, [sp] add sp, sp, 4 jmp flags`) + + +li %r(register), %a:S33(immediate | label) +; assert(0 - 0x80000000 <= %a, "%a is too low") +; assert(%a <= 0xffffffff, "%a is too high") +%nota = ~%a +when 0x0000 <= %a && %a <= 0xffff: 00110001 rrrr0000 %a[15:0] ; First 64k +when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 ; Last 64k +when !(%a & 0x0f) && %a < 0xffff0: 00110001 rrrr0000 %a[19:4] 00100111 rrrrrrrr 00000000 00000100 ; 16-byte aligned +when !(%a & 0x03) && %a < 0x3fffc: 00110001 rrrr0000 %a[17:2] 00100111 rrrrrrrr 00000000 00000010 ; 4-byte aligned +00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] ; Any 32-bit +# Load 32-bit immediate %a into %r + +qcall %a:U32(label) +; assert(0 - 0x80000000 <= %a, "%a is too low") +; assert(%a <= 0xffffffff, "%a is too high") +%r = 13 +%f = 15 +%nota = ~%a +when 0x0000 <= %a && %a <= 0xffff: 01011000 rrrrffff %a[15:0] ; First 64k +when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 01001000 rrrrffff 0000rrrr 00000000 ; Last 64k +when !(%a & 0x0f) && %a < 0xffff0: 00110001 rrrr0000 %a[19:4] 00100111 rrrrrrrr 00000000 00000100 01001000 rrrrffff 0000rrrr 00000000 ; 16-byte aligned +when !(%a & 0x03) && %a < 0x3fffc: 00110001 rrrr0000 %a[17:2] 00100111 rrrrrrrr 00000000 00000010 01001000 rrrrffff 0000rrrr 00000000 ; 4-byte aligned +00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] 01001000 rrrrffff 0000rrrr 00000000 ; Any 32-bit +# Jump and link to 32-bit label + +halt%c(condition) +1000cccc 00001111 00000000 00000000 +# Halt on condition %c From 2f09320fa56c3eca48810371c39e66f925f14c9b Mon Sep 17 00:00:00 2001 From: PleegWat Date: Sat, 5 Sep 2026 15:39:55 +0200 Subject: [PATCH 2/4] Add optimization for arbitrary aligned values Any value with 16 or less significant bits but larger than 64k is loaded in one fewer cycle --- isa/test.isa | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/isa/test.isa b/isa/test.isa index 5aca729..f030f08 100644 --- a/isa/test.isa +++ b/isa/test.isa @@ -332,11 +332,12 @@ ret li %r(register), %a:S33(immediate | label) ; assert(0 - 0x80000000 <= %a, "%a is too low") ; assert(%a <= 0xffffffff, "%a is too high") +%s = trailing_zeros(%a) +%sa = %a >> %s %nota = ~%a when 0x0000 <= %a && %a <= 0xffff: 00110001 rrrr0000 %a[15:0] ; First 64k when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 ; Last 64k -when !(%a & 0x0f) && %a < 0xffff0: 00110001 rrrr0000 %a[19:4] 00100111 rrrrrrrr 00000000 00000100 ; 16-byte aligned -when !(%a & 0x03) && %a < 0x3fffc: 00110001 rrrr0000 %a[17:2] 00100111 rrrrrrrr 00000000 00000010 ; 4-byte aligned +when %sa < 0xffff : 00110001 rrrr0000 %sa[15:0] 00100011 rrrrrrrr 00000000 %s[7:0] ; Aligned 00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] ; Any 32-bit # Load 32-bit immediate %a into %r @@ -345,14 +346,16 @@ qcall %a:U32(label) ; assert(%a <= 0xffffffff, "%a is too high") %r = 13 %f = 15 +%s = trailing_zeros(%a) +%sa = %a >> %s %nota = ~%a when 0x0000 <= %a && %a <= 0xffff: 01011000 rrrrffff %a[15:0] ; First 64k when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 01001000 rrrrffff 0000rrrr 00000000 ; Last 64k -when !(%a & 0x0f) && %a < 0xffff0: 00110001 rrrr0000 %a[19:4] 00100111 rrrrrrrr 00000000 00000100 01001000 rrrrffff 0000rrrr 00000000 ; 16-byte aligned -when !(%a & 0x03) && %a < 0x3fffc: 00110001 rrrr0000 %a[17:2] 00100111 rrrrrrrr 00000000 00000010 01001000 rrrrffff 0000rrrr 00000000 ; 4-byte aligned +when %sa < 0xffff : 00110001 rrrr0000 %sa[15:0] 00100011 rrrrrrrr 00000000 %s[7:0] 01001000 rrrrffff 0000rrrr 00000000 ; Aligned 00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] 01001000 rrrrffff 0000rrrr 00000000 ; Any 32-bit # Jump and link to 32-bit label halt%c(condition) 1000cccc 00001111 00000000 00000000 # Halt on condition %c + From 4c0cd79fdd1726bfdcf1b080178224306ae90dc5 Mon Sep 17 00:00:00 2001 From: PleegWat Date: Sat, 5 Sep 2026 16:37:51 +0200 Subject: [PATCH 3/4] Fix several bugs --- isa/test.isa | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/isa/test.isa b/isa/test.isa index f030f08..a994441 100644 --- a/isa/test.isa +++ b/isa/test.isa @@ -334,11 +334,11 @@ li %r(register), %a:S33(immediate | label) ; assert(%a <= 0xffffffff, "%a is too high") %s = trailing_zeros(%a) %sa = %a >> %s -%nota = ~%a -when 0x0000 <= %a && %a <= 0xffff: 00110001 rrrr0000 %a[15:0] ; First 64k -when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 ; Last 64k -when %sa < 0xffff : 00110001 rrrr0000 %sa[15:0] 00100011 rrrrrrrr 00000000 %s[7:0] ; Aligned -00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] ; Any 32-bit +%nota = %a ^ 0xffffffff ; Needs xor; ~ operator does not generate leading high bits +when %a <=u 0xffff : 00110001 %r[3:0]0000 %a[15:0] ; First 64k +when %nota <= 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 ; Last 64k +when %sa <= 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] ; Aligned +00110001 %r[3:0]0000 %a[31:16] 00110111 %r[3:0]%r[3:0] 00000000 00010000 00110001 %r[3:0]%r[3:0] %a[15:0] ; Any 32-bit # Load 32-bit immediate %a into %r qcall %a:U32(label) @@ -348,14 +348,13 @@ qcall %a:U32(label) %f = 15 %s = trailing_zeros(%a) %sa = %a >> %s -%nota = ~%a -when 0x0000 <= %a && %a <= 0xffff: 01011000 rrrrffff %a[15:0] ; First 64k -when %nota <= 0xffff : 00110001 rrrr0000 %nota[15:0] 00100011 rrrr0000 0000rrrr 00000000 01001000 rrrrffff 0000rrrr 00000000 ; Last 64k -when %sa < 0xffff : 00110001 rrrr0000 %sa[15:0] 00100011 rrrrrrrr 00000000 %s[7:0] 01001000 rrrrffff 0000rrrr 00000000 ; Aligned -00110001 rrrr0000 %a[31:16] 00100111 rrrrrrrr 00000000 00010000 00110001 rrrrrrrr %a[15:0] 01001000 rrrrffff 0000rrrr 00000000 ; Any 32-bit +%nota = %a ^ 0xffffffff ; Needs xor; ~ operator does not generate leading high bits +when %a <=u 0xffff : 01011000 %r[3:0]ffff %a[15:0] ; First 64k +when %nota <= 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Last 64k +when %sa <= 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Aligned +00110001 %r[3:0]0000 %a[31:16] 00110111 %r[3:0]%r[3:0] 00000000 00010000 00110001 %r[3:0]%r[3:0] %a[15:0] 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Any 32-bit # Jump and link to 32-bit label halt%c(condition) 1000cccc 00001111 00000000 00000000 # Halt on condition %c - From dd20822ee11e38f77f1075122dfb73a3c543a0cc Mon Sep 17 00:00:00 2001 From: PleegWat Date: Sat, 5 Sep 2026 16:41:52 +0200 Subject: [PATCH 4/4] Use all unsigned compares --- isa/test.isa | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/isa/test.isa b/isa/test.isa index a994441..45b78ec 100644 --- a/isa/test.isa +++ b/isa/test.isa @@ -334,11 +334,11 @@ li %r(register), %a:S33(immediate | label) ; assert(%a <= 0xffffffff, "%a is too high") %s = trailing_zeros(%a) %sa = %a >> %s -%nota = %a ^ 0xffffffff ; Needs xor; ~ operator does not generate leading high bits -when %a <=u 0xffff : 00110001 %r[3:0]0000 %a[15:0] ; First 64k -when %nota <= 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 ; Last 64k -when %sa <= 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] ; Aligned -00110001 %r[3:0]0000 %a[31:16] 00110111 %r[3:0]%r[3:0] 00000000 00010000 00110001 %r[3:0]%r[3:0] %a[15:0] ; Any 32-bit +%nota = %a ^ 0xffffffff +when %a <=u 0xffff : 00110001 %r[3:0]0000 %a[15:0] ; First 64k +when %nota <=u 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 ; Last 64k +when %sa <=u 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] ; Aligned +00110001 %r[3:0]0000 %a[31:16] 00110111 %r[3:0]%r[3:0] 00000000 00010000 00110001 %r[3:0]%r[3:0] %a[15:0] ; Any 32-bit # Load 32-bit immediate %a into %r qcall %a:U32(label) @@ -348,13 +348,14 @@ qcall %a:U32(label) %f = 15 %s = trailing_zeros(%a) %sa = %a >> %s -%nota = %a ^ 0xffffffff ; Needs xor; ~ operator does not generate leading high bits -when %a <=u 0xffff : 01011000 %r[3:0]ffff %a[15:0] ; First 64k -when %nota <= 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Last 64k -when %sa <= 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Aligned +%nota = %a ^ 0xffffffff +when %a <=u 0xffff : 01011000 %r[3:0]ffff %a[15:0] ; First 64k +when %nota <=u 0xffff: 00110001 %r[3:0]0000 %nota[15:0] 00100011 %r[3:0]0000 0000%r[3:0] 00000000 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Last 64k +when %sa <=u 0xffff : 00110001 %r[3:0]0000 %sa[15:0] 00110111 %r[3:0]%r[3:0] 00000000 %s[7:0] 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Aligned 00110001 %r[3:0]0000 %a[31:16] 00110111 %r[3:0]%r[3:0] 00000000 00010000 00110001 %r[3:0]%r[3:0] %a[15:0] 01001000 %r[3:0]ffff 0000%r[3:0] 00000000 ; Any 32-bit # Jump and link to 32-bit label halt%c(condition) 1000cccc 00001111 00000000 00000000 # Halt on condition %c +