IR: support %align in code chunks, and load/store FAC0/FAC1

This commit is contained in:
Irmen de Jong 2024-12-24 16:46:31 +01:00
parent c86c0912f8
commit 49959af752
6 changed files with 31 additions and 8 deletions

View File

@ -627,7 +627,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
RegisterOrPair.AX -> addInstr(result, IRInstruction(Opcode.STOREHAX, IRDataType.WORD, reg1=tr.resultReg), null)
RegisterOrPair.AY -> addInstr(result, IRInstruction(Opcode.STOREHAY, IRDataType.WORD, reg1=tr.resultReg), null)
RegisterOrPair.XY -> addInstr(result, IRInstruction(Opcode.STOREHXY, IRDataType.WORD, reg1=tr.resultReg), null)
RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> TODO("floating point register parameters not supported")
RegisterOrPair.FAC1 -> addInstr(result, IRInstruction(Opcode.STOREHFACZERO, IRDataType.FLOAT, fpReg1 = tr.resultFpReg), null)
RegisterOrPair.FAC2 -> addInstr(result, IRInstruction(Opcode.STOREHFACONE, IRDataType.FLOAT, fpReg1 = tr.resultFpReg), null)
in Cx16VirtualRegisters -> {
addInstr(result, IRInstruction(Opcode.STOREM, paramDt, reg1=tr.resultReg, labelSymbol = "cx16.${parameter.register.registerOrPair.toString().lowercase()}"), null)
}

View File

@ -231,7 +231,11 @@ class IRCodeGen(
chunk += IRInstruction(Opcode.BREAKPOINT)
listOf(chunk)
}
is PtAlign -> TODO("ir support for inline %align")
is PtAlign -> {
val chunk = IRCodeChunk(null, null)
chunk += IRInstruction(Opcode.ALIGN, immediate = node.align.toInt())
listOf(chunk)
}
is PtConditionalBranch -> translate(node)
is PtInlineAssembly -> listOf(IRInlineAsmChunk(null, node.assembly, node.isIR, null))
is PtIncludeBinary -> listOf(IRInlineBinaryChunk(null, readBinaryData(node), null))

View File

@ -58,9 +58,7 @@ IR/VM
- fix TODO("IR rol/ror on split words array")
- fix "<< in array" / ">> in array"
- implement missing operators in AssignmentGen (array shifts etc)
- support %align on code chunks
- fix call() return value handling
- fix float register parameters (FAC1,FAC2) for extsubs, search for TODO("floating point register parameters not supported")
- proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
- make it possible to jump and branch to a computed address (expression) in all cases, see TODO("JUMP to expression address"
- idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)

View File

