.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 .text main: ;set address of input ldil r1, inputdata@lo ldih r1, inputdata@hi call+ vm br+ main vm: ;r0 ... lut address (can be overwritten) ;r1 ... address to input, every byte is a new input ; includes pc implicitly ;r3 ... effective stack address ;r5 ... input ;decrement address to input by 1 subi r1, r1, 1 ;load base address of stack ldil r3, stack@lo ldih r3, stack@hi vm_default: vm_loop: ;increment input address addi r1, r1, 1 ;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 stack[sp-1] ;ldw r0, 0-4(r3); pop r0 ret+; ;case * ;42 vm_mul: ;decrement sp ;subi r3, r3, 4 ;load sp ;ldw r6, 0(r3) pop r6 ;load sp-1 ;ldw r7, 0-4(r3) pop r7 ;return init ldis r8, 0 ;save of sp-1 mov r0, r7 ;check if sp-1 is even or odd andx r0, 1 ;add sp to result adddnz r8, r8, r6 ;if odd decrement sp-1 subinz r7, r7, 1 ;just to get zero flag unset addizs r7, r7, 0 loop: ;if last was not zero ;add to sp-1 to result adddnz r8, r8, r6 adddnz r8, r8, r6 ;decrement sp-1 by 2 subi r7, r7, 2 ;jump if not zero brnz+ loop ;save result ;stw r8, 0-4(r3) push r8 br+ vm_loop ;case + ;43 vm_add: ;decrement sp ;subi r3, r3, 4 ;load sp ;ldw r6, 0(r3) pop r6 ;load sp-1 ;ldw r7, 0-4(r3) pop r7 ;sp-1 = sp-1 + sp add r7, r7, r6 ;store sp-1 ;stw r7, 0-4(r3) push r7 br+ vm_loop ;case - ;45 vm_sub: ;decrement sp ;subi r3, r3, 4 ;load sp ;ldw r6, 0(r3) pop r6 ;load sp-1 ;ldw r7, 0-4(r3) pop r7 ;sp-1 = sp-1 - sp sub r7, r7, r6 ;store sp-1 ;stw r7, 0-4(r3) push r7 br+ vm_loop ;case 0 1 2 3 4 5 6 7 8 9 ;48-57 vm_consts: ;input minus offset subi r6, r5, 48 ;store onto stack ;stw r6, 0(r3) push r6 ;increment stack addr ;addi r3, r3, 4 br+ vm_loop ;case < ;60 vm_lessthan: ;decrement sp ;subi r3, r3, 4 ;load sp ;ldw r6, 0(r3) pop r6 ;load sp-1 ;ldw r7, 0-4(r3) pop r7 ;load r8 with 0 ldis r8, 0 ;compare sp-1 with sp cmp r7, r6 ;set r8 to -1 if less than ldislt r8, 0xFF ;store r8 to sp-1 ;stw r8, 0-4(r3) push r8 br+ vm_loop ;case D ;68 vm_dup: ;load sp-1 ;ldw r6, 0-4(r3) fetch r6 ;store to sp ;stw r6, 0(r3) push r6 ;increment stack addr ;addi r3, r3, 4 br+ vm_loop ;case I ;73 vm_imm: ;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 ;store result to stack ;stw r6, 0(r3) push r6 ;pc+4 addi r1, r1, 4 ;increment sp ;addi r3, r3, 4 br+ vm_loop ;case J ;74 vm_jmp: ;decrement sp ;subi r3, r3, 4 ;load sp ;ldw r6, 0(r3) pop r6 ;compare to 0 cmpi r6,0 ;increment pc if == 0 addideq r1, r1, 1 breq+ vm_loop ;if != 0 ;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 ldis r7, 0xFF00 add r6, r6, r7 vm_possign: ;pc += data add r1, r1, r6 br+ vm_loop ;case P ;80 vm_pop: ;decrement stack addr ;subi r3, r3, 4 disc r0 br+ vm_loop ;case X ;88 vm_xch: ;load sp-1 ;ldw r6, 0-4(r3) pop r6 ;load sp-2 ;ldw r7, 0-8(r3) pop r7 ;store sp-1 to sp-2 ;stw r6, 0-8(r3) push r6 ;store sp-2 to sp-1 ;stw r7, 0-4(r3) push r7 br+ vm_loop ;case ~ ;126 vm_not: ;ldw r6, 0-4(r3) pop r6 not r6 ;stw r6, 0-4(r3) push r6 br+ vm_loop .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