fix conditions, add ien flag, improve keyboard, add gpio

This commit is contained in:
Redo
2023-01-04 13:29:55 -06:00
parent 4af6f46a51
commit b75ff48300
8 changed files with 160 additions and 53 deletions

View File

@ -42,7 +42,7 @@
#define ldi cpu->instr = readmemory(cpu->i); cpu->cycle = 0;
#define addf(x,y) { x=(x+y); cpu->cf=x>=256; x&=0xFF; setzf(x); }
#define subf(x,y) addf(x,-y);
#define cmpf(x,y) { int t=x-y; cpu->cf=(t>=256); setzf(t); }
#define cmpf(x,y) { int t=x-y; cpu->cf=(t<0); setzf(t); }
#define rol(x,y) x=(x<<y)|(x>>(8-y));
#define ror(x,y) x=(x>>y)|(x<<(8-y));
#define sra(x,y) x=(x>>y);
@ -80,6 +80,7 @@ struct CPU {
int irq;
int ifg;
int rfg;
int ien;
int instr;
int cycle;
int instrpre;
@ -130,14 +131,15 @@ typedef void(*CPUInstruction)(struct CPU* const cpu, struct Memory* const mem);
#include "instructions_gen.c"
int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs) {
int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs, const int breakaddr) {
int i = 0;
while(i<count) {
if(cpu->irq && !cpu->ifg && cpu->cycle==0) { cpu->instr = 0xF2; }
if(cpu->irq && !cpu->ifg && cpu->cycle==0 && cpu->ien) { cpu->instr = 0xF2; }
if(cpu->rfg || cpu->ifg || cpu->irq) {
CPUInstruction instr = CPUInstructions[cpu->instr][cpu->cycle];
if(instr) instr(cpu, mem);
if(!countinstrs || cpu->cycle==0) { i++; }
if(cpu->i==breakaddr) { i = count; break; }
} else { i = count; break; }
if(mem->numevents!=0) { break; }
}

Binary file not shown.

View File

@ -11,6 +11,7 @@ local lg = love.graphics
local li = love.image
local le = love.event
local lt = love.timer
local lk = love.keyboard
----
local function InitColorset()
@ -43,7 +44,7 @@ local function handleEvents(cpu, mem)
end
local RegDisplay = {
scrX = 384+16, scrY = 32,
scrX = 384+16, scrY = 32+8,
width = 128, height = 192,
fontWidth = 8, fontHeight = 12,
registers = {
@ -63,7 +64,8 @@ local RegDisplay = {
flags = {
{ name = "CF" , idx = "cf" , x=64+8,y=8 },
{ name = "NZ" , idx = "nz" , x=64+8,y=8+16 },
{ name = "IRQ", idx = "irq", x=64+8,y=8+16*2},
{ name = "IRq", idx = "irq", x=64+8,y=8+16*2},
{ name = "IEn", idx = "ien", x=64+8,y=8+16*5},
{ name = "Int", idx = "ifg", x=64+8,y=8+16*3},
{ name = "Run", idx = "rfg", x=64+8,y=8+16*4},
},
@ -107,8 +109,9 @@ local function RedrawRegDisplay(rd, cpu, mem)
end
local ReadMemory
local WriteMemory
local StackDisplay = {
scrX = 8+384+32+6, scrY = 32+192+32,
scrX = 8+384+32+6, scrY = 32+192+32-4,
lines = 16, fontHeight = 12,
}
local function InitStackDisplay(sd)
@ -130,11 +133,11 @@ end
local MemoryDisplays = {
{
scrX = 8, scrY = 32+192+32,
scrX = 8, scrY = 32+192+32-4,
columns = 16, columnSpace = 4, rows = 16,
fontHeight = 12,
showAscii = false,
addr = 0x0000,
addr = 0x3000,
highlightTime = 8,
},
}
@ -205,9 +208,9 @@ local function RedrawMemoryDisplay(md, cpu, mem)
end
local ProgramDisplay = {
scrX = 8+384+8+128+8, scrY = 32,
scrX = 8+384+8+128+8, scrY = 32+8,
fontHeight = 12,
numLines = 35,
numLines = 34,
highlightTime = 8,
}
local function pdLinesFromDasm(dasm)
@ -301,20 +304,12 @@ local CharDisplay = {
width = 64*6, height = 16*12,
rows = 16, cols = 64,
fontWidth = 6, fontHeight = 12,
scrX = 8, scrY = 32,
scrX = 8, scrY = 32+8,
addrChar = 0x0800,
addrColor = 0x0C00,
}
local function InitCharDisplay(cd)
lg.print("Char Display", cd.scrX, cd.scrY-16)
cd.chars = {}
cd.colors = {}
cd.highlight = {}
for a = 0, cd.rows*cd.cols-1 do
cd.chars[a] = ""
cd.colors[a] = ColorSet[1]
cd.highlight[a] = false
end
cd.font = lg.newFont("consola.ttf", cd.fontHeight-1, "mono")
end
@ -346,19 +341,92 @@ local keycodes = require("keycodes")
local CPURequestInterrupt
local function KeyboardOnKey(kb, key, press, cpu, mem)
local code = keycodes[key] or keycodes["invalid"]
table.insert(kb.queue, code)
if code==0x7F then print("invalid key: "..key) end
table.insert(kb.queue, code + (press and 128 or 0))
if #kb.queue > kb.queueSize then table.remove(kb.queue, 1) end
kb.queueEmpty = false
kbSetNext(kb, cpu, mem)
if kb.interrupts then CPURequestInterrupt(cpu) end
end
local function RedrawFPSCounter(x,y)
local function RedrawFPSCounter(x, y)
lg.setColor(0,0,0)
lg.rectangle("fill",x,y,64,12)
lg.setColor(1,1,1)
lg.print("FPS: "..lt.getFPS(), x,y)
end
local function printHighlight(s, o, h, x, y)
x = x+o*7
local w = 7*#s
lg.setColor(1,1,1)
if h then
lg.rectangle("fill", x, y, w, 12)
lg.setColor(0,0,0)
end
lg.print(s, x, y)
end
local function RedrawKeyInfo(x, y, uk, run)
lg.setColor(0,0,0)
lg.rectangle("fill",x,y,768,12)
lg.setColor(1,1,1)
printHighlight("[ESC] Toggle keyboard", 0, lk.isDown("escape"), x, y)
lg.setColor(1,1,1)
if uk then
printHighlight("Keystrokes passed to device", 23, false, x, y)
else
printHighlight("[R] "..(run and "Stop" or "Run "), 23, lk.isDown("r"), x, y)
printHighlight("[T] Tick once", 33, lk.isDown("t"), x, y)
printHighlight("[S] Step once", 48, lk.isDown("s"), x, y)
printHighlight("[Q] Quit", 63, lk.isDown("q"), x, y)
end
end
local GPIO = {}
local function InitGPIO(gpio)
gpio.mulLeft = 0
gpio.mulRight = 0
gpio.divLeft = 0
gpio.divRight = 0
gpio.intQueued = false
end
local function UpdateGPIO(gpio, cpu, mem)
if gpio.intQueued then
gpio.intQueued = false
CPURequestInterrupt(cpu)
end
end
local function gpioSetValue(name, func)
return function(addr, cpu, mem, gpio)
gpio[name] = ReadMemory(mem, addr)
func(addr, cpu, mem, gpio)
end
end
local function gpioMul(addr, cpu, mem, gpio)
local base = math.floor(addr/256)*256
local res = gpio.mulLeft*gpio.mulRight
WriteMemory(mem, base+0x00, math.floor(res/256))
WriteMemory(mem, base+0x01, res%256)
end
local function gpioDiv(addr, cpu, mem, gpio)
local base = math.floor(addr/256)*256
WriteMemory(mem, base+0x02, math.floor(gpio.divLeft/gpio.divRight))
WriteMemory(mem, base+0x03, gpio.divLeft%gpio.divRight)
end
local gpioFunctions = {
[0x00] = gpioSetValue("mulLeft" , gpioMul),
[0x01] = gpioSetValue("mulRight", gpioMul),
[0x02] = gpioSetValue("divLeft" , gpioDiv),
[0x03] = gpioSetValue("divRight", gpioDiv),
[0x04] = function(addr, cpu, mem, gpio) WriteMemory(mem, addr, gpioPopcount(readMemory(mem, addr))) end,
[0x05] = function(addr, cpu, mem, gpio) gpio.intQueued = true; WriteMemory(mem, addr, 0); end
}
local function GPIOOnWrite(addr, cpu, mem, gpio)
local offset = addr%256
local func = gpioFunctions[offset]
if func then
func(addr, cpu, mem, gpio)
end
end
local peripherals = {
CharDisplay = { range = {0x0800, 0x0FFF}, write = true },
@ -371,6 +439,9 @@ local peripherals = {
onread = function(addr, cpu, mem) KeyboardOnRead (addr, cpu, mem, Keyboard) end,
onwrite = function(addr, cpu, mem) KeyboardOnWrite(addr, cpu, mem, Keyboard) end,
},
GPIO = { range = {0x0400, 0x04FF}, write = true,
onwrite = function(addr, cpu, mem) GPIOOnWrite(addr, cpu, mem, GPIO) end,
},
}
----
@ -413,7 +484,7 @@ end
ReadMemory = function(mem, addr)
return mem.c.data[addr%65536]%256
end
local function WriteMemory(mem, addr, val)
WriteMemory = function(mem, addr, val)
if mem.c.canwrite[addr%65536]~=0 then
mem.c.data[addr%65536] = val%256
end
@ -445,21 +516,22 @@ struct CPU {
int irq;
int ifg;
int rfg;
int ien;
int instr;
int cycle;
int instrpre;
int frame;
};
int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs);
int TickCPU(struct CPU* const cpu, struct Memory* const mem, const int count, const int countinstrs, const int breakaddr);
]]
local CPU = {
c = ffi.new("struct CPU"),
}
local cpuDll = ffi.load("8608emulator.dll")
local function TickCPU(cpu, mem, count, countinstrs)
local function TickCPU(cpu, mem, count, countinstrs, breakaddr)
local countleft = count
while countleft>0 do
countleft = cpuDll.TickCPU(cpu.c, mem.c, countleft, countinstrs and 1 or 0)
countleft = cpuDll.TickCPU(cpu.c, mem.c, countleft, countinstrs and 1 or 0, breakaddr or 0xFFFFFFFF)
handleEvents(cpu, mem)
end
end
@ -470,6 +542,10 @@ CPURequestInterrupt = function(cpu)
cpu.c.irq = 1;
end
function RunToNextInstr(cpu)
end
----
local function RedrawVideoDisplay(vd, mem)
@ -497,9 +573,11 @@ local function RedrawCharDisplay(cd, mem)
local abase = cy*cd.cols + cx
local achar = cd.addrChar + abase
local acolor = cd.addrColor + abase
local colorid = ReadMemory(mem, acolor)%64
local colormem = ReadMemory(mem, acolor)
local colorid = colormem%64
local highlight = colormem>=128
lg.setColor(ColorSet[colorid])
if cd.highlight[a] then
if highlight then
lg.rectangle("fill", cd.scrX + cx*cd.fontWidth, cd.scrY + cy*cd.fontHeight, cd.fontWidth, cd.fontHeight)
lg.setColor(0, 0, 0)
end
@ -524,7 +602,7 @@ local function InitWindowCanvas()
lg.setFont(InfoFont)
lg.print("8608 CPU Emulator", 4, 4)
end
local function RedrawWindow()
local function RedrawWindow(usekeyboard, runcpu)
lg.setCanvas(WindowCanvas)
lg.setFont(InfoFont)
RedrawCharDisplay(CharDisplay, Memory)
@ -534,6 +612,7 @@ local function RedrawWindow()
RedrawProgramDisplay(ProgramDisplay, CPU, Memory)
for _, md in ipairs(MemoryDisplays) do RedrawMemoryDisplay(md, CPU, Memory) end
RedrawFPSCounter(128+32, 4)
RedrawKeyInfo(128+32+64+16, 4, usekeyboard, runcpu)
lg.setCanvas()
end
@ -547,6 +626,7 @@ function love.load()
InitMemory(Memory, peripherals)
InitWindowCanvas()
InitCPU(CPU)
InitGPIO(GPIO)
--InitVideoDisplay(VideoDisplay)
InitCharDisplay(CharDisplay)
InitRegDisplay(RegDisplay)
@ -560,24 +640,38 @@ end
local RunCPU = false
local CPUSpeed = 4999
local UseKeyboard = false
function love.draw()
UpdateGPIO(GPIO, CPU, Memory)
CPU.c.frame = CPU.c.frame + 1
if RunCPU then
TickCPU(CPU, Memory, CPUSpeed, false)
TickCPU(CPU, Memory, CPUSpeed, false, nil)
end
RedrawWindow()
RedrawWindow(UseKeyboard, RunCPU)
lg.setColor(1,1,1)
lg.draw(WindowCanvas, 0, 0, 0, 2, 2)
lg.print(CPU.c.frame)
end
function love.keypressed(k)
if k=="escape" then le.quit()
elseif k=="t" then TickCPU(CPU, Memory, 1, true )
elseif k=="e" then TickCPU(CPU, Memory, 1, false)
elseif k=="r" then RunCPU = not RunCPU
elseif k=="i" then CPU.c.irq = 1
else KeyboardOnKey(Keyboard, k, true, CPU, Memory)
if k=="escape" then
UseKeyboard = not UseKeyboard
else
if UseKeyboard then
KeyboardOnKey(Keyboard, k, true, CPU, Memory)
else
if k=="q" then le.quit()
elseif k=="s" then TickCPU(CPU, Memory, 1, true , nil)
elseif k=="t" then TickCPU(CPU, Memory, 1, false, nil)
elseif k=="o" then RunToNextInstr(cpu)
elseif k=="r" then RunCPU = not RunCPU
elseif k=="i" then CPU.c.irq = 1
end
end
end
end
function love.keyreleased(k)
if k~="escape" and UseKeyboard then KeyboardOnKey(Keyboard, k, false, CPU, Memory) end
end

View File

@ -1,6 +1,6 @@
// Auto-generated by gendefs.lua
void cpu_instr_0_0(struct CPU* const cpu, struct Memory* const mem) { cpu->a=0; cpu->b=0; cpu->c=0; cpu->u=0; cpu->t=0; cpu->p=0; cpu->q=0; cpu->s=0; cpu->v=0; cpu->i=0; cpu->cf=0; cpu->nz=0; cpu->irq=0; cpu->ifg=0; cpu->rfg=1; lni; }
void cpu_instr_0_0(struct CPU* const cpu, struct Memory* const mem) { cpu->a=0; cpu->b=0; cpu->c=0; cpu->u=0; cpu->t=0; cpu->p=0; cpu->q=0; cpu->s=0; cpu->v=0; cpu->i=0; cpu->cf=0; cpu->nz=0; cpu->irq=0; cpu->ifg=0; cpu->rfg=1; cpu->ien=0; lni; }
void cpu_instr_16_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a, 1 ); lni; }
void cpu_instr_17_0(struct CPU* const cpu, struct Memory* const mem) { addf(cpu->a,-1 ); lni; }
void cpu_instr_18_0(struct CPU* const cpu, struct Memory* const mem) { cpu->p++; lni; }
@ -73,9 +73,9 @@ void cpu_instr_51_1(struct CPU* const cpu, struct Memory* const mem) { if(!cpu->
void cpu_instr_52_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_52_1(struct CPU* const cpu, struct Memory* const mem) { if( cpu->cf ) { jmprelt } else { lni } }
void cpu_instr_53_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_53_1(struct CPU* const cpu, struct Memory* const mem) { if( cpu->nz && cpu->cf) { jmprelt } else { lni } }
void cpu_instr_53_1(struct CPU* const cpu, struct Memory* const mem) { if(cpu->nz && (!cpu->cf)) { jmprelt } else { lni } }
void cpu_instr_54_0(struct CPU* const cpu, struct Memory* const mem) { loadimmedt cpu->cycle++; }
void cpu_instr_54_1(struct CPU* const cpu, struct Memory* const mem) { if(!cpu->nz && !cpu->cf) { jmprelt } else { lni } }
void cpu_instr_54_1(struct CPU* const cpu, struct Memory* const mem) { if((!cpu->nz) || cpu->cf) { jmprelt } else { lni } }
void cpu_instr_55_0(struct CPU* const cpu, struct Memory* const mem) { cpu->b=lobyte(cpu->p); lni; }
void cpu_instr_56_0(struct CPU* const cpu, struct Memory* const mem) { cpu->c=hibyte(cpu->p); lni; }
void cpu_instr_57_0(struct CPU* const cpu, struct Memory* const mem) { cpu->b=lobyte(cpu->q); lni; }
@ -445,6 +445,8 @@ void cpu_instr_241_0(struct CPU* const cpu, struct Memory* const mem) { cpu->rfg
void cpu_instr_242_0(struct CPU* const cpu, struct Memory* const mem) { cpu->irq=0; cpu->ifg=1; int t=cpu->i; cpu->i=cpu->v; cpu->v=(t-1)%65536; lni; }
void cpu_instr_243_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ifg=1; int t=cpu->i; cpu->i=cpu->v; cpu->v=t; lni; }
void cpu_instr_244_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ifg=0; int t=cpu->i; cpu->i=cpu->v; cpu->v=t; lni; }
void cpu_instr_245_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ien=1; lni; }
void cpu_instr_246_0(struct CPU* const cpu, struct Memory* const mem) { cpu->ien=0; lni; }
void cpu_instr_255_0(struct CPU* const cpu, struct Memory* const mem) { lni; }
CPUInstruction CPUInstructions[256][8] = {
@ -693,8 +695,8 @@ CPUInstruction CPUInstructions[256][8] = {
{cpu_instr_242_0,0,0,0,0,0,0,0},
{cpu_instr_243_0,0,0,0,0,0,0,0},
{cpu_instr_244_0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{cpu_instr_245_0,0,0,0,0,0,0,0},
{cpu_instr_246_0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},

View File

@ -18,6 +18,7 @@ return {
["="] = 25,
[","] = 26,
["."] = 27,
["-"] = 28,
["/"] = 29,
["`"] = 30,