From 0a3f69d53c4d12054c10001a4b97cdf302972c15 Mon Sep 17 00:00:00 2001 From: Martin Perner Date: Wed, 12 Jan 2011 18:39:29 +0100 Subject: [PATCH] vm: made deepjit downloadable? --- progs/deepjit.s | 689 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 689 insertions(+) create mode 100644 progs/deepjit.s diff --git a/progs/deepjit.s b/progs/deepjit.s new file mode 100644 index 0000000..b73b238 --- /dev/null +++ b/progs/deepjit.s @@ -0,0 +1,689 @@ +#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 -- 2.25.1