; r12 |
; r13 h/
; r14 ----- New flags register value (VF)
-; r15
+; r15 ----- Saved instruction F field
; r16 l\___ Pointer to V[X]
; r17 h/
; r18
reset:
; ----- Disable interrupts and set stack pointer to top of SRAM
- eor r25, r25
+ clr r25
out SREG, r25
ldi r25, HIGH(RAMEND)
out SPH, r25
; --------------------------------------------------------------
; Main loop
loop:
- ; Check for pin change interrupt and debounce
+ ; Check for pin change interrupt flag and debounce switches
; TODO
; Fetch instruction
- movw ZL, r2
- lpm r4, Z+
+ movw ZL, r2 ; Put bytecode PC into Z
+ lsl ZL ; *2 to get a byte address from a word address
+ rol ZH
+ lpm r4, Z+ ; Load a word and increment
lpm r5, Z+
- movw r2, ZL
+ lsr ZH ; /2 to get a word address from a byte address
+ ror ZL
+ movw r2, ZL ; Save updated bytecode PC
; Decode first operand, always register V[X]
- mov r16, r5
- andi r16, 0x0f
- lsl r16
- lsl r16
- ldi r17, 0x00
+ mov r24, r5 ; Extract X field from instruction
+ andi r24, 0x0f
+ lsl r24 ; *4 to get an offset from an index
+ lsl r24
+ clr r25 ; Add offset to base address of registers
ldi ZL, LOW(interp_regs)
ldi ZH, HIGH(interp_regs)
- movw r16, ZL
- ld r6, Z+
- ld r7, Z+
- ld r8, Z+
- ld r9, Z+
-
- ; Decode second operand based on instruction type
- mov r10, r5
- asr r10
- asr r10
- asr r10
- asr r10
- eor r0, r0
+ add ZL, r24
+ adc ZH, r25
+ movw r16, ZL ; Save the reg addr for use as destination later
+ ldd r6, Z+0 ; Load operand value
+ ldd r7, Z+1
+ ldd r8, Z+2
+ ldd r9, Z+3
+
+ ; Decode second operand based on instruction F field
+ mov r24, r5 ; Extract F field from instruction
+ lsr r24
+ lsr r24
+ lsr r24
+ lsr r24
+ clr r25 ; Add base address of operand-dispatch jumptable
ldi ZL, LOW(operand_jumptable)
ldi ZH, HIGH(operand_jumptable)
- add ZL, r10
- adc ZH, r0
- ijmp
+ add ZL, r24
+ adc ZH, r25
+ mov r15, r24 ; Save the F field for decoding instruction later
+ ijmp ; Jump to whatever code decodes the other operand
_decode_done:
- ; Dispatch based on instruction type
+ ; Dispatch based on instruction F field
+ mov r24, r15 ; Recover saved F field from instruction
+ clr r25 ; Add base address of instruction-dispatch jumptable
ldi ZL, LOW(f_dispatch_jumptable)
ldi ZH, HIGH(f_dispatch_jumptable)
- eor r0, r0
- add ZL, r10
- adc ZH, r0
+ add ZL, r24
+ adc ZH, r25
+ ijmp ; Jump to whatever code runs this type of instruction
_dispatch_done_writeback_flags:
+ ldi r24, 0xc3 ; Index of the VF register (0xf * 4)
+ clr r25 ; Add offset to base address of registers
ldi ZL, LOW(interp_regs)
ldi ZH, HIGH(interp_regs)
- ldi r25, 0x0e*4
- add ZL, r25
- eor r0, r0
- adc ZH, r0
- st Z, r14
+ add ZL, r24
+ adc ZH, r25
+ st Z, r14 ; Store the flag byte generated by the instruction
_dispatch_done_writeback_reg:
- movw ZL, r16
- st Z+, r6
- st Z+, r7
- st Z+, r8
- st Z+, r9
+ movw ZL, r16 ; Recover the pointer to V[X]
+ std Z+0, r6 ; Save the instruction result to the register
+ std Z+1, r7
+ std Z+2, r8
+ std Z+3, r9
_dispatch_done:
rjmp loop
.dw operand_none
.dw operand_none
+
+; ----- V[Y]
operand_VY:
+ mov r24, r4
+ andi r24, 0xf0
+ lsr r24
+ lsr r24
+ clr r25
+ ldi ZL, LOW(interp_regs)
+ ldi ZH, HIGH(interp_regs)
+ add ZL, r24
+ adc ZH, r25
+ ldd r10, Z+0
+ ldd r11, Z+1
+ ldd r12, Z+2
+ ldd r13, Z+3
+
rjmp _decode_done
+
+; ----- 32-bit immediate following instruction
operand_imm32:
+ movw ZL, r2 ; Put bytecode PC into Z
+ lsl ZL ; *2 to get a byte address from a word address
+ rol ZH
+ lpm r10, Z+ ; Load four bytes and increment
+ lpm r11, Z+
+ lpm r14, Z+
+ lpm r13, Z+
+ lsr ZH ; /2 to get a word address from a byte address
+ ror ZL
+ movw r2, ZL ; Save updated bytecode PC
+
rjmp _decode_done
+
+; ----- 4-bit zero-extended immediate within instruction
operand_Y:
+ mov r10, r4
+ lsr r10
+ lsr r10
+ lsr r10
+ lsr r10
+ clr r11
+ clr r12
+ clr r13
+
rjmp _decode_done
+
+; ----- V[Y] + 4-bit zero-extended immediate within instruction
operand_VY_N:
- rjmp _decode_done
+ ; Load V[Y]
+ mov r24, r4
+ andi r24, 0xf0
+ lsr r24
+ lsr r24
+ clr r25
+ ldi ZL, LOW(interp_regs)
+ ldi ZH, HIGH(interp_regs)
+ add ZL, r24
+ adc ZH, r25
+ ldd r10, Z+0
+ ldd r11, Z+1
+ ldd r12, Z+2
+ ldd r13, Z+3
+
+ ; Add N
+ mov r24, r4
+ andi r24, 0x0f
+ clr r25
+ add r10, r24
+ adc r11, r25
+ adc r12, r25
+ adc r13, r25
-operand_ssNN:
rjmp _decode_done
+
+; ----- Zero-extended 12-bit immediate within instruction
operand_0NNN:
+ movw r10, r4
+ ldi r25, 0x0f
+ and r11, r25
+ clr r12
+ clr r13
rjmp _decode_done
+
+; ----- PC + sign-extended 8-bit immediate within instruction
operand_PC_ssNN:
+ ; Sign-extend 8-bit immediate
+ mov r10, r4
+ clr r11
+ clr r12
+ clr r13
+ sbrs r10, 7
+ rjmp _sext_done_PCssNN
+ com r11
+ com r12
+ com r13
+_sext_done_PCssNN:
+
+ ; Add PC
+ clr r25
+ add r10, r2
+ adc r11, r3
+ adc r12, r25
+ adc r13, r25
+
rjmp _decode_done
+
+; ----- PC + sign-extended 12-bit immediate within instruction
operand_PC_sNNN:
+ ; Sign-extend 12-bit immediate
+ movw r10, r4
+ ldi r25, 0x0f
+ and r11, r25
+ clr r12
+ clr r13
+ sbrs r11, 3
+ rjmp _sext_done_PCsNNN
+ ldi r25, 0xf0
+ or r11, r25
+ com r12
+ com r13
+_sext_done_PCsNNN:
+
+ ; Add PC
+ clr r25
+ add r10, r2
+ adc r11, r3
+ adc r12, r25
+ adc r13, r25
+
rjmp _decode_done
+
operand_none:
rjmp _decode_done
dispatch_alu:
+ mov r24, r4
+ andi r24, 0x0f
+ clr r25
ldi ZL, LOW(alu_dispatch_jumptable)
ldi ZH, HIGH(alu_dispatch_jumptable)
- mov r25, r4
- andi r25, 0x0f
- eor r1, r1
- add ZL, r0
- adc ZH, r1
+ add ZL, r24
+ adc ZH, r25
ijmp
dispatch_imm4:
+ mov r24, r4
+ andi r24, 0x0f
+ clr r25
ldi ZL, LOW(imm4_dispatch_jumptable)
ldi ZH, HIGH(imm4_dispatch_jumptable)
- mov r25, r4
- andi r25, 0x0f
- eor r1, r1
- add ZL, r0
- adc ZH, r1
+ add ZL, r24
+ adc ZH, r25
ijmp
dispatch_branch:
+ mov r24, r5
+ andi r24, 0x0f
+ clr r25
ldi ZL, LOW(branch_dispatch_jumptable)
ldi ZH, HIGH(branch_dispatch_jumptable)
- mov r25, r5
- andi r25, 0x0f
- eor r1, r1
- add ZL, r0
- adc ZH, r1
+ add ZL, r24
+ adc ZH, r25
ijmp
+
exec_nop:
exec_add:
exec_sub: