начал сегодня писать FVM для AVR+32K XRAM, обнаружил что интерпретатор байт-кода
идеально ложится на систему команд и архитектуру (три 16-битных индексных регистра XYZ) AVR
подскажите, как сделать запуск "микрокода" команд ВМ через jump table ? сейчас опкоды ВМ тупо перебираются парами команд cpi/breq, для запуска последней команды понадобится 256 машинных циклов:
Код:
; Virtual FORTH Machine for AVR ATmega8515 + 32K EXT SRAM
; (c) Dmitry Ponyatov <forth@km.ru>, public domain
; ATTENTION: entry point must be @ 0x8000 (high 32K)
.include "m8515def.inc"
.org 0x00
rjmp RESET
.org 0x20
.def tmp = r20
.def cellh = r21
.def celll = r22
.def op = r21 ; opcode
RESET:
; enable watchdog
ldi tmp,0b00001111
out WDTCR,tmp
; enable external RAM control
; reset VM pointers
ldi XH,0x80 ; instruction pointer
ldi XL,0x00
ldi YH,0xE0 ; return stack
ldi YL,0x00
ldi ZH,0xF0 ; data stack
ldi ZL,0x00
; load opcode
NEXT: ; FORTH interpreter NEXT point
; load command opcode
ld op,X+
; FVM standard commands
cpi op,0x00
breq vm_NOP
cpi op,0x01
breq vm_JMP
cpi op,0x03
breq vm_CALL
cpi op,0x04
breq vm_RET
; user commands
cpi op,0xF0
breq vm_F0
cpi op,0xF1
breq vm_F1
cpi op,0xF2
breq vm_F2
cpi op,0xF3
breq vm_F3
cpi op,0xF4
breq vm_F4
cpi op,0xF5
breq vm_F5
cpi op,0xF6
breq vm_F6
cpi op,0xF7
breq vm_F7
cpi op,0xF8
breq vm_F8
cpi op,0xF9
breq vm_F9
cpi op,0xFA
breq vm_FA
cpi op,0xFB
breq vm_FB
cpi op,0xFC
breq vm_FC
cpi op,0xFD
breq vm_FD
cpi op,0xFE
breq vm_FE
cpi op,0xFF
breq vm_FF
ABORT: ; abort on incorrect command or assertion
sleep
rjmp ABORT
; VM commands
vm_NOP: rjmp NEXT
vm_JMP:
ld celll,X+ ; \ move to next command
ld cellh,X+ ; /
mov XH,cellh ; \ move Ip to colabble addr
mov XL,celll ; /
rjmp NEXT
vm_CALL:
ld celll,X+ ; \ move to next command
ld cellh,X+ ; /
st -Y,XL ; \ store next command addr
st -Y,XH ; / to return stack
mov XH,cellh ; \ move Ip to colabble addr
mov XL,celll ; /
rjmp NEXT
vm_RET:
ld XH,Y+
ld XL,Y+
rjmp NEXT
; put your own user defined commands here
vm_F0: rjmp NEXT
vm_F1: rjmp NEXT
vm_F2: rjmp NEXT
vm_F3: rjmp NEXT
vm_F4: rjmp NEXT
vm_F5: rjmp NEXT
vm_F6: rjmp NEXT
vm_F7: rjmp NEXT
vm_F8: rjmp NEXT
vm_F9: rjmp NEXT
vm_FA: rjmp NEXT
vm_FB: rjmp NEXT
vm_FC: rjmp NEXT
vm_FD: rjmp NEXT
vm_FE: rjmp NEXT
vm_FF: ; this command will be executed
; if VM memory will be empty
sleep
rjmp vm_FF