--- /dev/null
+#define PROGINSTR stw r0, PDATA(r13)
+.data
+.org 0x10
+inputdata:
+;8 * 8 4
+.fill 1, 0x382A3834
+;1 X * 8
+.fill 1, 0x31582A38
+;+ D X -
+.fill 1, 0x2B44582D
+;P \xF8 J D
+.fill 1, 0x50F84A44
+;+ * 8 6
+.fill 1, 0x2B2A3836
+;\000 \020 I D
+.fill 1, 0x00204944
+;~ < \000 \000
+.fill 1, 0x7E3C0000
+;8 P \005 J
+.fill 1, 0x3850054A
+;* 8
+.fill 1, 0x2A38
+
+stack:
+.fill 256, 0
+
+;needed for jumps
+;assuming that no more than 42 instr are used
+instrtable:
+.fill 42, 0
+
+prog_eof:
+.ifill pop r0
+.ifill ret+
+
+prog_mul:
+.ifill pop r6
+.ifill pop r7
+.ifill ldis r8, 0;0xed400004
+.ifill mov r0, r7;0xe1038000
+.ifill andx r0, 1;0xe2800008
+.ifill adddnz r8, r8, r6;0x00443001
+.ifill subinz r7, r7, 1;0x01bb8008
+.ifill addizs r7, r7, 0;0x113b8000
+;loop:
+.ifill adddnz r8, r8, r6;0x00443001
+.ifill adddnz r8, r8, r6;0x00443001
+.ifill subi r7, r7, 2;0xe1bb8010
+.fill 0x0b7ffe83;brnz+ loop
+.ifill push r8
+
+prog_consts:
+.fill 0xed300004;ldis r6, CONST
+.ifill push r6
+
+prog_add:
+.ifill pop r6
+.ifill pop r7
+.ifill add r7, r7, r6;0xe03bb000
+.ifill push r7
+
+prog_sub:
+.ifill pop r6
+.ifill pop r7
+.ifill sub r7, r7, r6;0xe0bbb000
+.ifill push r7
+
+prog_lessthan:
+.ifill pop r6
+.ifill pop r7
+.ifill cmp r7, r6;0xec3b0000
+.ifill pushlt r14
+.ifill pushge r15
+
+prog_dup:
+.ifill fetch r6
+.ifill push r6
+
+prog_jmp:
+.ifill pop r6
+.ifill cmpi r6,0;0xecb00000
+;static calced
+.fill 1, 0x1b000103;breq- vm_next
+.fill 1, 0xeb000003;br+ CONST
+
+prog_imm:
+.fill 1, 0xed400000;ldil r6, CONST
+.fill 1, 0xed400002;ldih r6, CONST
+.ifill push r6
+
+prog_pop:
+.ifill disc r6
+
+prog_xch:
+.ifill pop r6
+.ifill pop r7
+.ifill push r6
+.ifill push r7
+
+prog_not:
+.ifill pop r6
+.ifill not r6;0xe4b7fffa
+.ifill push r6
+
+.text
+ .define UART_BASE, 0x2000
+ .define UART_STATUS, 0x0
+ .define UART_RECV, 0xc
+ .define UART_TRANS, 0x8
+
+ .define UART_TRANS_EMPTY, 0x1
+ .define UART_RECV_NEW, 0x2
+
+ .define PBASE, 0x2030
+ .define PADDR, 0x4
+ .define PDATA, 0x8
+
+
+main:
+
+ ldi r10, UART_BASE@lo
+ ldih r10, UART_BASE@hi
+;recv byte
+u_recv_byte:
+ ldw r3, UART_STATUS(r10)
+ andx r3, UART_RECV_NEW
+ brzs+ u_recv_byte; branch if zero
+ xor r0, r0, r0
+ ldw r0, UART_RECV(r10)
+;recv byte
+
+ ;set address of input
+ ldil r1, inputdata@lo
+ ldih r1, inputdata@hi
+
+ ;set address of program start
+ ldil r2, prog_start@lo
+ ldih r2, prog_start@hi
+
+ ;set address to instruction table
+ ldil r3, instrtable@lo
+ ldih r3, instrtable@hi
+
+ ;set address to defer table
+ ldil r9, defertable@lo
+ ldih r9, defertable@hi
+
+ ldil r13, PBASE@lo
+ ldih r13, PBASE@hi
+
+ ;set programmer address
+ stw r2, PADDR(r13)
+
+
+ ;call jit compiler
+ call+ jit
+
+ ;set address to stack
+ ;ldil r3, stack@lo
+ ;ldih r3, stack@hi
+
+ ;make r15 a 0-register
+ ldis r15, 0
+ ;make r14 a 8-bit -1-register
+ ldis r14, 0xFF
+
+ ;call jit'ed prog
+ call+ prog_start
+
+;send result
+u_send_byte:
+ ldi r10, UART_BASE@lo
+ ldih r10, UART_BASE@hi
+ ldw r9, UART_STATUS(r10)
+ andx r9, UART_TRANS_EMPTY
+ brnz+ u_send_byte ; branch if not zero
+ stb r0, UART_TRANS(r10)
+;send result
+
+ br+ main
+
+;first version only supports backward jumps
+jit:
+ ;r1 ... address to input, every byte is a new input
+ ; includes pc implicitly
+ ;r2 ... address to program start
+ ;r3 ... address of instruction table
+ ;r4 ... gets loaded with instr. prog. addr.
+ ;r5 ... input
+ ;r9 ... address to actual entry in defer table
+ ;r10... address to defer table
+ ;r13 .. programmer address
+
+ ;load address of program
+ ldil r14, prog_mul@lo
+ ldih r14, prog_mul@hi
+
+ ldil r15, prog_consts@lo
+ ldih r15, prog_consts@hi
+
+ ;backup defer table address
+ mov r10, r9
+ ;decrement address to input by 1
+ subi r1, r1, 1
+
+vm_default:
+vm_loop:
+ ;increment input address
+ addi r1, r1, 1
+
+ ;store address of next instruction in table
+ stw r2, 0(r3)
+ ;increment instr. table
+ addi r3, r3, 4
+
+ ;load input
+ ldb r5, 0(r1)
+ ;we need to multiply input by 4 to get correct address offset
+ lls r0, r5, 2
+ ;calc position in jumptable
+ ldw r0, jumptable(r0)
+ ;jump to instr
+ brr r0
+
+vm_eof:
+ ;load address of program
+ ldil r4, prog_eof@lo
+ ldih r4, prog_eof@hi
+ ;program instruction (2)
+ ldw r0, 0(r4)
+ stw r0, PDATA(r13)
+ ldw r0, 4(r4)
+ stw r0, PDATA(r13)
+
+ ;end of program
+ ;now it is time to clear up the defer table
+
+ ldil r7, prog_jmp@lo
+ ldih r7, prog_jmp@hi
+ ;load branch template
+ ldw r7, 12(r7)
+
+ ;if actual and base are equal, no entry
+ cmp r9, r10
+ ;return
+ reteq-
+
+vm_defer:
+ ;load pointer to where to jump to
+ ldw r6, 0(r10)
+ ;load where to jump to
+ ldw r6, 0(r6)
+ ;load where to save from defer table
+ stw r8, 4(r10)
+
+ ;generate branch
+ sub r11, r6, r8
+ lrs r11, r11, 2
+ ;set the upper 16 bit 0
+ andx r11, 0xFFFF
+ ;shift to the position of imm in br
+ lls r11, r11, 7
+ or r6, r7, r11
+
+ stw r8, PADDR(r13)
+ stw r6, PDATA(r13)
+
+ addi r10, r10, 8
+ cmp r10, r9
+ reteq+
+ brnq- vm_defer
+
+;case *
+;42
+vm_mul:
+ ;program instruction (14)
+ ldw r0, 0(r14)
+ PROGINSTR
+ ldw r0, 4(r14)
+ PROGINSTR
+ ldw r0, 8(r14)
+ PROGINSTR
+ ldw r0, 12(r14)
+ PROGINSTR
+ ldw r0, 16(r14)
+ PROGINSTR
+ ldw r0, 20(r14)
+ PROGINSTR
+ ldw r0, 24(r14)
+ PROGINSTR
+ ldw r0, 28(r14)
+ PROGINSTR
+ ldw r0, 32(r14)
+ PROGINSTR
+ ldw r0, 36(r14)
+ PROGINSTR
+ ldw r0, 40(r14)
+ PROGINSTR
+ ldw r0, 44(r14)
+ PROGINSTR
+ ldw r0, 48(r14)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 52
+
+ br+ vm_loop
+
+;case +
+;43
+vm_add:
+ ;load address of program
+ ldil r4, prog_add@lo
+ ldih r4, prog_add@hi
+
+ ;program instruction (5)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+ ldw r0, 8(r4)
+ PROGINSTR
+ ldw r0, 12(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 16
+
+ br+ vm_loop
+
+;case -
+;45
+vm_sub:
+ ;load address of program
+ ldil r4, prog_sub@lo
+ ldih r4, prog_sub@hi
+
+ ;program instruction (5)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+ ldw r0, 8(r4)
+ PROGINSTR
+ ldw r0, 12(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 16
+
+ br+ vm_loop
+
+;case 0 1 2 3 4 5 6 7 8 9
+;48-57
+vm_consts:
+ ;program instruction (3)
+ ldw r0, 0(r15)
+ ;the first instr. loads r6 with the number
+ ;thus we shall emulate this
+
+ ;call number
+ subi r6, r5, 48
+ ;shift 3 bits left, as the immediate in ldi has
+ ;an offset of 3
+ lls r6, r6, 3
+ ;now 'add' this to the ldi
+ or r0, r0, r6
+
+ ;store this 'dynamic' instruction
+ PROGINSTR
+ ldw r0, 4(r15)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 8
+
+ br+ vm_loop
+
+;case <
+;60
+vm_lessthan:
+ ;load address of program
+ ldil r4, prog_lessthan@lo
+ ldih r4, prog_lessthan@hi
+
+ ;program instruction (6)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+ ldw r0, 8(r4)
+ PROGINSTR
+ ldw r0, 12(r4)
+ PROGINSTR
+ ldw r0, 16(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 20
+
+ br+ vm_loop
+
+;case D
+;68
+vm_dup:
+ ldil r4, prog_dup@lo
+ ldih r4, prog_dup@hi
+
+ ;program instruction (3)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 8
+
+ br+ vm_loop
+
+;case I
+;73
+vm_imm:
+ ;the following instructions calculate the immediate
+ ;load new high byte
+ ldb r6, 4(r1)
+ ;shift high byte
+ lls r6, r6, 8
+ ;load 2nd byte
+ ldb r7, 3(r1)
+ ;add to high byte
+ add r6, r6, r7
+ ;shift
+ lls r6, r6, 8
+ ;load
+ ldb r7, 2(r1)
+ ;add
+ add r6, r6, r7
+ ;shift
+ lls r6, r6, 8
+ ;load
+ ldb r7, 1(r1)
+ ;add
+ add r6, r6, r7
+
+ ;now we will generate ldih/l which will store this
+ ;immediate into a register
+
+ ;load address of program
+ ldil r4, prog_imm@lo
+ ldih r4, prog_imm@hi
+
+ ;save r6 to r7
+ mov r7, r6
+
+ ;generate 1st instr
+ ldw r0, 0(r4)
+ andx r6, 0xFFFF
+ lls r6, r6, 3
+ or r0, r0, r6
+ PROGINSTR
+
+ ;generate 2nd instr
+ ldw r0, 4(r4)
+ andxh r7, 0xFFFF
+ lrs r7, r7, 13
+ or r0, r0, r7
+ PROGINSTR
+
+ ;now we program the instructions that will save the
+ ;immediate onto the stack and increment the later
+
+ ldw r0, 8(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 12
+
+ ;pc+4
+ addi r1, r1, 4
+ br+ vm_loop
+
+;case J
+;74
+vm_jmp:
+ ;gfreit mi net ...
+ ;gespeicherte instrs sollten input indepentent sein
+ ;jumptable verwenden
+ ;fuer forward jumps muss deferrer table gemacht werden *puke*
+
+ ;load address of program
+ ldil r4, prog_jmp@lo
+ ldih r4, prog_jmp@hi
+
+ ;program instruction (2)
+ ;pop r6
+ ldw r0, 0(r4)
+ PROGINSTR
+
+ ;compare to 0
+ ;cmpi r6,0
+ ldw r0, 4(r4)
+ PROGINSTR
+
+ ;breq+ vm_next
+ ;is statically known
+ ldw r0, 8(r4)
+ PROGINSTR
+
+ ;we add the offset to this instruction
+ addi r8, r2, 12
+
+
+ ;we know calculate the jump destination
+ ;set r6 to 0 (to clear upper bytes)
+ ldis r6, 0
+ ;load pc+1 input
+ ldb r6, 1(r1)
+ ;compare input with neg. max of 8 bit
+ cmpi r6, 0x80
+ brlt- vm_possign
+
+
+
+ ;generate negativ offset
+ ldis r7, 0xFF00
+ ;r6 is now the 'real' negativ number
+ or r6, r6, r7
+ ;todo: testing showed (at least once) we are off by 2 instr.
+ ;addi r6, r6, 2
+ ;multiply by to get the offset
+ lls r6, r6, 2
+ ;generate address in table
+ add r6, r3, r6
+ ;r0 now has the target address
+ ;todo: 0-4?
+ ldw r0, 0(r6)
+ ;we calc the offset
+ sub r8, r0, r8
+ ;we shift 2 bits out, because rel. br takes instr.
+ ;count and not address amount ...
+ lrs r8, r8, 2
+ ;set the upper 16 bit 0
+ andx r8, 0xFFFF
+ ;shift to the position of imm in br
+ lls r8, r8, 7
+ ;load template br
+ ldw r0, 12(r4)
+ or r0, r0, r8
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 16
+
+ br+ vm_loop
+
+
+vm_possign:
+ ;we know save the address in the instrtable where the addr to jump to stands
+ ;the value doesn't exists at the moment, but it will at evaluation
+
+ ;save position to save the instr into defer table
+ stw r8, 4(r9)
+
+ ;we need one instruction to have the correct offset (?)
+ PROGINSTR
+
+ ;todo: check if -1 is needed
+ ;subi r6, r6, 1
+ ;multiply with 2 to get offset right
+ lls r6, r6, 2
+ ;add to current base
+ add r6, r3, r6
+ ;save the address to defer table
+ stw r6, 0(r9)
+ ;increment defer table address
+ addi r9, r9, 8
+ ;increment address
+ addi r2, r2, 16
+ br+ vm_loop
+
+;case P
+;80
+vm_pop:
+ ;load address of program
+ ldil r4, prog_pop@lo
+ ldih r4, prog_pop@hi
+
+ ;program instruction (1)
+ ldw r0, 0(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 4
+
+ br+ vm_loop
+
+;case X
+;88
+vm_xch:
+ ;load address of program
+ ldil r4, prog_xch@lo
+ ldih r4, prog_xch@hi
+
+ ;program instruction (4)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+ ldw r0, 8(r4)
+ PROGINSTR
+ ldw r0, 12(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 16
+
+ br+ vm_loop
+
+;case ~
+;126
+vm_not:
+ ;load address of program
+ ldil r4, prog_not@lo
+ ldih r4, prog_not@hi
+
+ ;program instruction (3)
+ ldw r0, 0(r4)
+ PROGINSTR
+ ldw r0, 4(r4)
+ PROGINSTR
+ ldw r0, 8(r4)
+ PROGINSTR
+
+ ;increment address
+ addi r2, r2, 12
+
+ br+ vm_loop
+
+prog_start:
+
+.data
+jumptable:
+;0
+.fill 1, vm_eof
+.fill 41, vm_default
+;42
+.fill 1, vm_mul
+;43
+.fill 1, vm_add
+;44
+.fill 1, vm_default
+;45
+.fill 1, vm_sub
+;46-47
+.fill 2, vm_default
+;48-57
+.fill 10, vm_consts
+;58-59
+.fill 2, vm_default
+;60
+.fill 1, vm_lessthan
+;61-67
+.fill 7, vm_default
+;68
+.fill 1, vm_dup
+;69-72
+.fill 4, vm_default
+;73
+.fill 1, vm_imm
+;74
+.fill 1, vm_jmp
+;75-79
+.fill 5, vm_default
+;80
+.fill 1, vm_pop
+;81-87
+.fill 7, vm_default
+;88
+.fill 1, vm_xch
+;89-125
+.fill 37, vm_default
+;126
+.fill 1, vm_not
+;127-255
+.fill 129, vm_default
+
+;we assume not more than 3 entries
+defertable:
+.fill 6, 0