Browse files

cleanup and improve maintainability

reorganised and cleaned up a lot of code, notably moved opcode
associations to a seperate file, and had both machine and asm use
that file to encode/decode opcodes.
  • Loading branch information...
1 parent 9487303 commit e03dde2567cad64d955645b00b03a5e3e8b4a278 @Textmode committed May 15, 2011
Showing with 713 additions and 476 deletions.
  1. +76 −80 asm.lua
  2. +534 −396 machine.lua
  3. +77 −0 opcodes.lua
  4. +26 −0 util.lua
View
156 asm.lua
@@ -2,11 +2,14 @@ local _M = {_NAME="asm", number=0}
local _MT = {__index=_M}
+local opcodes = require "opcodes"
+local op = opcodes.map
+
local symbols, len -- needed for parsing
-local regnum = {PRM=0x0, A =0x1, B=0x2, C=0x3, D=0x4, ACC=0x5, RET=0x6,
- FLG=0xc, SIG=0xd, SEG=0xe, IP =0xf}
-local regs = {'A', 'B', 'C', 'D', 'ACC', 'RET', 'FLG', 'SIG', 'SEG', 'IP'}
+local regnum = {A=0x0, B =0x1, C=0x2, D=0x3, ACC=0x4, RET=0x5,
+ SS=0xa, SP=0xb, FLG=0xc, SIG=0xd, SEG=0xe, IP =0xf}
+local regs = {'A', 'B', 'C', 'D', 'ACC', 'RET', 'SS', 'SP', 'FLG', 'SIG', 'SEG', 'IP'}
-- takes two strings indicating registers, and encodes them into a
-- single free-register byte (taken by some opcodes)
@@ -50,24 +53,21 @@ local function parm(p)
if p == 'null' then return 'symbol', abs, 'null' end -- null is always availible, and never set
- for i=1,#regs do
- form = regs[i] == p and 'register' or form
+ for i=1,#regs do form = regs[i] == p and 'register' or form
end
if form ~= 'register' then
value = parsenum(p)
form = 'literal'
-
+
if value == nil then
value = symbols[p]
- if value then
+ if value then
return form, abs, value
else
form = 'symbol'
value = p
end
-
-
end
end
@@ -92,7 +92,7 @@ local encoders = {
-- NOP is the do-nothing instruction. it has only one form.
if not (a or b or c) then
return false, "NOP must be properly qualified: 'NOP'" end
- return string.char(0x00)
+ return string.char(op.NOP)
end;
MOV = function(a, b, c)
-- MOV is the move data instruction.
@@ -108,9 +108,9 @@ local encoders = {
if af == 'register' and bf == 'register' then -- free-register form
if aa == true and ba == true then -- pure register form
- return string.char(0x0f, reg_encode(av, bv))
+ return string.char(op.MOV_1dR_2dR, reg_encode(av, bv))
elseif aa == false and ba == false then --pure addressed register form
- return string.char(0x02, reg_encode(av, bv))
+ return string.char(op.MOV_1iR_2iR, reg_encode(av, bv))
end
end
@@ -120,17 +120,17 @@ local encoders = {
if (af=='literal' or af=='symbol') and bf=='register' then
if aa == true and ba == true then
if bv == "A" then
- return string.char(0x05, (af=='literal' and tonumber(av)) or 0), af=='symbol'
+ return string.char(op.MOV_1dN_2dA, (af=='literal' and tonumber(av)) or 0), af=='symbol'
elseif bv == "B" then
- return string.char(0x21, (af=='literal' and tonumber(av)) or 0), af=='symbol'
+ return string.char(op.MOV_1dN_2dB, (af=='literal' and tonumber(av)) or 0), af=='symbol'
else
return false, "No encodings for mixed-mode moves not involving registers A or B"
end
elseif aa == false and ba == true then -- mixed get form
if bv == "A" then
- return string.char(0x04, (af=='literal' and tonumber(av)) or 0), af=='symbol'
+ return string.char(op.MOV_1iN_2dA, (af=='literal' and tonumber(av)) or 0), af=='symbol'
elseif bv == "B" then
- return string.char(0x22, (af=='literal' and tonumber(av)) or 0), af=='symbol'
+ return string.char(op.MOV_1iN_2dB, (af=='literal' and tonumber(av)) or 0), af=='symbol'
else
return false, "No encodings for mixed-mode moves not involving registers A or B"
end
@@ -141,9 +141,9 @@ local encoders = {
if af == 'register' and (bf=='literal' or bf=='symbol') then
if aa == true and ba == false then -- mixed push/set form
if av == "A" then
- return string.char(0x03, (bf=='literal' and tonumber(bv)) or 0), bf=='symbol'
+ return string.char(op.MOV_1dA_2dN, (bf=='literal' and tonumber(bv)) or 0), bf=='symbol'
elseif av == "B" then
- return string.char(0x23, (bf=='literal' and tonumber(bv)) or 0), bf=='symbol'
+ return string.char(op.MOV_1dB_2dN, (bf=='literal' and tonumber(bv)) or 0), bf=='symbol'
else
return false, "No encodings for mixed-mode moves not involving registers A or B"
end
@@ -168,7 +168,7 @@ local encoders = {
if not (aa and ba and ca and da) then
return false, "LMOV only works with absolute registers" end
- return string.char(0x24, reg_encode(av, bv), reg_encode(cv, dv))
+ return string.char(op.LMOV_1dR_2dR_3dR_4dR, reg_encode(av, bv), reg_encode(cv, dv))
end;
INC = function(a, b, c)
-- the monopramic increment-by-one instruction., aka ADD 1, R, R
@@ -179,7 +179,7 @@ local encoders = {
if not (af == 'register' and aa and av=='ACC') then
return false, "INC only supports absolute ACC as a destination" end
- return string.char(0x01)
+ return string.char(op.INC_1dACC)
end;
DEC = function(a, b, c)
-- the monopramic decrement-by-one instruction., aka SUB 1, R, R
@@ -190,7 +190,7 @@ local encoders = {
if not (af == 'register' and aa and av=='ACC') then
return false, "DEC only supports absolute ACC as a destination" end
- return string.char(0x1f)
+ return string.char(op.DEC_1dACC)
end;
ADD = function(a, b, c)
-- Addtion instruction, performs basic addition
@@ -209,15 +209,15 @@ local encoders = {
if cv == 'ACC' then
if (av == "A" or av == "B") and (bv == "A" or bv == "B") then
- return string.char(0x09)
+ return string.char(op.ADD_1dA_2dB_3dACC)
else -- free-register form
- return string.char(0x06, reg_encode(av, bv))
+ return string.char(op.ADD_1dR_2dR_3dACC, reg_encode(av, bv))
end
elseif cv=='RET' then
if (av == "A" or av == "B") and (bv == "A" or bv == "B") then
- return string.char(0xa6)
+ return string.char(op.ADD_1dA_2dB_3dRET)
else -- free-register form
- return string.char(0xa4, reg_encode(av, bv))
+ return string.char(op.ADD_1dR_2dR_3dRET, reg_encode(av, bv))
end
end
return false, "unhandled ADD form!"
@@ -237,16 +237,16 @@ local encoders = {
return false, "SUB only supports absolute ACC or RET as a destination" end
if cv == 'ACC' then
- if (av == "A" or av == "B") and (bv == "A" or bv == "B") then
- return string.char(0xa7)
+ if (av == "A") and (bv == "B") then
+ return string.char(op.SUB_1dA_2dB_3dACC)
else -- free-register form
- return string.char(0x06, reg_encode(av, bv))
+ return string.char(op.SUB_1dR_2dR_3dACC, reg_encode(av, bv))
end
elseif cv=='RET' then
- if (av == "A" or av == "B") and (bv == "A" or bv == "B") then
- return string.char(0xa5)
+ if (av == "A") and (bv == "B") then
+ return string.char(op.SUB_1dA_2dB_3dRET)
else -- free-register form
- return string.char(0x20, reg_encode(av, bv))
+ return string.char(op.SUB_1dR_2dR_3dRET, reg_encode(av, bv))
end
end
end;
@@ -265,9 +265,9 @@ local encoders = {
return false, "DIV only supports absolute RET or ACC as a destination" end
if cv == 'RET' then
- return string.char(0xa1, reg_encode(av, bv))
+ return string.char(op.DIV_1dR_2dR_3dRET, reg_encode(av, bv))
else -- cv == ACC
- return string.char(0x1d, reg_encode(av, bv))
+ return string.char(op.DIV_1dR_2dR_3dACC, reg_encode(av, bv))
end
end;
MUL = function(a, b, c)
@@ -285,9 +285,9 @@ local encoders = {
return false, "MUL only supports absolute RET or ACC as a destination." end
if cv == 'RET' then
- return string.char(0x19, reg_encode(av, bv))
+ return string.char(op.MUL_1dR_2dR_3dRET, reg_encode(av, bv))
else -- cv == ACC
- return string.char(0x1e, reg_encode(av, bv))
+ return string.char(op.MUL_1dR_2dR_3dACC, reg_encode(av, bv))
end
end;
MOD = function(a, b, c)
@@ -305,9 +305,9 @@ local encoders = {
return false, "MOD only supports absolute RET or ACC as a destination" end
if cv == 'RET' then
- return string.char(0x1b, reg_encode(av, bv))
+ return string.char(op.MOD_1dR_2dR_3dRET, reg_encode(av, bv))
else -- cv == ACC
- return string.char(0x1c, reg_encode(av, bv))
+ return string.char(op.MOD_1dR_2dR_3dACC, reg_encode(av, bv))
end
end;
SHW = function(a, b, c)
@@ -320,17 +320,17 @@ local encoders = {
return false, "SHW only presently works for absolute registers" end
if av=='A' then
- return string.char(0x0a)
+ return string.char(op.SHW_1dA)
else
- return string.char(0xa1, reg_encode(av))
+ return string.char(op.SHW_1dR, reg_encode(av))
end
end;
HLT = function(a, b, c)
-- halt instruction, tells the machine to halt
if not (not (a or b or c)) then
return false, "HLT must be properly qualified: 'HLT'" end
- return string.char(0xff)
+ return string.char(op.STOP)
end;
SWP = function(a, b, c)
-- swap, exchanges the values of parameters. only defined
@@ -345,9 +345,9 @@ local encoders = {
return false, "SWP only works with absolute parms" end
if (av == "A" or av == "B") and (bv == "A" or bv == "B") then
- return string.char(0x08)
+ return string.char(op.SWP_1dA_2dB)
else -- free-register form
- return string.char(0x07, reg_encode(av, bv))
+ return string.char(op.SWP_1dR_2dR, reg_encode(av, bv))
end
return false, "unhandled SWP form!"
end;
@@ -367,10 +367,8 @@ local encoders = {
return false, "LES may only place its result in RET" end
if (av == "A") and (bv == "B") then
- return string.char(0x0d)
+ return string.char(op.LES_1dA_2dB_3dRET)
else -- free-register form
-
- --return string.char(0x0d)
return false, "LES is only currently defined in the form LES .A,.B"
end
return false, "unhandled LES form!"
@@ -391,10 +389,8 @@ local encoders = {
return false, "GTR may only place its result in RET" end
if (av == "A") and (bv == "B") then
- return string.char(0xa3)
+ return string.char(op.GTR_1dA_2dB_3dRET)
else -- free-register form
-
- --return string.char(0x0d)
return false, "GTR is only currently defined in the form GTR .A,.B"
end
end;
@@ -414,9 +410,8 @@ local encoders = {
return false, "EQL may only place its result in RET" end
if (av == "A") and (bv == "B") then
- return string.char(0xa0)
+ return string.char(op.EQL_1dA_2dB_3dRET)
else -- free-register form
-
return false, "EQL is only currently defined in the form EQL .A,.B"
end
return false, "unhandled EQL form!"
@@ -437,11 +432,13 @@ local encoders = {
return false, "GTE may only place its result in RET" end
if (av == "A") and (bv == "B") then
- return string.char(0x08,0x0d,0x08) -- swap, lessthan, swap
+ return string.char(op.SWP_1dA_2dB,op.LES_1dA_2dB_3dRET,op.SWP_1dA_2dB)
+ elseif (av == "B") and (bv == "A") then
+ return string.char(op.SWP_1dA_2dB,op.LES_1dA_2dB_3dRET,op.SWP_1dA_2dB)
else -- free-register form
- return false, "GTE is only currently defined in the form GTE .A,.B"
+ return false, "GTE is only currently defined in the forms GTE .A,.B and GTE .B .A"
end
- return false, "unhandled GRT form!"
+ return false, "unhandled GTE form!"
end;
LTE = function(a, b, c)
-- less-than-or-equal-to instruction, compares two values and stores
@@ -459,7 +456,9 @@ local encoders = {
return false, "LTE may only place its result in RET" end
if (av == "A") and (bv == "B") then
- return string.char(0x08,0xa3,0x08) -- swap, lessthan, swap
+ return string.char(op.SWP_1dA_2dB,op.GTR_1dA_2dB_3dRET,op.SWP_1dA_2dB)
+ elseif (av == "B") and (bv == "A") then
+ return string.char(op.SWP_1dA_2dB,op.GTR_1dA_2dB_3dRET,op.SWP_1dA_2dB)
else -- free-register form
return false, "LTE is only currently defined in the form LTE .A,.B"
end
@@ -479,9 +478,9 @@ local encoders = {
return false, "JNZ only supports absolute (inline) jump targets at this time." end
if bf == 'literal' then
- return string.char(0x0c, bv)
+ return string.char(op.JNZ_1dRET_2dN, bv)
elseif bf == 'symbol' then
- return string.char(0x0c, 0x00), true
+ return string.char(op.JNZ_1dRET_2dN, 0x00), true
end
return false, "unhandled JNZ form!"
end;
@@ -491,18 +490,15 @@ local encoders = {
if not (a and not (b or c)) then
return false, "JMP must be properly qualified: 'JMP nn'" end
local af, aa, av = parm(a)
- if not (aa) then
- return false, "JMP only supports absolute jump targets at this time." end
if af == 'literal' then
- return string.char(0x0b, av)
+ return string.char(op.JMP_1dN, av)
elseif af == 'symbol' then
- return string.char(0x0b, 0x00), true
+ return string.char(op.JMP_1dN, 0x00), true
elseif af == 'register' then
- -- this is actually the free-register LJMP opcode, mapping the
- -- first parm to SEG (the segment pointer) makes it effectively
- -- a free-register short-jump
- return string.char(0x25, reg_encode('SEG', av))
+ -- theres no actual free-register JMP, but LJMP with SEG as 1dR is equivilent.
+ -- (its also the same size)
+ return string.char(op.LJMP_1dR_1dR, reg_encode('SEG', av))
end
return false, "unhandled JMP form!"
end;
@@ -518,7 +514,7 @@ local encoders = {
if not (af == 'register' and bf == 'register') then
return false, "LJMP only supports register jump targets at this time." end
- return string.char(0x25, reg_encode(av, bv))
+ return string.char(op.LJMP_1dR_1dR, reg_encode(av, bv))
end;
LET = function(a, b, c)
-- LET psudo-instruction, defines a sybol as the given value.
@@ -534,7 +530,7 @@ local encoders = {
return false, "only literals, or known symbols may be stored" end
symbols[a] = tonumber(b) or 0
- return ""
+ return "" -- non-encoding.
end;
LBL = function(a, b, c)
-- Label psudo-instruction, sets the named symbols to the offset and
@@ -550,7 +546,7 @@ local encoders = {
if av then symbols[av] = len%256 end
if bv then symbols[bv] = math.floor(len/256) end
- return ""
+ return "" -- non-encoding.
end;
BYTE = function(a, b, c)
-- BYTE psudo-instruction, defines the given symbols as the offset
@@ -610,9 +606,9 @@ local encoders = {
return false, "MNZ only supports absolute values at this time." end
if bf == 'register' then
- return string.char(0x0e, reg_encode(av, bv), cv)
+ return string.char(op.MNZ_1dR_2dR_3dN, reg_encode(av, bv), cv)
elseif bf == 'symbol' then
- return string.char(0x0e, reg_encode(av, bv), 0x00), true
+ return string.char(op.MNZ_1dR_2dR_3dN, reg_encode(av, bv), 0x00), true
end
return false, "unhandled MNZ form!"
end;
@@ -628,7 +624,7 @@ local encoders = {
if not (aa and ba) then
return false, "NOT only works with absolute registers" end
- return string.char(0x10, reg_encode(av, bv))
+ return string.char(op.NOT_1dR_2dR_1dR, reg_encode(av, bv))
end;
AND = function(a, b, c)
-- bitwise-AND instruction
@@ -644,7 +640,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "AND may only place its result in RET" end
- return string.char(0x11, reg_encode(av, bv))
+ return string.char(op.AND_1dR_2dR_3dRET, reg_encode(av, bv))
end;
OR = function(a, b, c)
-- bitwise-OR instruction
@@ -660,7 +656,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "OR may only place its result in RET" end
- return string.char(0x12, reg_encode(av, bv))
+ return string.char(op.OR_1dR_2dR_3dRET, reg_encode(av, bv))
end;
XOR = function(a, b, c)
-- bitwise-XOR instruction
@@ -674,7 +670,7 @@ local encoders = {
if not (aa and ba) then
return false, "XOR only works with absolute registers" end
- return string.char(0x13, reg_encode(av, bv))
+ return string.char(op.XOR_1dR_2dR_3dRET, reg_encode(av, bv))
end;
SHL = function(a, b, c)
-- Shift left instruction. shifts the bitpattern of the given value a
@@ -692,7 +688,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "SHL may only place its result in RET" end
- return string.char(0x14, reg_encode(av, bv))
+ return string.char(op.SHL_1dR_2dR_3dRET, reg_encode(av, bv))
end;
SHR = function(a, b, c)
-- Shift right instruction. shifts the bitpattern of the given value
@@ -710,7 +706,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "SHR may only place its result in RET" end
- return string.char(0x15, reg_encode(av, bv))
+ return string.char(op.SHR_1dR_2dR_3dRET, reg_encode(av, bv))
end;
SRE = function(a, b, c)
-- similar to SHR, save that it extends the sign-bit, thus
@@ -727,7 +723,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "SHR may only place its result in RET" end
- return string.char(0x16, reg_encode(av, bv))
+ return string.char(op.SRE_1dR_2dR_3dRET, reg_encode(av, bv))
end;
ROL = function(a, b, c)
-- Roll Left instruction. Rolls are similar in effect to shifts,
@@ -745,7 +741,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "ROL may only place its result in RET" end
- return string.char(0x26, reg_encode(av, bv))
+ return string.char(op.ROL_1dR_2dR_3dRET, reg_encode(av, bv))
end;
ROR = function(a, b, c)
-- Roll Right instruction. Rolls are similar in effect to shifts,
@@ -763,7 +759,7 @@ local encoders = {
if not (ca and cv=='RET') then
return false, "ROR may only place its result in RET" end
- return string.char(0x27, reg_encode(av, bv))
+ return string.char(op.ROR_1dR_2dR_3dRET, reg_encode(av, bv))
end;
IN = function(a, b, c)
-- Device port read instruction. attempts to read a single value
@@ -778,7 +774,7 @@ local encoders = {
if not (aa and ba) then
return false, "IN only works with absolute registers" end
- return string.char(0x17, reg_encode(av, bv))
+ return string.char(op.IN_1dR_2dR, reg_encode(av, bv))
end;
OUT = function(a, b, c)
-- Device port write instruction. attempts send a given byte of data
@@ -792,7 +788,7 @@ local encoders = {
if not (aa and ba) then
return false, "OUT only works with absolute registers" end
- return string.char(0x18, reg_encode(av, bv))
+ return string.char(op.OUT_1dR_2dR, reg_encode(av, bv))
end;
}
View
930 machine.lua
@@ -3,6 +3,7 @@ local bitfield = require "bitfield"
local device = require "device"
local util = require 'util'
local socket = desire 'socket'
+local opcodes = require 'opcodes'
local _M = {_NAME="machine", number=0}
@@ -66,8 +67,8 @@ local parity = {
-------------------------------------------------------------------------
-- MISC
-- number to register mappings
-local cr_tbl = {[0x0]='PRM', [0x1]='A', [0x2]='B', [0x3]='C', [0x4]='D',
- [0x5]='ACC', [0x6]='RET', [0xc]='FLG',[0xd]='SIG', [0xe]='SEG', [0xf]='IP' }
+local cr_tbl = {[0x0]='A', [0x1]='B', [0x2]='C', [0x3]='D', [0x4]='ACC', [0x5]='RET',
+ [0xa]='SS', [0xb]='SP', [0xc]='FLG',[0xd]='SIG', [0xe]='SEG', [0xf]='IP' }
-------------------------------------------------------------------------
@@ -78,7 +79,7 @@ local function printf(...)
print(string.format(...))
end
--- a variant of io.write that include printf-like formating.
+-- a variant of io.write that include printf-like formatting.
local function writef(...)
io.write(string.format(...))
end
@@ -157,6 +158,7 @@ end
-- stores a value at a given segment and offset.
local function adrset(m, adr, value, seg)
assert(m and adr, "adrset requires a segment (or machine), and an address")
+ assert(value, "adrset requires a value")
seg = seg or m.SEG
m.memory[adr+(seg*256)] = value
end
@@ -219,408 +221,544 @@ end
local function nop() end
-------------------------------------------------------------------------
--- Instruction set
---
--- the long table of opcode-function pairs that drive this malformed beast.
-_M.iset = {
- -- NOP
- -- No OPeration, do nothing, etc.
- [0x00]=function(self)
- return 1;
- end;
- -- INC ACC
- -- Fixed register Increment
- [0x01]=function(self)
- local r = (self.ACC+1)
-
- self.ACC = doflags(self, r) % 256
- return 1
- end;
- -- MOV &R:&R
- -- indirect free-register move
- [0x02]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- adrset(self, self[b], adrget(self, self[a]))
- return 2;
- end;
- -- MOV .A:&nn
- -- Move A to addresss.
- [0x03]=function(self)
- local point = adrget(self, self.IP+1)
- adrset(self, point, self.A)
- return 2;
- end;
- -- MOV &nn:.A
- -- Put address contents into A
- [0x04]=function(self)
- local point = adrget(self, self.IP+1)
- self.A = adrget(self, point)
- return 2;
- end;
- -- MOV nn:.A
- -- put literal into A
- [0x05]=function(self)
- self.A = adrget(self, self.IP+1)
- return 2;
- end;
- -- ADD R:R -> .ACC
- -- free-register ADDition, results in ACC
- [0x06]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local r = (self[a] + self[b])
-
- self.ACC = doflags(self, r) % 256
- return 2;
- end;
- -- SWP R:R
- -- Free-register swap
- [0x07]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self[a], self[b] = self[b], self[a]
- return 2;
- end;
-
-
- -- SWP .A:.B (or SWP .B:.A ...)
- -- fixed register AB swap
- [0x08]=function(self)
- self.A, self.B = self.B, self.A
- return 1;
- end;
- -- ADD .A:.B -> .ACC
- -- fixed-register AB ADDition, results in ACC
- [0x09]=function(self)
- local r = (self.A + self.B)
-
- self.ACC = doflags(self, r) % 256
- return 1;
- end;
- -- SHW .A
- -- fixed register Show A
- [0x0a]=function(self)
- print("A: "..self.A)
- return 1;
- end;
- -- JMP nn (or MOV nn:.IP
- -- unconditional jump with literal address
- [0x0b]=function(self)
- self.IP = adrget(self, self.IP+1)
- return 0;
- end;
- -- JNZ .RET, nn (or MNZ .RET, nn:.IP)
- -- fixed-register RET conditional jump with literal address
- [0x0c]=function(self)
- if self.RET ~= 0 then
- self.IP = adrget(self, self.IP+1)
- return 0
- end
- return 2;
- end;
- -- LES .A:.B -> .RET
- -- Fixed-register AB less-than, results in RET
- [0x0d]=function(self)
- self.RET = ({[true]=1,[false]=0})[self.A < self.B]
- return 1;
- end;
- -- MNZ R, R, &nn
- -- free-register conditional move to literal address
- [0x0e]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local c = adrget(self, self.IP+2)
-
- if a == 'PRM' or b == 'PRM' then
- self:signal(SIG_ILLEGAL_INSTRUCTION)
- elseif self[a] ~= 0 then
- adrset(self, c, self[b])
- end
- return 3;
- end;
- -- MOV R:R
- -- free-register move
- [0x0f]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self[b] = self[a]
- return 2;
- end;
-
-
- -- NOT R -> R
- -- free-register Bitwise NOT in:out
- [0x10]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self[b] = bitfield:new(self[a], 8):NOT()
- return 2;
- end;
- -- AND R:R -> .RET
- -- free-register bitwise AND
- [0x11]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):AND(self[b])
- return 2;
- end;
- -- OR R:R -> .RET
- -- free-register bitwise OR
- [0x12]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):OR(self[b])
- return 2;
- end;
- -- XOR R:R -> .RET
- -- free-register bitwise XOR
- [0x13]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):XOR(self[b])
- return 2;
- end;
- -- SHL R:R -> .RET
- -- free-register shift left
- [0x14]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):shift(self[b])
- return 2;
- end;
- -- SHR R:R -> .RET
- -- free-register shift right
- [0x15]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):shift(-self[b])
- return 2;
- end;
- -- SRE R:R -> .RET
- -- free-register shift right w/ sign extension
- [0x16]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):shift(-self[b], true)
- return 2;
- end;
- -- IN R1 -> R2
- -- free-register I/O port read
- [0x17]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
-
- local ret, err = self:deviceRead(self[a])
- if not ret then
- self:signal(SIG_DEVICE_NOT_READY)
- else
- self[b] = ret
- end
- return 2;
- end;
+-- opcode Function
+-- the actual functions that do the heavy-lifting.
+local ins = {}
+
+--generals...
+local function store(self, reg, seg, adr)
+ assert(reg, "must be given a valid register")
+ assert(type(reg) == 'string', "must be given a valid register name")
+ assert(seg and adr, "must be given a valid address")
+ adrset(self, adr, self[reg], seg)
+end
+
+local function load(self, reg, seg, adr)
+ assert(reg, "must be given a valid register")
+ assert(type(reg) == 'string', "must be given a valid register name")
+ assert(seg and adr, "must be given a valid address")
+
+ self[reg] = adrget(self, adr, seg)
+end
+
+-- specifics...
+
+-- NOP
+-- No OPeration, do nothing, etc.
+function ins.NOP(self)
+ return 1;
+end;
+
+-- INC A
+-- Fixed register Increment
+function ins.INC_1dA(self)
+ self.A = doflags(self,(self.A+1)) % 256
+ return 1
+end;
+-- INC B
+-- Fixed register Increment
+function ins.INC_1dB(self)
+ self.B = doflags(self,(self.B+1)) % 256
+ return 1
+end;
+-- INC C
+-- Fixed register Increment
+function ins.INC_1dC(self)
+ self.C = doflags(self,(self.C+1)) % 256
+ return 1
+end;
+-- INC D
+-- Fixed register Increment
+function ins.INC_1dD(self)
+ self.D = doflags(self,(self.D+1)) % 256
+ return 1
+end;
+-- INC ACC
+-- Fixed register Increment
+function ins.INC_1dACC(self)
+ self.ACC = doflags(self,(self.ACC+1)) % 256
+ return 1
+end;
+
+-- DEC A
+-- Fixed register Decrement
+function ins.DEC_1dACC(self)
+ self.A = doflags(self,(self.A-1)) % 256
+ return 1
+end;
+-- DEC B
+-- Fixed register Decrement
+function ins.DEC_1dACC(self)
+ self.B = doflags(self,(self.B-1)) % 256
+ return 1
+end;
+-- DEC C
+-- Fixed register Decrement
+function ins.DEC_1dC(self)
+ self.C = doflags(self,(self.C-1)) % 256
+ return 1
+end;
+-- DEC D
+-- Fixed register Decrement
+function ins.DEC_1dD(self)
+ self.D = doflags(self,(self.D-1)) % 256
+ return 1
+end;
+-- DEC ACC
+-- Fixed register Decrement
+function ins.DEC_1dACC(self)
+ self.ACC = doflags(self,(self.ACC-1)) % 256
+ return 1
+end;
+
+-- MOV &R:&R
+-- indirect free-register move
+function ins.MOV_1iR_2iR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ adrset(self, self[b], adrget(self, self[a]))
+ return 2;
+end;
+
+-- MOV .A:nn
+-- Move A to addresss.
+function ins.MOV_1dA_2dN(self)
+ store(self, 'A', self.SEG, adrget(self, self.IP+1))
+ return 2;
+end;
+
+-- MOV .B:nn
+-- Move B to addresss.
+function ins.MOV_1dB_2dN(self)
+ store(self, 'B', self.SEG, adrget(self, self.IP+1))
+ return 2;
+end;
+
+-- MOV .C:nn
+-- Move C to addresss.
+function ins.MOV_1dC_2dN(self)
+ store(self, 'C', self.SEG, adrget(self, self.IP+1))
+ return 2;
+end;
+
+-- MOV .D:nn
+-- Move D to addresss.
+function ins.MOV_1dD_2dN(self)
+ store(self, 'D', self.SEG, adrget(self, self.IP+1))
+ return 2;
+end;
+
+-- MOV &nn:.A
+-- Put address contents into A
+function ins.MOV_1iN_2dA(self)
+ local point = adrget(self, self.IP+1)
+ self.A = adrget(self, point)
+ return 2;
+end;
+
+-- MOV nn:.A
+-- put literal into A
+function ins.MOV_1dN_2dA(self)
+ self.A = adrget(self, self.IP+1)
+ return 2;
+end;
+
+-- MOV nn, B
+-- Fixed-register literal MOV to B
+function ins.MOV_1dN_2dB(self)
+ self.B = adrget(self, self.IP+1)
+ return 2;
+end;
+
+-- MOV R:R
+-- free-register move
+function ins.MOV_1dR_2dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self[b] = self[a]
+ return 2;
+end;
+
+-- MOV &nn, B
+-- Fixed-register indirect MOV to B
+function ins.MOV_1iN_2dB(self)
+ self.B = adrget(self, adrget(self, self.IP+1))
+ return 2;
+end;
+
+-- MOV B, &nn
+-- Fixed-register indirect MOV from B
+function ins.MOV_1dB_2iN(self)
+ adrset(self,adrget(self, self.IP+1), self.B)
+ return 2;
+end;
+
+-- ADD .A:.B -> .RET
+-- fixed-register AB ADDition, results in RET
+function ins.ADD_1dA_2dB_3dRET(self)
+ local r = (self.A + self.B)
+ self.RET = doflags(self, r) % 256
+ return 1;
+end;
+
+-- ADD .A:.B -> .ACC
+-- fixed-register AB ADDition, results in ACC
+function ins.ADD_1dA_2dB_3dACC(self)
+ local r = (self.A + self.B)
- -- OUT R1, R2
- -- free-register I/O port write
- [0x18]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
+ self.ACC = doflags(self, r) % 256
+ return 1;
+end;
+
+-- ADD R:R -> .ACC
+-- free-register ADDition, results in ACC
+function ins.ADD_1dR_2dR_3dACC(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r = (self[a] + self[b])
+ self.ACC = doflags(self, r) % 256
+ return 2;
+end;
+
+-- ADD R:R -> .RET
+-- free-register ADDition, results in ACC
+function ins.ADD_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r = (self[a] + self[b])
+
+ self.RET = doflags(self, r) % 256
+ return 2;
+end;
+
+-- SWP R:R
+-- Free-register swap
+function ins.SWP_1dR_2dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self[a], self[b] = self[b], self[a]
+ return 2;
+end;
+
+-- MNZ R, R, nn
+-- free-register conditional move to literal address
+function ins.MNZ_1dR_2dR_3dN(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local c = adrget(self, self.IP+2)
+
+ if self[a] ~= 0 then
+ adrset(self, c, self[b])
+ end
+ return 3;
+end;
- local ret, err = self:deviceWrite(self[a], self[b])
- if not ret then
- self:signal(SIG_DEVICE_NOT_READY)
- end
- return 2;
- end;
- -- MUL R, R -> RET
- -- Free-register Multiply
- [0x19]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- if a == 'PRM' or b == 'PRM' then
- self:signal(SIG_ILLEGAL_INSTRUCTION) end
-
- local r = round(self[a] * self[b])
-
- self.RET = doflags(self, r) % 256
- return 2;
- end;
- -- SUB R1:.R2 -> .ACC
- -- free-register ADDition, results in ACC
- [0x1a]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
-
- local r = (self[a] - self[b])
-
- self.ACC = doflags(self, r) % 256
- return 2;
- end;
- -- MOD R, R -> RET
- -- Free-register Modulo
- [0x1b]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local r =round(self[a] % self[b])
- self.RET = doflags(self, r) % 256
- return 2;
- end;
- -- MOD R, R -> ACC
- -- Free-register Modulo
- [0x1c]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local r = round(self[a] % self[b])
-
- self.ACC = doflags(self, r) % 256
- return 2;
- end;
- -- DIV R, R -> ACC
- -- Free-register divide
- [0x1d]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- if self.b == 0 then self:signal(SIG_DIV0) end
- local r = round(self[a] / self[b])
- self.ACC = doflags(self, r) % 256
- return 2;
- end;
- -- MUL R, R -> ACC
- -- Free-register Multiply
- [0x1e]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- if a == 'PRM' or b == 'PRM' then
- self:signal(SIG_ILLEGAL_INSTRUCTION) end
-
- local r = round(self[a] * self[b])
-
- self.ACC = doflags(self, r) % 256
- return 2;
- end;
- -- DEC ACC
- -- Fixed register Decrement
- [0x1f]=function(self)
- local r = (self.ACC-1)
-
- self.ACC = doflags(self, r) % 256
- return 1
- end;
+-- SWP .A:.B (or SWP .B:.A ...)
+-- fixed register AB swap
+function ins.SWP_1dA_2dB(self)
+ self.A, self.B = self.B, self.A
+ return 1;
+end;
- -- SUB R1:R2 -> RET
- -- Free-register SUBtraction, results in RET
- [0x20]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local r = (self[a] - self[b])
-
- self.RET = doflags(self, r) % 256
- return 2;
- end;
- -- MOV nn, B
- -- Fixed-register literal MOV to B
- [0x21]=function(self)
- self.B = adrget(self, self.IP+1)
- return 2;
- end;
- -- MOV &nn, B
- -- Fixed-register indirect MOV to B
- [0x22]=function(self)
- self.B = adrget(self, adrget(self, self.IP+1))
- return 2;
- end;
- -- MOV B, &nn
- -- Fixed-register indirect MOV from B
- [0x23]=function(self)
- adrset(self,adrget(self, self.IP+1), self.B)
- return 2;
- end;
- -- LMOV R1(seg),R2(off),R3(destseg), R4(destoff)
- -- free-register direct Long-move
- [0x24]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local c, d = convreg(self, adrget(self, self.IP+2))
- adrset(self, self[d], adrget(self, self[b], self[a]), self[c])
- return 3;
- end;
- -- LJMP R1(seg), R2(off)
- -- free-register unconditional jump
- [0x25]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.SEG = self[a]
- self.IP = self[b]
- return 0;
- end;
- -- ROL R:R -> .RET
- -- free-register roll left
- [0x26]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):roll(self[b])
- return 2;
- end;
- -- ROR R:R -> .RET
- -- free-register roll right
- [0x27]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- self.RET = bitfield:new(self[a], 8):roll(-self[b])
- return 2;
- end;
-
-
- -- EQL .A:.B -> .RET
- -- fixed-register AB equals, results in RET
- [0xa0]=function(self)
- self.RET = ({[true]=1,[false]=0})[self.A == self.B]
- return 1;
- end;
- -- SHW R
- -- Free-register show
- [0xa1]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- print(a..": "..self[a])
- return 2;
- end;
- -- DIV R, R -> RET
- -- Free-register divide
- [0xa2]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- if self.b == 0 then self:signal(SIG_DIV0) end
- local r = round(self[a] / self[b])
- self.RET = doflags(self, r) % 256
- return 2;
- end;
- -- GTR .A:.B -> .RET
- -- Fixed-register AB greater-than, results in RET
- [0xa3]=function(self)
- self.RET = ({[true]=1,[false]=0})[self.A > self.B]
- return 1;
- end;
- -- ADD R:R -> .RET
- -- free-register ADDition, results in ACC
- [0xa4]=function(self)
- local a, b = convreg(self, adrget(self, self.IP+1))
- local r = (self[a] + self[b])
-
- self.RET = doflags(self, r) % 256
- return 2;
- end;
- -- SUB .A:.B -> .RET
- -- fixed-register AB SUBtraction, results in RET
- [0xa5]=function(self)
- local r = (self.A - self.B)
-
- self.RET = doflags(self, r) % 256
- return 1;
- end;
- -- ADD .A:.B -> .RET
- -- fixed-register AB ADDition, results in RET
- [0xa6]=function(self)
- local r = (self.A + self.B)
-
- self.RET = doflags(self, r) % 256
- return 1;
- end;
- -- SUB .A:.B -> .ACC
- -- fixed-register AB SUBtraction, results in ACC
- [0xa7]=function(self)
- local r = (self.A - self.B)
-
- self.ACC = doflags(self, r) % 256
- return 1;
- end;
+-- ADD .A:.B -> .ACC
+-- fixed-register AB ADDition, results in ACC
+function ins.ADD_1dA_2dB(self)
+ local r = (self.A + self.B)
+
+ self.ACC = doflags(self, r) % 256
+ return 1;
+end;
+
+
+-- SHW .A
+-- fixed register Show A
+function ins.SHW_1dA(self)
+ print("A: "..self.A)
+ return 1;
+end;
+
+-- SHW R
+-- Free-register show
+function ins.SHW_1dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ print(a..": "..self[a])
+ return 2;
+end;
+
+-- JMP nn (or MOV nn:.IP
+-- unconditional jump with literal address
+function ins.JMP_1dN(self)
+ self.IP = adrget(self, self.IP+1)
+ return 0;
+end;
+
+-- JNZ .RET, nn (or MNZ .RET, nn:.IP)
+-- fixed-register RET conditional jump with literal address
+function ins.JNZ_1dRET_2dN(self)
+ if self.RET ~= 0 then
+ self.IP = adrget(self, self.IP+1)
+ return 0
+ end
+ return 2;
+end;
+
+-- NOT R -> R
+-- free-register Bitwise NOT in:out
+function ins.NOT_1dR_2dR_1dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self[b] = bitfield:new(self[a], 8):NOT()
+ return 2;
+end;
+
+-- AND R:R -> .RET
+-- free-register bitwise AND
+function ins.AND_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):AND(self[b])
+ return 2;
+end;
+
+-- OR R:R -> .RET
+-- free-register bitwise OR
+function ins.OR_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):OR(self[b])
+ return 2;
+end;
+
+-- XOR R:R -> .RET
+-- free-register bitwise XOR
+function ins.XOR_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):XOR(self[b])
+ return 2;
+end;
+
+-- SHL R:R -> .RET
+-- free-register shift left
+function ins.SHL_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):shift(self[b])
+ return 2;
+end;
+
+-- SHR R:R -> .RET
+-- free-register shift right
+function ins.SHR_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):shift(-self[b])
+ return 2;
+end;
+
+-- SRE R:R -> .RET
+-- free-register shift right w/ sign extension
+function ins.SRE_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):shift(-self[b], true)
+ return 2;
+end;
+
+-- ROL R:R -> .RET
+-- free-register roll left
+function ins.ROL_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):roll(self[b])
+ return 2;
+end;
+
+-- ROR R:R -> .RET
+-- free-register roll right
+function ins.ROR_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.RET = bitfield:new(self[a], 8):roll(-self[b])
+ return 2;
+end;
+
+-- IN R1 -> R2
+-- free-register I/O port read
+function ins.IN_1dR_2dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local ret, err = self:deviceRead(self[a])
+ if not ret then
+ self:signal(SIG_DEVICE_NOT_READY)
+ else
+ self[b] = ret
+ end
+ return 2;
+end;
+
+-- OUT R1, R2
+-- free-register I/O port write
+function ins.OUT_1dR_2dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local ret, err = self:deviceWrite(self[a], self[b])
+ if not ret then
+ self:signal(SIG_DEVICE_NOT_READY)
+ end
+ return 2;
+end;
- -- HLT
- -- halts the machine
- [0xff]=function(self)
- self.state = 'halt';
- return 0;
- end;
+-- MUL R, R -> RET
+-- Free-register Multiply
+function ins.MUL_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ if a == 'PRM' or b == 'PRM' then
+ self:signal(SIG_ILLEGAL_INSTRUCTION) end
+
+ local r = round(self[a] * self[b])
- }
+ self.RET = doflags(self, r) % 256
+ return 2;
+end;
+-- SUB .A:.B -> .ACC
+-- fixed-register AB ADDition, results in ACC
+function ins.SUB_1dA_2dB_3dACC(self)
+ local r = (self.A - self.B)
+
+ self.ACC = doflags(self, r) % 256
+ return 1;
+end;
+
+-- SUB R1:.R2 -> .ACC
+-- free-register ADDition, results in ACC
+function ins.SUB_1dR_2dR_3dACC(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r = (self[a] - self[b])
+
+ self.ACC = doflags(self, r) % 256
+ return 2;
+end;
+
+-- SUB .A:.B -> .RET
+-- fixed-register AB ADDition, results in ACC
+function ins.SUB_1dA_2dB_3dRET(self)
+ local r = (self.A - self.B)
+
+ self.ACC = doflags(self, r) % 256
+ return 1;
+end;
+
+-- SUB R1:.R2 -> .RET
+-- free-register SUBition, results in RET
+function ins.SUB_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r = (self[a] - self[b])
+
+ self.RET = doflags(self, r) % 256
+ return 2;
+end;
+
+
+-- MOD R, R -> RET
+-- Free-register Modulo
+function ins.MOD_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r =round(self[a] % self[b])
+ self.RET = doflags(self, r) % 256
+ return 2;
+end;
+
+-- MOD R, R -> ACC
+-- Free-register Modulo
+function ins.MOD_1dR_2dR_3dACC(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local r = round(self[a] % self[b])
+
+ self.ACC = doflags(self, r) % 256
+ return 2;
+end;
+
+-- DIV R, R -> ACC
+-- Free-register divide
+function ins.DIV_1dR_2dR_3dACC(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ if self.b == 0 then self:signal(SIG_DIV0) end
+ local r = round(self[a] / self[b])
+ self.ACC = doflags(self, r) % 256
+ return 2;
+end;
+
+-- DIV R, R -> RET
+-- Free-register divide
+function ins.DIV_1dR_2dR_3dRET(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ if self.b == 0 then self:signal(SIG_DIV0) end
+ local r = round(self[a] / self[b])
+ self.RET = doflags(self, r) % 256
+ return 2;
+end;
+
+
+-- MUL R, R -> ACC
+-- Free-register Multiply
+function ins.MUL_1dR_2dR_3dACC(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+
+ local r = round(self[a] * self[b])
+
+ self.ACC = doflags(self, r) % 256
+ return 2;
+end;
+
+-- LMOV R1(seg),R2(off),R3(destseg), R4(destoff)
+-- free-register direct Long-move
+function ins.LMOV_1dR_2dR_3dR_4dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ local c, d = convreg(self, adrget(self, self.IP+2))
+ adrset(self, self[d], adrget(self, self[b], self[a]), self[c])
+ return 3;
+end;
+
+-- LJMP R1(seg), R2(off)
+-- free-register unconditional jump
+function ins.LJMP_1dR_2dR(self)
+ local a, b = convreg(self, adrget(self, self.IP+1))
+ self.SEG = self[a]
+ self.IP = self[b]
+ return 0;
+end;
+
+-- EQL .A:.B -> .RET
+-- fixed-register AB equals, results in RET
+function ins.EQL_1dA_2dB_3dRET(self)
+ self.RET = ({[true]=1,[false]=0})[self.A == self.B]
+ return 1;
+end;
+
+-- GTR .A:.B -> .RET
+-- Fixed-register AB greater-than, results in RET
+function ins.GTR_1dA_2dB_3dRET(self)
+ self.RET = ({[true]=1,[false]=0})[self.A > self.B]
+ return 1;
+end;
+
+-- LES .A:.B -> .RET
+-- Fixed-register AB less-than, results in RET
+function ins.LES_1dA_2dB_3dRET(self)
+ self.RET = ({[true]=1,[false]=0})[self.A < self.B]
+ return 1;
+end;
+
+-- HLT
+-- halts the machine
+function ins.HLT(self)
+ self.state = 'halt';
+ return 0;
+end;
+
+-------------------------------------------------------------------------
+-- Instruction set
+--
+
+_M.iset = {}
+local remap = opcodes.map
+local map
+for i=0, 0xff do
+ map = (remap[i] and remap[i][1]) or false
+ if map then
+ if not ins[map] then error(string.format("illegal mapping %02x to '%s'", i, tostring(map))) end
+ _M.iset[i] = ins[map]
+ end
+end
-_M.speed = 1*MEGAHERTZ -- set he default speed.
+_M.speed = 1*MEGAHERTZ -- set the default speed.
-----
-- With parm it returns the current SIGnal
View
77 opcodes.lua
@@ -0,0 +1,77 @@
+local _M = {_NAME="opcodes", _TYPE="module"}
+
+local remap = {
+ [0x00] = {'NOP'};
+ [0x01] = {'INC_1dACC'};
+ [0x02] = {'MOV_1iR_2iR'};
+ [0x03] = {'MOV_1dA_2dN'};
+ [0x04] = {'MOV_1iN_2dA'};
+ [0x05] = {'MOV_1dN_2dA'};
+ [0x06] = {'ADD_1dR_2dR_3dACC'};
+ [0x07] = {'SWP_1dR_2dR'};
+
+ [0x08] = {'SWP_1dA_2dB', 'SWP_1dB_2dA'};
+ [0x09] = {'ADD_1dA_2dB_3dACC'};
+ [0x0a] = {'SHW_1dA'};
+ [0x0b] = {'JMP_1dN', 'MOV_1dN_2dIP', 'LJMP_1dSEG_2dN'};
+ [0x0c] = {'JNZ_1dRET_2dN', 'MNZ_1dRET_2dN_3dIP'};
+ [0x0d] = {'LES_1dA_2dB_3dRET', 'GTE_2dB_1dA_3dRET'};
+ [0x0e] = {'MNZ_1dR_2dR_3dN'};
+ [0x0f] = {'MOV_1dR_2dR'};
+
+ [0x10] = {'NOT_1dR_2dR_1dR'};
+ [0x11] = {'AND_1dR_2dR_3dRET'};
+ [0x12] = {'OR_1dR_2dR_3dRET'};
+ [0x13] = {'XOR_1dR_2dR_3dRET'};
+ [0x14] = {'SHL_1dR_2dR_3dRET'};
+ [0x15] = {'SHR_1dR_2dR_3dRET'};
+ [0x16] = {'SRE_1dR_2dR_3dRET'};
+ [0x17] = {'IN_1dR_2dR'};
+
+ [0x18] = {'OUT_1dR_2dR'};
+ [0x19] = {'MUL_1dR_2dR_3dRET'};
+ [0x1a] = {'SUB_1dR_2dR_3dACC'};
+ [0x1b] = {'MOD_1dR_2dR_3dRET'};
+ [0x1c] = {'MOD_1dR_2dR_3dACC'};
+ [0x1d] = {'DIV_1dR_2dR_3dACC'};
+ [0x1e] = {'MUL_1dR_2dR_3dACC'};
+ [0x1f] = {'DEC_1dACC'};
+
+ [0x20] = {'SUB_1dR_2dR_3dRET'};
+ [0x21] = {'MOV_1dN_2dB'};
+ [0x22] = {'MOV_1iN_2dB'};
+ [0x23] = {'MOV_1dB_2dN'};
+ [0x24] = {'LMOV_1dR_2dR_3dR_4dR'};
+ [0x25] = {'LJMP_1dR_2dR'};
+ [0x26] = {'ROL_1dR_2dR_3dRET'};
+ [0x27] = {'ROR_1dR_2dR_3dRET'};
+
+ [0xa0] = {'EQL_1dA_2dB_3dRET'};
+ [0xa1] = {'SHW_1dR'};
+ [0xa2] = {'DIV_1dR_2dR_3dRET'};
+ [0xa3] = {'GTR_1dA_2dB_3dRET', 'LTE_2dB_1dA_3dRET'};
+ [0xa4] = {'ADD_1dR_2dR_3dRET'};
+ [0xa5] = {'SUB_1dR_2dR_3dRET'};
+ [0xa6] = {'ADD_1dA_2dB_3dRET'};
+ [0xa7] = {'SUB_1dA_2dB_3dACC'};
+
+ [0xff] = {'HLT', 'STOP'};
+}
+
+local ins
+for i=0x00, 0xff do
+ ins = remap[i]
+ if ins then
+ for j=1, #ins do
+ if remap[ins[j]] then
+ assert(("dupliate instruction: %s = 0x%02x,0x%02x"):format(ins[j], i, remap[ins[j]]))
+ end
+ remap[ins[j]] = i
+ end
+ end
+end
+
+_M.map = remap
+
+return _M;
+
View
26 util.lua
@@ -0,0 +1,26 @@
+
+-- 'desire' functions similarly to 'require', save that failure is not an error.
+-- use this if you can make use of a modules features, but can make do without.
+--
+-- if successful it returns the same value that require would return
+-- (either true, or the actual module table) if unsuccessful, it returns
+-- false, and a string indicating the error.
+function desire(name, ...)
+ local p, m, err = pcall(require, n, ...)
+ if p then
+ return m
+ else -- p == false
+ return p, m
+ end
+end
+
+-- inquire determines if a package is loaded.
+-- if so, it returns the value that 'require' would return.
+-- otherwise, it returns false and the string "not loaded"
+function inquire(name, ...)
+ if package.loaded[name] then
+ return package.loaded[name]
+ else
+ return false, "not loaded"
+ end
+end

0 comments on commit e03dde2

Please sign in to comment.