8608/8608-definition.lua
2024-08-11 02:39:37 -06:00

252 lines
11 KiB
Lua

-- 8608-definition.lua
-- This file contains information about the instruction set and microcode for the 8608 architecture.
-- It is used by generate-architecture.lua, alongside the instruction definitions in 8608-instructions.lua, to generate the following:
-- instructionList.txt, a human-readable list of all instructions.
-- 8608.asm, a set of definitions for CustomAsm that allows it to assemble 8608 programs.
-- The microcode ROM data, which is built into the physical CPU to control it.
local arch8608 = {
-- List of every control line in the CPU
-- Organized by bit position within the four microcode ROMs
roms = {
{ pos = {0, 0, 0}, size = {64, 16, 64}, signals = {
"alulU", "alulT", "alulC", "alulB", "alulA", "alurIL", "alurIH", "alurVL",
"alurVH", "alurSL", "alurSH", "alurQL", "alurQH", "alurPL", "alurPH", "alurU",
"alurT", "alurC", "alurB", "alurA", "alur1", "alur2", "alurm1", "alurm2",
"adrrhU", "adrrhC", "adrrlT", "adrrTX", "_", "adrr2A", "adwrhU", "adwrhC",
"adwrlT", "adwrTX", "adwrlA", "adwrAX", "adwlI", "adwlV", "adwlS", "adwlQ",
"adwlP", "adrlI", "adrlV", "adrlS", "adrlQ", "adrlP", "aluAdd", "adwSaveV",
"aluRun", "aluRInv", "aluCinOn", "aluCinC", "memWriteAlur", "adrInc", "adwInc", "aluXor",
"aluIor", "aluAnd", "memWriteAlur", "adrOut", "adrSaveI", "adwSaveP", "adwSaveQ", "adwSaveS",
} },
{ pos = {-34, 16, 0}, size = {32, 32, 8}, signals = {
"aluSaveU", "aluSaveT", "aluSaveC", "aluSaveB", "aluSaveA", "aluSaveCarry", "aluSaveNZ", "always1",
} },
{ pos = {-34, 16, 17}, size = {32, 32, 32}, signals = {
"_", "_", "_", "_", "_", "_", "_", "_",
"_", "memSaveF", "memSaveNZ", "instrPre", "instrLoadPre", "always1", "instrLoadSel", "adrOut",
"memWriteAlur", "memSave", "instrNext0NZ", "instrNext0Z", "instrNext0NC", "instrNext0C", "instrLoadSub", "instrLoad",
"instrNext2", "instrNext1", "instrNext0", "memSaveU", "memSaveT", "memSaveC", "memSaveB", "memSaveA",
} },
{ pos = {66, 16, 0}, size = {32, 32, 32}, signals = {
"adrr1", "adrrm1", "adrrm4", "adrr2", "adwrm1", "adwrm2", "adwr2", "adwr1",
"memRead", "memWrite", "runFlgVal", "runFlgClk", "intFlgVal", "intFlgClk", "irqFlgClk", "always1",
"aluShiftArith", "aluShiftRoll", "aluShiftRight", "aluShift", "alurF", "_", "_", "_",
"_", "_", "_", "_", "_", "_", "_", "_",
} },
},
-- Macro operations
-- These can be used as a shortcut to convey that multiple control lines should be set
-- Macro definitions may contain other macros
operations = {
base = {"always1"},
instrNext = {"base","adrlI","adrInc","adrSaveI","loadInstr"},
instrSub1 = {"base","instrLoadSub", "instrNext0"},
instrSub2 = {"base","instrLoadSub", "instrNext1", },
instrSub3 = {"base","instrLoadSub", "instrNext1","instrNext0"},
instrSub4 = {"base","instrLoadSub","instrNext2", },
instrSub5 = {"base","instrLoadSub","instrNext2", "instrNext0"},
instrSub6 = {"base","instrLoadSub","instrNext2","instrNext1", },
instrSub7 = {"base","instrLoadSub","instrNext2","instrNext1","instrNext0"},
instrSub23Cond = {"base","instrLoadSub","instrNext1"},
-- instrSwapIV = {"base","adwlI","adwSaveV","adrlV","adrSaveI","loadInstr"},
instrPreload = {"adrlI","adrInc","adrSaveI","adrOut","memRead","instrLoadSel","instrLoadPre"},
instrNextPre = {"base","instrPre","instrLoad","instrLoadSub"},
loadInstr = {"adrOut","memRead","instrLoadSel","instrLoad","instrLoadSub"},
loadReg = {"adrOut","memRead","memSave"},
storeReg = {"adrOut","memWrite","memWriteAlur"},
loadRegT = {"loadReg","memSaveT"},
pushReg = {"storeReg","adrlS","adwlS","adwInc","adwSaveS"},
popReg = {"loadReg","adrlS","adrrm1","adwlS","adwrm1","adwSaveS"},
pop161 = {"popReg","memSaveT"},
pop162 = {"popReg","memSaveU"},
loadImmed = {"adrlI","adrInc","adrSaveI","loadReg"},
loadImmedT = {"loadImmed","memSaveT"},
loadImm161 = {"loadImmed","memSaveU"},
loadImm162 = {"loadImmed","memSaveT"},
--loadStackRel = {"adrlS","adrrTX","loadReg"},
loadStackRel = {"adrrlT","loadReg"},
loadStackRelT = {"loadStackRel","memSaveT"},
loadStackRelU = {"loadStackRel","memSaveU"},
loadStackRel161 = {"loadStackRel", "memSaveU"},
loadStackRel162 = {"loadStackRel","adrInc","memSaveT"},
--storeStackRel = {"adrlS","adrrTX","storeReg"},
storeStackRel = {"adrrlT","storeReg"},
storeStackRel161 = {"storeStackRel" },
storeStackRel162 = {"storeStackRel","adrInc"},
storeStackRelU = {"storeStackRel","alurU"},
load161 = { "loadReg","memSaveU"},
load162 = {"adrInc","loadReg","memSaveT"},
store161 = { "storeReg"},
store162 = {"adrInc","storeReg"},
loadUTU = {"adrrUT", "loadReg","memSaveU"},
storeUT = {"adrrUT", "storeReg"},
storeUTP = {"adrrUT","adrlP","storeReg"},
storeUTQ = {"adrrUT","adrlQ","storeReg"},
memSaveFlags = {"memSaveNZ"},
load16FE1 = {"adrrm4","adrr2","load161"},
load16FE2 = {"adrrm4","adrr2","load162"},
load16FC1 = {"adrrm4", "load161"},
load16FC2 = {"adrrm4", "load162"},
adwrUT = {"adwrhU","adwrlT"},
adrrUT = {"adrrhU","adrrlT"},
-- adwrCB = {"adwrhC","adwrlB"},
adwIncUT = {"adwrUT", "adwInc"},
adwIncUTP = {"adwrUT","adwlP","adwInc"},
adwIncUTQ = {"adwrUT","adwlQ","adwInc"},
adwP = {"adwlP","adwSaveP"},
adwQ = {"adwlQ","adwSaveQ"},
adwS = {"adwlS","adwSaveS"},
incP = {"adwP","adwInc"},
incQ = {"adwQ","adwInc"},
incP2 = {"adwP","adwr2"},
incQ2 = {"adwP","adwr2"},
saveIV = {"adwlI","adwSaveV"},
jmpRelT = {"instrNext","adrrTX"},
jmpAbs = {"base","loadInstr","adrSaveI"},
jmpAbsUT = {"jmpAbs","adrrUT"},
jmpAbsP = {"jmpAbs","adrlP"},
jmpAbsQ = {"jmpAbs","adrlQ"},
jmpAbsV = {"jmpAbs","adrlV"},
saveRetAddr = {"adwlI","adwInc","adwSaveQ"},
pushRetAddr1 = {"alurIH","pushReg"},
pushRetAddr2 = {"alurIL","pushReg"},
aluA = {"alulA","aluSaveA"},
aluB = {"alulB","aluSaveB"},
aluC = {"alulC","aluSaveC"},
aluT = {"alulT","aluSaveT"},
aluU = {"alulU","aluSaveU"},
aluOpAdd = {"aluRun","aluAdd","aluSaveCarry","aluSaveNZ" },
aluOpAddC= {"aluRun","aluAdd","aluSaveCarry","aluSaveNZ", "aluCinC" },
aluOpSub = {"aluRun","aluAdd","aluSaveCarry","aluSaveNZ","aluRInv","aluCinOn"},
aluOpSubC= {"aluRun","aluAdd","aluSaveCarry","aluSaveNZ","aluRInv","aluCinC" },
aluOpAnd = {"aluRun","aluAnd" , "aluSaveNZ"},
aluOpIor = {"aluRun","aluIor" , "aluSaveNZ"},
aluOpXor = {"aluRun","aluXor" , "aluSaveNZ"},
aluOpCmp = {"aluOpSub"},
aluOpInc = {"aluOpAdd","aluCinOn"},
aluOpDec = {"aluOpAdd","aluRInv"},
aluOpMov = {"aluAdd","aluSaveNZ"},
aluOpShl = {"aluRun", "aluShift" ,"aluSaveNZ"},
aluOpShr = {"aluRun", "aluShift","aluShiftRight" ,"aluSaveNZ"},
aluOpRol = {"aluRun", "aluShift", "aluShiftRoll" ,"aluSaveNZ"},
aluOpRor = {"aluRun", "aluShift","aluShiftRight","aluShiftRoll" ,"aluSaveNZ"},
aluOpSra = {"aluRun", "aluShift","aluShiftRight", "aluShiftArith","aluSaveNZ"},
clearRegs = {
"aluSaveA","aluSaveB","aluSaveC","aluSaveU","aluSaveT",
"adwSaveP","adwSaveQ","adwSaveS","adwSaveV",
"adrSaveI",
"aluSaveNZ","aluSaveCarry",
"intFlgClk",
"irqFlgClk",
"runFlgClk","runFlgVal",
},
},
-- Shortcuts for instruction descriptions
-- These strings will be substituted into instruction descriptions wherever their [key] occurs
descShortcuts = {
{"%mem", "a value from memory"},
{"%mem16", "a value from memory"},
{"%imm8", "a given 8-bit value"},
{"%imm16", "a given 16-bit value"},
{"%A", "the value in the A register"},
{"%B", "the value in the B register"},
{"%C", "the value in the C register"},
{"%xInc16", "increment the X register by 2 bytes"},
{"%yInc16", "increment the Y register by 2 bytes"},
{"%xInc", "increment the X register"},
{"%yInc", "increment the Y register"},
{"%Xin16", "the 16-bit value in memory at the address in X"},
{"%Yinn16", "the 16-bit value in memory at the address in Y"},
{"%xIn", "the value in memory at the address in X"},
{"%yIn", "the value in memory at the address in Y"},
{"%XofsIn16", "the 16-bit value in memory at the address (X plus a given 8-bit offset)"},
{"%YofsIn16", "the 16-bit value in memory at the address (Y plus a given 8-bit offset)"},
{"%XofsIn", "the value in memory at the address (X plus a given 8-bit offset)"},
{"%YofsIn", "the value in memory at the address (Y plus a given 8-bit offset)"},
{"%Xofs", "the address (X plus a given 8-bit offset)"},
{"%Yofs", "the address (Y plus a given 8-bit offset)"},
{"%X", "the 16-bit value in the X register"},
{"%Y", "the 16-bit value in the Y register"},
{"%adrX", "the address in X"},
{"%adrY", "the address in Y"},
{"%zpgIn16", "the 16-bit value in memory at a given 8-bit address"},
{"%zpgIn", "the value in memory at a given 8-bit address"},
{"%zpg", "an given 8-bit address"},
{"%absIn16", "the 16-bit value in memory at a given 16-bit address"},
{"%absIn", "the value in memory at a given 16-bit address"},
{"%abs", "a given 16-bit address"},
{"%alu", "and store the result in the A register"},
{"%flags", " and set the Carry Flag and Zero Flag according to the result"},
{"%zflag", " and set the Zero Flag according to the result"},
{"%cmp", "Set the Carry Flag and Zero Flag according to the result of subtracting"},
{"%brel", "Add a signed 8-bit offset to the Program Counter, jumping forward or backward in the program"},
{"%brelc", "Otherwise, do nothing"},
{"%if", "If the result of the last math operation was"},
{"%zFlgMem", "and set the Zero Flag according to the value loaded"},
},
-- Aliases for instructions
-- Used to generate the assembler definitions.
-- imm8neg instead of imm8 means the immediate value will be negated when assembling.
transformMnemonic = function(mnem)
mnem = mnem:gsub("zpg", "imm8u")
mnem = mnem:gsub("ofs", "imm8u")
mnem = mnem:gsub("rel", "imm8rel")
mnem = mnem:gsub("abs", "imm16")
mnem = mnem:gsub("ind", "imm16")
mnem = mnem:gsub("#", "#imm8")
mnem = mnem:gsub("#imm8#imm8", "#imm16")
return mnem
end,
aliases = {
-- ["jmp q" ] = {"ret" },
["ADD imm8" ] = {"SUB imm8neg"},
-- ["adb imm8" ] = {"sbb imm8neg"},
-- ["adc imm8" ] = {"sbc imm8neg"},
["ADC imm8" ] = {"SBC imm8neg"},
},
-- Filename to generate the assembler definitions file to.
assemblerDefsFile = "8608.asm",
-- Header to be inserted at the top of the assembler definitions file
assemblerDefsHeader = [[
; 8608.asm
; Include this file into a CustomAsm assembly file to use the 8608 architecture, like so:
; #include "8608.asm"
; See CustomAsm for more info: https://github.com/hlorenzi/customasm
; Generated by generate-architecture.lua using the definitions in 8608-definition.lua
; Definitions for all instructions in the 8608 architecture.
]],
-- Filename to generate the instruction listing file to.
instructionListFile = "instructionList.txt",
-- Header to be inserted at the top of the instruction listing file
instructionListHeader = [[
instructionList.txt
List of all instructions in the 8608 architecture.
Instructions are encoded as the opcode, followed by any immediate values.
16-bit immediates are encoded in big-endian byte order.
Each instruction is described in order of: Mnemonic, Opcode, Clock cycles, Description
]],
}
return arch8608