-- ilo.lua -- Partially derived from Ngaro in Lua -- Copyright (c) 2010 - 2023, Charles Childers -- -- This is only tested on Lua 5.4 and requires 32-bit -- integers. (set `#define LUA_32BITS 1` in luaconf.h when -- building Lua) -- Variables local ip = 0 -- instruction pointer local sp = 0 -- stack pointer local rp = 0 -- return pointer local stack = {} -- data stack local address = {} -- return stack local memory = {} -- simulated ram -- Support Code local function file_size(filename) local fh = assert(io.open(filename, 'rb')) local len = assert(fh:seek('end')) fh:close() return len end local function constrain(n) return (n > 0x7FFFFFFF) and (n - 0x100000000) or n end local function save_image() local image = io.open('ilo.rom', 'wb') local i = 0 while i < 65536 do image:write(string.pack(' stack[sp] then stack[sp - 1] = -1 else stack[sp - 1] = 0 end sp = sp - 1 end, [16] = function() -- fe (fetch) stack[sp] = memory[stack[sp]] end, [17] = function() -- st (store) memory[stack[sp]] = stack[sp - 1] sp = sp - 2 end, [18] = function() -- ad (add) stack[sp - 1] = stack[sp - 1] + stack[sp] sp = sp - 1 end, [19] = function() -- su (subtract) stack[sp - 1] = stack[sp - 1] - stack[sp] sp = sp - 1 end, [20] = function() -- mu (multiply) stack[sp - 1] = stack[sp - 1] * stack[sp] sp = sp - 1 end, [21] = function() -- di (divide & remainder) local b = stack[sp] local a = stack[sp - 1] local x = math.abs(b) local y = math.abs(a) local q = constrain(y // x) local r = constrain(y % x) if a < 0 and b < 0 then r = r * -1 elseif a > 0 and b < 0 then q = q * -1 elseif a < 0 and b > 0 then r = r * -1 q = q * -1 end stack[sp] = q stack[sp - 1] = r end, [22] = function() -- an (and) stack[sp - 1] = stack[sp - 1] & stack[sp] sp = sp - 1 end, [23] = function() -- or (or) stack[sp - 1] = stack[sp - 1] | stack[sp] sp = sp - 1 end, [24] = function() -- xo (xor) stack[sp - 1] = stack[sp - 1] ~ stack[sp] sp = sp - 1 end, [25] = function() -- sl (shift left) stack[sp - 1] = stack[sp - 1] << stack[sp] sp = sp - 1 end, [26] = function() -- sr (shift right) stack[sp - 1] = stack[sp - 1] >> stack[sp] sp = sp - 1 end, [27] = function() -- cp (compare) local a = stack[sp] -- length local b = stack[sp - 1] -- dest local c = stack[sp - 2] -- source local d = -1 -- flag sp = sp - 3 while a > 0 do if memory[b] ~= memory[c] then d = 0 end a = a - 1 b = b + 1 c = c + 1 end sp = sp + 1 stack[sp] = d end, [28] = function() -- cy (copy) local a = stack[sp] -- length local b = stack[sp - 1] -- dest local c = stack[sp - 2] -- source sp = sp - 3 while a > 0 do memory[b] = memory[c] a = a - 1 b = b + 1 c = c + 1 end end, [29] = function() -- io local d = stack[sp] sp = sp - 1 if d == 0 then io.write(string.char(stack[sp])) sp = sp - 1 elseif d == 1 then sp = sp + 1 stack[sp] = string.byte(io.read(1)) elseif d == 2 then read_block() elseif d == 3 then write_block() elseif d == 4 then save_image() elseif d == 5 then load_image("ilo.rom") ip = -1 sp = 0 rp = 0 elseif d == 6 then ip = 65536 elseif d == 7 then sp = sp + 1 stack[sp] = sp - 1 sp = sp + 1 stack[sp] = rp end end } -- ------------------------------------------------------------- -- process opcodes local function process_opcode(opcode) if opcode == 0 then return end -- skip NOP instructions local op_fn = opcodes[opcode] if op_fn then op_fn() end end local function process_opcodes() local opcode = memory[ip] process_opcode(opcode & 0xFF) process_opcode(opcode>>8 & 0xFF) process_opcode(opcode>>16 & 0xFF) process_opcode(opcode>>24 & 0xFF) end -- Load image into memory -- \ cells = size of image file (in cells) -- \ image = pointer to retroImage file local function load_image(file) local cells = file_size(file) / 4 local image = io.open(file, 'rb') local i = 0 while i < cells do memory[i] = string.unpack(' 0 do print(stack[sp]) sp = sp - 1 end end local function process_instructions() while ip < 65536 do process_opcodes() ip = ip + 1 end end local function main() load_image("ilo.rom") process_instructions() dump_stack() end main()