mirror of
https://github.com/irmen/prog8.git
synced 2024-12-22 18:30:01 +00:00
IR: fix some things related to asmsubs
This commit is contained in:
parent
60244aaf16
commit
66e7c51064
@ -44,7 +44,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
}
|
||||
is PtContainmentCheck -> other is PtContainmentCheck && other.type==type && other.element isSameAs element && other.iterable isSameAs iterable
|
||||
is PtIdentifier -> other is PtIdentifier && other.type==type && other.name==name
|
||||
is PtMachineRegister -> other is PtMachineRegister && other.type==type && other.register==register
|
||||
is PtIrRegister -> other is PtIrRegister && other.type==type && other.register==register
|
||||
is PtMemoryByte -> other is PtMemoryByte && other.address isSameAs address
|
||||
is PtNumber -> other is PtNumber && other.type==type && other.number==number
|
||||
is PtBool -> other is PtBool && other.value==value
|
||||
@ -87,7 +87,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
is PtContainmentCheck -> false
|
||||
is PtFunctionCall -> false
|
||||
is PtIdentifier -> true
|
||||
is PtMachineRegister -> true
|
||||
is PtIrRegister -> true
|
||||
is PtMemoryByte -> address is PtNumber || address is PtIdentifier
|
||||
is PtBool -> true
|
||||
is PtNumber -> true
|
||||
@ -354,7 +354,7 @@ class PtTypeCast(type: DataType, position: Position) : PtExpression(type, positi
|
||||
|
||||
|
||||
// special node that isn't created from compiling user code, but used internally in the Intermediate Code
|
||||
class PtMachineRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position)
|
||||
class PtIrRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position)
|
||||
|
||||
|
||||
fun constValue(expr: PtExpression): Double? = if(expr is PtNumber) expr.number else if(expr is PtBool) expr.asInt().toDouble() else null
|
||||
|
@ -34,7 +34,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
str + node.name + "()"
|
||||
}
|
||||
is PtIdentifier -> "${node.name} ${type(node.type)}"
|
||||
is PtMachineRegister -> "VMREG#${node.register} ${type(node.type)}"
|
||||
is PtIrRegister -> "VMREG#${node.register} ${type(node.type)}"
|
||||
is PtMemoryByte -> "@()"
|
||||
is PtNumber -> {
|
||||
val numstr = if(node.type == DataType.FLOAT) node.number.toString() else node.number.toHex()
|
||||
|
@ -81,7 +81,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
}
|
||||
is PtAddressOf -> false
|
||||
is PtIdentifier -> false
|
||||
is PtMachineRegister -> false
|
||||
is PtIrRegister -> false
|
||||
is PtMemoryByte -> return usesOtherRegistersWhileEvaluating(arg.address)
|
||||
is PtNumber -> false
|
||||
is PtBool -> false
|
||||
|
@ -70,7 +70,7 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
is PtNumber,
|
||||
is PtBool,
|
||||
is PtIdentifier,
|
||||
is PtMachineRegister,
|
||||
is PtIrRegister,
|
||||
is PtArrayIndexer,
|
||||
is PtPrefix,
|
||||
is PtBinaryExpression -> { /* no cmp necessary the lda has been done just prior */ }
|
||||
|
@ -667,7 +667,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
internal fun directIntoY(expr: PtExpression): Boolean {
|
||||
return when(expr) {
|
||||
is PtIdentifier -> true
|
||||
is PtMachineRegister -> true
|
||||
is PtIrRegister -> true
|
||||
is PtNumber -> true
|
||||
is PtBuiltinFunctionCall -> expr.name in arrayOf("lsb", "msb")
|
||||
else -> false
|
||||
|
@ -8,7 +8,7 @@ import prog8.intermediate.*
|
||||
internal class AssignmentGen(private val codeGen: IRCodeGen, private val expressionEval: ExpressionGen) {
|
||||
|
||||
internal fun translate(assignment: PtAssignment): IRCodeChunks {
|
||||
if(assignment.target.children.single() is PtMachineRegister)
|
||||
if(assignment.target.children.single() is PtIrRegister)
|
||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||
|
||||
val chunks = translateRegularAssign(assignment)
|
||||
@ -17,7 +17,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
}
|
||||
|
||||
internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks {
|
||||
if(augAssign.target.children.single() is PtMachineRegister)
|
||||
if(augAssign.target.children.single() is PtIrRegister)
|
||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||
|
||||
val target = augAssign.target
|
||||
@ -270,11 +270,11 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
else
|
||||
throw AssemblyError("assignment value and target dt mismatch")
|
||||
} else false
|
||||
if (assignment.value is PtMachineRegister) {
|
||||
valueRegister = (assignment.value as PtMachineRegister).register
|
||||
if (assignment.value is PtIrRegister) {
|
||||
valueRegister = (assignment.value as PtIrRegister).register
|
||||
if(extendByteToWord) {
|
||||
valueRegister = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister, reg2=(assignment.value as PtMachineRegister).register), null)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister, reg2=(assignment.value as PtIrRegister).register), null)
|
||||
}
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(assignment.value)
|
||||
|
@ -857,7 +857,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val assignTarget = PtAssignTarget(target.position)
|
||||
assignTarget.children.add(target)
|
||||
assignment.children.add(assignTarget)
|
||||
assignment.children.add(PtMachineRegister(register, target.type, target.position))
|
||||
assignment.children.add(PtIrRegister(register, target.type, target.position))
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
result += codeGen.translateNode(assignment)
|
||||
return result
|
||||
|
@ -24,7 +24,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
|
||||
fun translateExpression(expr: PtExpression): ExpressionCodeResult {
|
||||
return when (expr) {
|
||||
is PtMachineRegister -> {
|
||||
is PtIrRegister -> {
|
||||
ExpressionCodeResult(emptyList(), irType(expr.type), expr.register, -1)
|
||||
}
|
||||
is PtBool -> {
|
||||
@ -505,8 +505,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(returnIrType==IRDataType.FLOAT)
|
||||
FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFreeFloat(), returns.register)
|
||||
else {
|
||||
statusFlagResult = returns.register.statusflag
|
||||
val returnRegister = if(statusFlagResult==null) codeGen.registers.nextFree() else -1
|
||||
val returnRegister = codeGen.registers.nextFree()
|
||||
FunctionCallArgs.RegSpec(returnIrType, returnRegister, returns.register)
|
||||
}
|
||||
} else {
|
||||
|
@ -3,16 +3,17 @@
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
str scanline_buf = "?"* 20
|
||||
|
||||
sub start() {
|
||||
if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
bool @shared flag
|
||||
|
||||
if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
cx16.r0L = test(12345, flag, -42)
|
||||
|
||||
if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
}
|
||||
|
||||
asmsub test(uword arg @AY, bool flag @Pc, byte value @X) -> ubyte @A, bool @Pc {
|
||||
%asm {{
|
||||
txa
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ class IRFileReader {
|
||||
private fun parseDatatype(type: String, isArray: Boolean): DataType {
|
||||
if(isArray) {
|
||||
return when(type) {
|
||||
// note: there are no BOOLEANS anymore in the IR. Only UBYTE.
|
||||
// note: there are no BOOLEANS arrays anymore in the IR. Only UBYTE.
|
||||
"byte" -> DataType.ARRAY_B
|
||||
"ubyte", "str" -> DataType.ARRAY_UB
|
||||
"word" -> DataType.ARRAY_W
|
||||
@ -509,7 +509,7 @@ class IRFileReader {
|
||||
}
|
||||
} else {
|
||||
return when(type) {
|
||||
// note: there are no BOOLEANS anymore in the IR. Only UBYTE.
|
||||
"bool" -> DataType.BOOL
|
||||
"byte" -> DataType.BYTE
|
||||
"ubyte" -> DataType.UBYTE
|
||||
"word" -> DataType.WORD
|
||||
|
@ -41,6 +41,12 @@ loadi reg1, reg2 - load reg1 with value at memory indirect,
|
||||
loadx reg1, reg2, address - load reg1 with value at memory address indexed by value in reg2 (only the lsb part used for indexing)
|
||||
loadix reg1, reg2, pointeraddr - load reg1 with value at memory indirect, pointed to by pointeraddr indexed by value in reg2 (only the lsb part used for indexing)
|
||||
loadr reg1, reg2 - load reg1 with value in register reg2
|
||||
loadha reg1 - load cpu hardware register A into reg1.b
|
||||
loadhx reg1 - load cpu hardware register X into reg1.b
|
||||
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
|
||||
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)
|
||||
@ -48,6 +54,12 @@ storeix reg1, reg2, pointeraddr - store reg1 at memory indirect, pointed t
|
||||
storezm address - store zero at memory address
|
||||
storezi reg1 - store zero at memory pointed to by reg1
|
||||
storezx reg1, address - store zero at memory address, indexed by value in reg1 (only the lsb part used for indexing)
|
||||
storeha reg1 - store reg1.b into cpu hardware register A
|
||||
storehx reg1 - store reg1.b into cpu hardware register X
|
||||
storehy reg1 - store reg1.b into cpu hardware register Y
|
||||
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
|
||||
|
||||
|
||||
CONTROL FLOW
|
||||
@ -247,6 +259,12 @@ enum class Opcode {
|
||||
LOADX,
|
||||
LOADIX,
|
||||
LOADR,
|
||||
LOADHA,
|
||||
LOADHX,
|
||||
LOADHY,
|
||||
LOADHAX,
|
||||
LOADHAY,
|
||||
LOADHXY,
|
||||
STOREM,
|
||||
STOREI,
|
||||
STOREX,
|
||||
@ -254,6 +272,12 @@ enum class Opcode {
|
||||
STOREZM,
|
||||
STOREZI,
|
||||
STOREZX,
|
||||
STOREHA,
|
||||
STOREHX,
|
||||
STOREHY,
|
||||
STOREHAX,
|
||||
STOREHAY,
|
||||
STOREHXY,
|
||||
|
||||
JUMP,
|
||||
JUMPI,
|
||||
@ -444,6 +468,12 @@ val OpcodesThatSetStatusbitsButNotCarry = arrayOf(
|
||||
Opcode.LOADX,
|
||||
Opcode.LOADIX,
|
||||
Opcode.LOADR,
|
||||
Opcode.LOADHA,
|
||||
Opcode.LOADHX,
|
||||
Opcode.LOADHY,
|
||||
Opcode.LOADHAX,
|
||||
Opcode.LOADHAY,
|
||||
Opcode.LOADHXY,
|
||||
Opcode.NEG,
|
||||
Opcode.NEGM,
|
||||
Opcode.INC,
|
||||
@ -585,6 +615,13 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.LOADX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
|
||||
Opcode.LOADIX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
|
||||
Opcode.LOADR to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||
Opcode.LOADHA to InstructionFormat.from("B,>r1"),
|
||||
Opcode.LOADHA to InstructionFormat.from("B,>r1"),
|
||||
Opcode.LOADHX to InstructionFormat.from("B,>r1"),
|
||||
Opcode.LOADHY to InstructionFormat.from("B,>r1"),
|
||||
Opcode.LOADHAX to InstructionFormat.from("W,>r1"),
|
||||
Opcode.LOADHAY to InstructionFormat.from("W,>r1"),
|
||||
Opcode.LOADHXY to InstructionFormat.from("W,>r1"),
|
||||
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"),
|
||||
@ -592,6 +629,13 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.STOREZM to InstructionFormat.from("BW,>a | F,>a"),
|
||||
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
|
||||
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
|
||||
Opcode.STOREHA to InstructionFormat.from("B,<r1"),
|
||||
Opcode.STOREHA to InstructionFormat.from("B,<r1"),
|
||||
Opcode.STOREHX to InstructionFormat.from("B,<r1"),
|
||||
Opcode.STOREHY to InstructionFormat.from("B,<r1"),
|
||||
Opcode.STOREHAX to InstructionFormat.from("W,<r1"),
|
||||
Opcode.STOREHAY to InstructionFormat.from("W,<r1"),
|
||||
Opcode.STOREHXY to InstructionFormat.from("W,<r1"),
|
||||
Opcode.JUMP to InstructionFormat.from("N,<a"),
|
||||
Opcode.JUMPI to InstructionFormat.from("N,<a"),
|
||||
Opcode.PREPARECALL to InstructionFormat.from("N,<i"),
|
||||
@ -1020,13 +1064,10 @@ data class IRInstruction(
|
||||
IRDataType.FLOAT -> result.add("fr${returns.registerNum}.f")
|
||||
}
|
||||
} else {
|
||||
result.add("@" + cpuReg)
|
||||
if(returns.cpuRegister?.statusflag==null) {
|
||||
when (returns.dt) {
|
||||
IRDataType.BYTE -> result.add(".b")
|
||||
IRDataType.WORD -> result.add(".w")
|
||||
IRDataType.FLOAT -> result.add(".f")
|
||||
}
|
||||
when(returns.dt) {
|
||||
IRDataType.BYTE -> result.add("r${returns.registerNum}.b@" + cpuReg)
|
||||
IRDataType.WORD -> result.add("r${returns.registerNum}.w@" + cpuReg)
|
||||
IRDataType.FLOAT -> result.add("r${returns.registerNum}.f@" + cpuReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +178,12 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.LOADI -> InsLOADI(ins)
|
||||
Opcode.LOADIX -> InsLOADIX(ins)
|
||||
Opcode.LOADR -> InsLOADR(ins)
|
||||
Opcode.LOADHA,
|
||||
Opcode.LOADHX,
|
||||
Opcode.LOADHY,
|
||||
Opcode.LOADHAX,
|
||||
Opcode.LOADHAY,
|
||||
Opcode.LOADHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
|
||||
Opcode.STOREM -> InsSTOREM(ins)
|
||||
Opcode.STOREX -> InsSTOREX(ins)
|
||||
Opcode.STOREIX -> InsSTOREIX(ins)
|
||||
@ -185,10 +191,16 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.STOREZM -> InsSTOREZM(ins)
|
||||
Opcode.STOREZX -> InsSTOREZX(ins)
|
||||
Opcode.STOREZI -> InsSTOREZI(ins)
|
||||
Opcode.STOREHA,
|
||||
Opcode.STOREHX,
|
||||
Opcode.STOREHY,
|
||||
Opcode.STOREHAX,
|
||||
Opcode.STOREHAY,
|
||||
Opcode.STOREHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register")
|
||||
Opcode.JUMP -> InsJUMP(ins)
|
||||
Opcode.JUMPI -> InsJUMPI(ins)
|
||||
Opcode.PREPARECALL -> nextPc()
|
||||
Opcode.CALLI -> throw IllegalArgumentException("VM cannot run code from memory")
|
||||
Opcode.CALLI -> throw IllegalArgumentException("VM cannot run code from memory bytes")
|
||||
Opcode.CALL -> InsCALL(ins)
|
||||
Opcode.SYSCALL -> InsSYSCALL(ins)
|
||||
Opcode.RETURN -> InsRETURN()
|
||||
@ -319,6 +331,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.FFLOOR -> InsFFLOOR(ins)
|
||||
Opcode.FCEIL -> InsFCEIL(ins)
|
||||
Opcode.FCOMP -> InsFCOMP(ins)
|
||||
|
||||
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class VmProgramLoader {
|
||||
|
||||
block.children.forEach { child ->
|
||||
when(child) {
|
||||
is IRAsmSubroutine -> throw IRParseException("vm does not support non-inlined asmsubs (use normal sub): ${child.label}")
|
||||
is IRAsmSubroutine -> throw IRParseException("vm does not support asmsubs (use normal sub): ${child.label}")
|
||||
is IRCodeChunk -> programChunks += child
|
||||
is IRInlineAsmChunk -> throw IRParseException("encountered unconverted inline assembly chunk")
|
||||
is IRInlineBinaryChunk -> throw IRParseException("inline binary data not yet supported in the VM")
|
||||
|
@ -85,7 +85,7 @@ class TestVm: FunSpec( {
|
||||
)
|
||||
block += startSub
|
||||
program.addBlock(block)
|
||||
shouldThrowWithMessage<IRParseException>("vm does not support non-inlined asmsubs (use normal sub): main.asmstart") {
|
||||
shouldThrowWithMessage<IRParseException>("vm does not support asmsubs (use normal sub): main.asmstart") {
|
||||
VirtualMachine(program)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user