252 lines
11 KiB
Lua
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
|