mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
more vm opcodes
This commit is contained in:
parent
bcc1a6b91f
commit
6696887f0e
@ -40,10 +40,23 @@ class Opcode(enum.IntEnum):
|
|||||||
CMP_GTE = 105
|
CMP_GTE = 105
|
||||||
CALL = 200
|
CALL = 200
|
||||||
RETURN = 201
|
RETURN = 201
|
||||||
JUMP = 202
|
SYSCALL = 202
|
||||||
JUMP_IF_TRUE = 203
|
JUMP = 203
|
||||||
JUMP_IF_FALSE = 204
|
JUMP_IF_TRUE = 204
|
||||||
SYSCALL = 205
|
JUMP_IF_FALSE = 205
|
||||||
|
JUMP_IF_STATUS_ZERO = 206
|
||||||
|
JUMP_IF_STATUS_NE = 207
|
||||||
|
JUMP_IF_STATUS_EQ = 208
|
||||||
|
JUMP_IF_STATUS_CC = 209
|
||||||
|
JUMP_IF_STATUS_CS = 210
|
||||||
|
JUMP_IF_STATUS_VC = 211
|
||||||
|
JUMP_IF_STATUS_VS = 212
|
||||||
|
JUMP_IF_STATUS_GE = 213
|
||||||
|
JUMP_IF_STATUS_LE = 214
|
||||||
|
JUMP_IF_STATUS_GT = 215
|
||||||
|
JUMP_IF_STATUS_LT = 216
|
||||||
|
JUMP_IF_STATUS_POS = 217
|
||||||
|
JUMP_IF_STATUS_NEG = 218
|
||||||
|
|
||||||
|
|
||||||
class Value:
|
class Value:
|
||||||
|
71
tinyvm/vm.py
71
tinyvm/vm.py
@ -52,7 +52,7 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
|||||||
# various arithmetic operations, logical operations, boolean test and comparison operations
|
# various arithmetic operations, logical operations, boolean test and comparison operations
|
||||||
# jump label
|
# jump label
|
||||||
# jump_if_true label, jump_if_false label
|
# jump_if_true label, jump_if_false label
|
||||||
# @todo jump_if_status_XX label special system dependent status register conditional check such as carry bit or overflow bit)
|
# jump_if_status_XX label special system dependent status register conditional check such as carry bit or overflow bit)
|
||||||
# return (return values on stack)
|
# return (return values on stack)
|
||||||
# syscall function (special system dependent implementation)
|
# syscall function (special system dependent implementation)
|
||||||
# call function (arguments are on stack)
|
# call function (arguments are on stack)
|
||||||
@ -74,7 +74,7 @@ import tkinter
|
|||||||
import tkinter.font
|
import tkinter.font
|
||||||
from typing import Dict, List, Tuple, Union, no_type_check
|
from typing import Dict, List, Tuple, Union, no_type_check
|
||||||
from .program import Instruction, Variable, Block, Program, Opcode, Value
|
from .program import Instruction, Variable, Block, Program, Opcode, Value
|
||||||
from .core import Memory, DataType, TerminateExecution
|
from .core import Memory, DataType, TerminateExecution, ExecutionError
|
||||||
|
|
||||||
|
|
||||||
class CallFrameMarker:
|
class CallFrameMarker:
|
||||||
@ -167,15 +167,9 @@ class VM:
|
|||||||
charin_address = 0xd001
|
charin_address = 0xd001
|
||||||
|
|
||||||
def __init__(self, program: Program, timerprogram: Program=None) -> None:
|
def __init__(self, program: Program, timerprogram: Program=None) -> None:
|
||||||
opcode_names = [oc.name for oc in Opcode]
|
for opcode in Opcode:
|
||||||
timerprogram = timerprogram or Program([])
|
if opcode not in self.dispatch_table:
|
||||||
for ocname in opcode_names:
|
raise NotImplementedError("missing opcode dispatch for " + opcode.name)
|
||||||
if not hasattr(self, "opcode_" + ocname):
|
|
||||||
raise NotImplementedError("missing opcode method for " + ocname)
|
|
||||||
for method in dir(self):
|
|
||||||
if method.startswith("opcode_"):
|
|
||||||
if not method[7:] in opcode_names:
|
|
||||||
raise RuntimeError("opcode method for undefined opcode " + method)
|
|
||||||
for oc in Opcode:
|
for oc in Opcode:
|
||||||
if oc not in self.dispatch_table:
|
if oc not in self.dispatch_table:
|
||||||
raise NotImplementedError("no dispatch entry in table for " + oc.name)
|
raise NotImplementedError("no dispatch entry in table for " + oc.name)
|
||||||
@ -186,7 +180,7 @@ class VM:
|
|||||||
self.memory.mark_readonly(start, end)
|
self.memory.mark_readonly(start, end)
|
||||||
self.main_stack = Stack()
|
self.main_stack = Stack()
|
||||||
self.timer_stack = Stack()
|
self.timer_stack = Stack()
|
||||||
self.main_program, self.timer_program, self.variables, self.labels = self.flatten_programs(program, timerprogram)
|
self.main_program, self.timer_program, self.variables, self.labels = self.flatten_programs(program, timerprogram or Program([]))
|
||||||
self.connect_instruction_pointers(self.main_program)
|
self.connect_instruction_pointers(self.main_program)
|
||||||
self.connect_instruction_pointers(self.timer_program)
|
self.connect_instruction_pointers(self.timer_program)
|
||||||
self.program = self.main_program
|
self.program = self.main_program
|
||||||
@ -516,23 +510,6 @@ class VM:
|
|||||||
self.pc = callframe.returninstruction
|
self.pc = callframe.returninstruction
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def opcode_JUMP(self, instruction: Instruction) -> bool:
|
|
||||||
return True # jump simply points to the next instruction elsewhere
|
|
||||||
|
|
||||||
def opcode_JUMP_IF_TRUE(self, instruction: Instruction) -> bool:
|
|
||||||
result = self.stack.pop()
|
|
||||||
if result:
|
|
||||||
self.pc = self.pc.alt_next # alternative next instruction
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def opcode_JUMP_IF_FALSE(self, instruction: Instruction) -> bool:
|
|
||||||
result = self.stack.pop()
|
|
||||||
if result:
|
|
||||||
return True
|
|
||||||
self.pc = self.pc.alt_next # alternative next instruction
|
|
||||||
return False
|
|
||||||
|
|
||||||
def opcode_SYSCALL(self, instruction: Instruction) -> bool:
|
def opcode_SYSCALL(self, instruction: Instruction) -> bool:
|
||||||
syscall = instruction.args[0]
|
syscall = instruction.args[0]
|
||||||
assert isinstance(syscall, str)
|
assert isinstance(syscall, str)
|
||||||
@ -542,6 +519,27 @@ class VM:
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError("no syscall method for " + syscall)
|
raise RuntimeError("no syscall method for " + syscall)
|
||||||
|
|
||||||
|
def opcode_JUMP(self, instruction: Instruction) -> bool:
|
||||||
|
return True # jump simply points to the next instruction elsewhere
|
||||||
|
|
||||||
|
def opcode_JUMP_IF_TRUE(self, instruction: Instruction) -> bool:
|
||||||
|
result = self.stack.pop()
|
||||||
|
assert isinstance(result, Value)
|
||||||
|
if result.value:
|
||||||
|
self.pc = self.pc.alt_next # alternative next instruction
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def opcode_JUMP_IF_FALSE(self, instruction: Instruction) -> bool:
|
||||||
|
result = self.stack.pop()
|
||||||
|
if result.value: # type: ignore
|
||||||
|
return True
|
||||||
|
self.pc = self.pc.alt_next # alternative next instruction
|
||||||
|
return False
|
||||||
|
|
||||||
|
def opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG(self, instruction: Instruction) -> bool:
|
||||||
|
raise ExecutionError("unsupported conditional jump", instruction) # @todo implement hardware specific status register flags
|
||||||
|
|
||||||
dispatch_table = {
|
dispatch_table = {
|
||||||
Opcode.TERMINATE: opcode_TERMINATE,
|
Opcode.TERMINATE: opcode_TERMINATE,
|
||||||
Opcode.NOP: opcode_NOP,
|
Opcode.NOP: opcode_NOP,
|
||||||
@ -570,10 +568,23 @@ class VM:
|
|||||||
Opcode.CMP_GTE: opcode_CMP_GTE,
|
Opcode.CMP_GTE: opcode_CMP_GTE,
|
||||||
Opcode.CALL: opcode_CALL,
|
Opcode.CALL: opcode_CALL,
|
||||||
Opcode.RETURN: opcode_RETURN,
|
Opcode.RETURN: opcode_RETURN,
|
||||||
|
Opcode.SYSCALL: opcode_SYSCALL,
|
||||||
Opcode.JUMP: opcode_JUMP,
|
Opcode.JUMP: opcode_JUMP,
|
||||||
Opcode.JUMP_IF_TRUE: opcode_JUMP_IF_TRUE,
|
Opcode.JUMP_IF_TRUE: opcode_JUMP_IF_TRUE,
|
||||||
Opcode.JUMP_IF_FALSE: opcode_JUMP_IF_FALSE,
|
Opcode.JUMP_IF_FALSE: opcode_JUMP_IF_FALSE,
|
||||||
Opcode.SYSCALL: opcode_SYSCALL,
|
Opcode.JUMP_IF_STATUS_ZERO: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_NE: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_EQ: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_CC: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_CS: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_VC: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_VS: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_GE: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_LE: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_GT: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_LT: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_POS: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
|
Opcode.JUMP_IF_STATUS_NEG: opcode_JUMP_IF_STATUS_UNSUPPORTED_FLAG,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user