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,

View File

@ -6,6 +6,8 @@ run F1 1 Resume non-interrupt execution
brk F3 1 Trigger interrupt
irt F4 1 Return from interrupt
nop FF 1 Do nothing
ien F5 1 Enbale interrupts
idi F6 1 Disable interrupts
16-bit Inc/Dec (I):
inc p 12 1 P++
@ -127,8 +129,8 @@ rts E1 3 I=*(----S)+1
jpr imm8 31 2 I+=imm8
jnz imm8 30 2 I+=imm8 if !Zero
jpz imm8 32 2 I+=imm8 if Zero
jlt imm8 33 2 I+=imm8 if !Carry
jge imm8 34 2 I+=imm8 if Carry
jge imm8 33 2 I+=imm8 if !Carry
jlt imm8 34 2 I+=imm8 if Carry
jgt imm8 35 2 I+=imm8 if !Zero & Carry
jle imm8 36 2 I+=imm8 if Zero | !Carry
@ -238,7 +240,7 @@ ldq p 8E 1 Q=P
lds p 8F 1 S=P
ldv p 90 1 V=P
Opcodes used: 226/255
Opcodes used: 228/255
0123456789ABCDEF
00 | C---------------
10 | UUIIUIIUUUUUUUUU
@ -255,4 +257,4 @@ B0 | AAAAAAAAAAAAAAAA
C0 | BBBBBBBBBBBBWWWW
D0 | AAAAAAAAAAAAAAAA
E0 | MJJJJJXXXSS-----
F0 | CCCCC----------C
F0 | CCCCCCC--------C

View File

@ -1,5 +1,7 @@
8608
8608 - an 8-bit data, 16-bit address, CISC architecture.
For a list of instructions, see instructionList.txt
How to use the assembler:
1. Install bllua3 from https://notabug.org/redo/bllua3
@ -11,4 +13,6 @@ How to use the assembler:
You can also run the assembler from the command line to get a memory dump and disassembly in stdout, if you have lua installed:
luajit "your_path/assembler-8608.lua" "other_path/filename.asm"
For a list of instructions, see instructionList.txt
How to use the emulator:
1. Install love2d from https://love2d.org
2. Open a command prompt in the "emulator" folder and run "love . C:/path/filename.asm"

View File

@ -130,13 +130,15 @@ operations = {
instructions = {
{ category = "Control", catlet="C" },
{ mnem="rst" , opcode=0x00, {"base","intFlgClk","irqFlgClk","runFlgClk","runFlgVal","clearRegs","loadInstr"}, desc="Clear all registers and set I=0", ccode={"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;"} },
{ mnem="rst" , opcode=0x00, {"base","intFlgClk","irqFlgClk","runFlgClk","runFlgVal","clearRegs","loadInstr"}, desc="Clear all registers and set I=0", ccode={"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;"} },
{ mnem="hlt" , opcode=0xF0, {"runFlgClk","instrNext"}, desc="Halt non-interrupt execution", ccode={"cpu.rfg=0; lni;"} },
{ mnem="run" , opcode=0xF1, {"runFlgClk","runFlgVal","instrNext"}, desc ="Resume non-interrupt execution", ccode={"cpu.rfg=1; lni;"} },
{ mnem="int" , opcode=0xF2, {"instrSwapIV","intFlgVal","intFlgClk","irqFlgClk"}, ccode={"cpu.irq=0; cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=(t-1)%65536; lni;"} },
{ mnem="brk" , opcode=0xF3, {"instrSwapIV","adwInc","intFlgVal","intFlgClk"}, desc="Trigger interrupt", ccode={"cpu.ifg=1; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} },
{ mnem="irt" , opcode=0xF4, {"instrSwapIV","adwInc","intFlgClk"}, desc="Return from interrupt", ccode={"cpu.ifg=0; int t=cpu.i; cpu.i=cpu.v; cpu.v=t; lni;"} },
{ mnem="nop" , opcode=0xFF, {"instrNext"}, desc="Do nothing", ccode={"lni;"}, },
{ mnem="ien" , opcode=0xF5, {"instrNext"}, desc="Enbale interrupts", ccode={"cpu.ien=1; lni;"}, },
{ mnem="idi" , opcode=0xF6, {"instrNext"}, desc="Disable interrupts", ccode={"cpu.ien=0; lni;"}, },
{ category = "16-bit Inc/Dec", catlet="I" },
{ mnem="inc p" , opcode=0x12, {"adwlP","adwInc","adwSaveP","instrNext"}, desc="P++", ccode={"cpu.p++; lni;"} },
@ -258,10 +260,10 @@ instructions = {
{ mnem="jpr imm8" , opcode=0x31, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub1"}, {"jmpRelT"}, desc="I+=imm8", ccode={"loadimmedt","jmprelt"} },
{ mnem="jnz imm8" , opcode=0x30, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NZ" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Zero" , ccode={"loadimmedt","if( cpu.nz ) { jmprelt } else { lni }"} },
{ mnem="jpz imm8" , opcode=0x32, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0Z" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero" , ccode={"loadimmedt","if(!cpu.nz ) { jmprelt } else { lni }"} },
{ mnem="jlt imm8" , opcode=0x33, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" , ccode={"loadimmedt","if(!cpu.cf ) { jmprelt } else { lni }"} },
{ mnem="jge imm8" , opcode=0x34, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" , ccode={"loadimmedt","if( cpu.cf ) { jmprelt } else { lni }"} },
{ mnem="jgt imm8" , opcode=0x35, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero & Carry", ccode={"loadimmedt","if( cpu.nz && cpu.cf) { jmprelt } else { lni }"} },
{ mnem="jle imm8" , opcode=0x36, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero | !Carry", ccode={"loadimmedt","if(!cpu.nz && !cpu.cf) { jmprelt } else { lni }"} },
{ mnem="jge imm8" , opcode=0x33, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0NC" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if !Carry" , ccode={"loadimmedt","if(!cpu.cf ) { jmprelt } else { lni }"} },
{ mnem="jlt imm8" , opcode=0x34, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C" }, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Carry" , ccode={"loadimmedt","if( cpu.cf ) { jmprelt } else { lni }"} },
{ mnem="jgt imm8" , opcode=0x35, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"jmpRelT"}, {"instrNext"}, desc="I+=imm8 if !Zero & Carry", ccode={"loadimmedt","if(cpu.nz && (!cpu.cf)) { jmprelt } else { lni }"} },
{ mnem="jle imm8" , opcode=0x36, jmp=true, rel=true, ncycles=2, {"loadImmed","memSaveT","instrSub23Cond","instrNext0C","instrNext0Z"}, {}, {"instrNext"}, {"jmpRelT"}, desc="I+=imm8 if Zero | !Carry", ccode={"loadimmedt","if((!cpu.nz) || cpu.cf) { jmprelt } else { lni }"} },
{ category = "Stack", catlet="S" },
{ mnem="psh a" , opcode=0x40, {"pushReg","alurA","instrSub1"}, {"instrNext"}, desc="*(S++)=A", ccode={"pushbyte(cpu.a);","lni;"} },