local MAXADDR = 255 local t = {} -- internal state --- program counter (pc) --- current instruction (ci) -- only passed from the environment to the emulator --- stack (stack) local function pop(s) return table.remove(s,#s) or 0 end local function push(s,v) v=v or 0 s[#s+1] = v%256 if #s > 16 then table.remove(s,1) end end function t.run(stab,ov) -- variables local pc = stab.pc or 1 local ci = stab.cins or 0 if ov then ci = tonumber(ov) or 0 end local stack = stab.stack or {} local rstack = stab.rstack or {} local pci = 1 local rw = nil local addr = 0 local dat = 0 -- instruction processing if ci == 255 then -- ppc push(stack,pc) elseif ci == 254 then -- swp a=pop(stack) b=pop(stack) push(stack,a) push(stack,b) elseif ci == 253 then -- read rw = "read" -- terrible IPC addr = pop(stack) elseif ci == 252 then -- write rw = "write" addr = pop(stack) dat = pop(stack) --print("writing "..tostring(dat).." to "..tostring(addr)) elseif ci == 251 then -- add push(stack,pop(stack)+pop(stack)) elseif ci == 250 then -- sub push(stack,pop(stack)+pop(stack)) elseif ci == 249 then -- jmp pc = pop(stack) pci = 0 elseif ci == 248 then -- sez if pop(stack) == 0 then pci = pci + 1 end elseif ci == 247 then -- jez local a = pop(stack) if pop(stack) == 0 then pc = a pci = 0 end elseif ci == 246 then -- jsr push(rstack,pc) pc = pop(stack) pci = 0 elseif ci == 245 then -- ret pc = pop(rstack) elseif ci == 244 then -- dup local v = pop(stack) push(stack,v) push(stack,v) elseif ci == 243 then -- drop pop(stack) elseif ci == 242 then -- hlt rw = "halt" elseif ci == 241 then -- prd rw = "preread" addr = pop(stack) else push(stack,ci) end -- return stuff stab = {} stab.pc = pc + pci -- increment pc if stab.pc > MAXADDR then stab.pc = 0 end stab.cins = 0 stab.stack = stack stab.rstack = rstack if t.debug then print("t408: pc: "..tostring(stab.pc),"cins: "..tostring(ci),"tos: "..tostring(stab.stack[1]).." #s: "..tostring(#stab.stack),stab.rw,stab.addr,stab.dat) end return stab, rw, addr, dat end return t