@ -47,6 +47,8 @@ loadhy reg1 - load cpu hardware register Y into reg1.b
loadhax reg1 - load cpu hardware register pair AX into reg1.w
loadhay reg1 - load cpu hardware register pair AY into reg1.w
loadhxy reg1 - load cpu hardware register pair XY into reg1.w
loadfaczero fpreg1 - load "cpu hardware register" fac0 into freg1.f
loadfacone fpreg1 - load "cpu hardware register" fac1 into freg1.f
storem reg1, address - store reg1 at memory address
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2 (only the lsb part used for indexing)
@ -60,6 +62,8 @@ storehy reg1 - store reg1.b into cpu hardware register
storehax reg1 - store reg1.w into cpu hardware register pair AX
storehay reg1 - store reg1.w into cpu hardware register pair AY
storehxy reg1 - store reg1.w into cpu hardware register pair XY
storehfaczero fpreg1 - store fpreg1.f into "cpu register" fac0
storehfacone fpreg1 - store fpreg1.f into "cpu register" fac1
CONTROL FLOW
@ -246,6 +250,7 @@ cli - clear interrupt disable flag
sei - set interrupt disable flag
nop - do nothing
breakpoint - trigger a breakpoint
align alignmentvalue - represents a memory alignment directive
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
concat [b, w] reg1, reg2, reg3 - reg1.w = 'concatenate' two registers: lsb/lsw of reg2 (as msb) and lsb/lsw of reg3 (as lsb) into word or int (int not yet implemented; requires 32bits regs)
push [b, w, f] reg1 - push value in reg1 on the stack
@ -268,6 +273,8 @@ enum class Opcode {
LOADHAX,
LOADHAY,
LOADHXY,
LOADHFACZERO,
LOADHFACONE,
STOREM,
STOREI,
STOREX,
@ -281,6 +288,8 @@ enum class Opcode {
STOREHAX,
STOREHAY,
STOREHXY,
STOREHFACZERO,
STOREHFACONE,
JUMP,
JUMPI,
@ -423,7 +432,8 @@ enum class Opcode {
POPST,
MSIG,
CONCAT,
BREAKPOINT
BREAKPOINT,
ALIGN
}
val OpcodesThatJump = arrayOf(
@ -630,6 +640,8 @@ val instructionFormats = mutableMapOf(
Opcode.LOADHAX to InstructionFormat.from("W,>r1"),
Opcode.LOADHAY to InstructionFormat.from("W,>r1"),
Opcode.LOADHXY to InstructionFormat.from("W,>r1"),
Opcode.LOADHFACZERO to InstructionFormat.from("F,>fr1"),
Opcode.LOADHFACONE to InstructionFormat.from("F,>fr1"),
Opcode.STOREM to InstructionFormat.from("BW,<r1,>a | F,<fr1,>a"),
Opcode.STOREI to InstructionFormat.from("BW,<r1,<r2 | F,<fr1,<r1"),
Opcode.STOREX to InstructionFormat.from("BW,<r1,<r2,>a | F,<fr1,<r1,>a"),
@ -644,6 +656,8 @@ val instructionFormats = mutableMapOf(
Opcode.STOREHAX to InstructionFormat.from("W,<r1"),
Opcode.STOREHAY to InstructionFormat.from("W,<r1"),
Opcode.STOREHXY to InstructionFormat.from("W,<r1"),
Opcode.STOREHFACZERO to InstructionFormat.from("F,<fr1"),
Opcode.STOREHFACONE to InstructionFormat.from("F,<fr1"),
Opcode.JUMP to InstructionFormat.from("N,<a"),
Opcode.JUMPI to InstructionFormat.from("N,<r1"),
Opcode.PREPARECALL to InstructionFormat.from("N,<i"),
@ -783,6 +797,7 @@ val instructionFormats = mutableMapOf(
Opcode.CLI to InstructionFormat.from("N"),
Opcode.SEI to InstructionFormat.from("N"),
Opcode.BREAKPOINT to InstructionFormat.from("N"),
Opcode.ALIGN to InstructionFormat.from("N,<i"),
)

View File

@ -256,7 +256,7 @@ private class ParsedCall(
private fun parseCall(rest: String): ParsedCall {
fun parseRegspec(reg: String): FunctionCallArgs.RegSpec {
val pattern = Regex("f?r([0-9]+)\\.(.)(@.{1,2})?$")
val pattern = Regex("f?r([0-9]+)\\.(.)(@.{1,4})?$")
val match = pattern.matchEntire(reg) ?: throw IRParseException("invalid regspec $reg")
val num = match.groups[1]!!.value.toInt()
val type = when(match.groups[2]!!.value) {

View File

@ -191,7 +191,9 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.LOADHY,
Opcode.LOADHAX,
Opcode.LOADHAY,
Opcode.LOADHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
Opcode.LOADHXY,
Opcode.LOADHFACZERO,
Opcode.LOADHFACONE -> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
Opcode.STOREM -> InsSTOREM(ins)
Opcode.STOREX -> InsSTOREX(ins)
Opcode.STOREIX -> InsSTOREIX(ins)
@ -204,7 +206,9 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.STOREHY,
Opcode.STOREHAX,
Opcode.STOREHAY,
Opcode.STOREHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
Opcode.STOREHXY,
Opcode.STOREHFACZERO,
Opcode.STOREHFACONE-> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
Opcode.JUMP -> InsJUMP(ins)
Opcode.JUMPI -> InsJUMPI(ins)
Opcode.PREPARECALL -> nextPc()
@ -341,6 +345,7 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.FFLOOR -> InsFFLOOR(ins)
Opcode.FCEIL -> InsFCEIL(ins)
Opcode.FCOMP -> InsFCOMP(ins)
Opcode.ALIGN -> nextPc() // actual alignment ignored in the VM
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
}