mirror of
https://github.com/irmen/prog8.git
synced 2024-11-03 13:07:54 +00:00
working on address-of
This commit is contained in:
parent
e34bab9585
commit
7294ec9a3c
@ -32,7 +32,7 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
assignSelfInMemory(address, assignment.value, assignment)
|
assignSelfInMemory(address, assignment.value, assignment)
|
||||||
} else if(memory != null) {
|
} else if(memory != null) {
|
||||||
if(memory.address is PtNumber)
|
if(memory.address is PtNumber)
|
||||||
assignSelfInMemory((memory.address as PtNumber).number.toInt(), assignment.value, assignment)
|
assignSelfInMemoryKnownAddress((memory.address as PtNumber).number.toInt(), assignment.value, assignment)
|
||||||
else
|
else
|
||||||
fallbackAssign(assignment)
|
fallbackAssign(assignment)
|
||||||
} else if(array!=null) {
|
} else if(array!=null) {
|
||||||
@ -45,7 +45,7 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignSelfInMemory(
|
private fun assignSelfInMemoryKnownAddress(
|
||||||
address: Int,
|
address: Int,
|
||||||
value: PtExpression,
|
value: PtExpression,
|
||||||
origAssign: PtAssignment
|
origAssign: PtAssignment
|
||||||
@ -55,8 +55,8 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
when(value) {
|
when(value) {
|
||||||
is PtIdentifier -> return code // do nothing, x=x null assignment.
|
is PtIdentifier -> return code // do nothing, x=x null assignment.
|
||||||
is PtMachineRegister -> return code // do nothing, reg=reg null assignment
|
is PtMachineRegister -> return code // do nothing, reg=reg null assignment
|
||||||
is PtPrefix -> return inplacePrefix(value.operator, vmDt, address, value.position)
|
is PtPrefix -> return inplacePrefix(value.operator, vmDt, address, null, value.position)
|
||||||
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, address, origAssign)
|
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, address, null, origAssign)
|
||||||
is PtMemoryByte -> {
|
is PtMemoryByte -> {
|
||||||
return if (!codeGen.options.compTarget.machine.isIOAddress(address.toUInt()))
|
return if (!codeGen.options.compTarget.machine.isIOAddress(address.toUInt()))
|
||||||
code // do nothing, mem=mem null assignment.
|
code // do nothing, mem=mem null assignment.
|
||||||
@ -70,7 +70,28 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
}
|
}
|
||||||
else -> return fallbackAssign(origAssign)
|
else -> return fallbackAssign(origAssign)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assignSelfInMemory(
|
||||||
|
addressOf: String,
|
||||||
|
value: PtExpression,
|
||||||
|
origAssign: PtAssignment
|
||||||
|
): IRCodeChunk {
|
||||||
|
val vmDt = codeGen.vmType(value.type)
|
||||||
|
val code = IRCodeChunk(origAssign.position)
|
||||||
|
when(value) {
|
||||||
|
is PtIdentifier -> return code // do nothing, x=x null assignment.
|
||||||
|
is PtMachineRegister -> return code // do nothing, reg=reg null assignment
|
||||||
|
is PtPrefix -> return inplacePrefix(value.operator, vmDt, null, addressOf, value.position)
|
||||||
|
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, null, addressOf, origAssign)
|
||||||
|
is PtMemoryByte -> {
|
||||||
|
val tempReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, labelSymbol = addressOf)
|
||||||
|
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, labelSymbol = addressOf)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
else -> return fallbackAssign(origAssign)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fallbackAssign(origAssign: PtAssignment): IRCodeChunk {
|
private fun fallbackAssign(origAssign: PtAssignment): IRCodeChunk {
|
||||||
@ -84,36 +105,59 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
operand: PtExpression,
|
operand: PtExpression,
|
||||||
vmDt: VmDataType,
|
vmDt: VmDataType,
|
||||||
signed: Boolean,
|
signed: Boolean,
|
||||||
address: Int,
|
knownAddress: Int?,
|
||||||
|
addressOfSymbol: String?,
|
||||||
origAssign: PtAssignment
|
origAssign: PtAssignment
|
||||||
): IRCodeChunk {
|
): IRCodeChunk {
|
||||||
when(operator) {
|
if(knownAddress!=null) {
|
||||||
"+" -> return expressionEval.operatorPlusInplace(address, vmDt, operand)
|
when (operator) {
|
||||||
"-" -> return expressionEval.operatorMinusInplace(address, vmDt, operand)
|
"+" -> return expressionEval.operatorPlusInplace(knownAddress, null, vmDt, operand)
|
||||||
"*" -> return expressionEval.operatorMultiplyInplace(address, vmDt, operand)
|
"-" -> return expressionEval.operatorMinusInplace(knownAddress, null, vmDt, operand)
|
||||||
"/" -> return expressionEval.operatorDivideInplace(address, vmDt, signed, operand)
|
"*" -> return expressionEval.operatorMultiplyInplace(knownAddress, null, vmDt, operand)
|
||||||
"|" -> return expressionEval.operatorOrInplace(address, vmDt, operand)
|
"/" -> return expressionEval.operatorDivideInplace(knownAddress, null, vmDt, signed, operand)
|
||||||
"&" -> return expressionEval.operatorAndInplace(address, vmDt, operand)
|
"|" -> return expressionEval.operatorOrInplace(knownAddress, null, vmDt, operand)
|
||||||
"^" -> return expressionEval.operatorXorInplace(address, vmDt, operand)
|
"&" -> return expressionEval.operatorAndInplace(knownAddress, null, vmDt, operand)
|
||||||
"<<" -> return expressionEval.operatorShiftLeftInplace(address, vmDt, operand)
|
"^" -> return expressionEval.operatorXorInplace(knownAddress, null, vmDt, operand)
|
||||||
">>" -> return expressionEval.operatorShiftRightInplace(address, vmDt, signed, operand)
|
"<<" -> return expressionEval.operatorShiftLeftInplace(knownAddress, null, vmDt, operand)
|
||||||
else -> {}
|
">>" -> return expressionEval.operatorShiftRightInplace(knownAddress, null, vmDt, signed, operand)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addressOfSymbol!!
|
||||||
|
when (operator) {
|
||||||
|
"+" -> return expressionEval.operatorPlusInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"-" -> return expressionEval.operatorMinusInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"*" -> return expressionEval.operatorMultiplyInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"/" -> return expressionEval.operatorDivideInplace(null, addressOfSymbol, vmDt, signed, operand)
|
||||||
|
"|" -> return expressionEval.operatorOrInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"&" -> return expressionEval.operatorAndInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"^" -> return expressionEval.operatorXorInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
"<<" -> return expressionEval.operatorShiftLeftInplace(null, addressOfSymbol, vmDt, operand)
|
||||||
|
">>" -> return expressionEval.operatorShiftRightInplace(null, addressOfSymbol, vmDt, signed, operand)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fallbackAssign(origAssign)
|
return fallbackAssign(origAssign)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplacePrefix(operator: String, vmDt: VmDataType, address: Int, position: Position): IRCodeChunk {
|
private fun inplacePrefix(operator: String, vmDt: VmDataType, knownAddress: Int?, addressSymbol: String?, position: Position): IRCodeChunk {
|
||||||
val code= IRCodeChunk(position)
|
val code= IRCodeChunk(position)
|
||||||
when(operator) {
|
when(operator) {
|
||||||
"+" -> { }
|
"+" -> { }
|
||||||
"-" -> {
|
"-" -> {
|
||||||
code += IRCodeInstruction(Opcode.NEGM, vmDt, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.NEGM, vmDt, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.NEGM, vmDt, labelSymbol = addressSymbol)
|
||||||
}
|
}
|
||||||
"~" -> {
|
"~" -> {
|
||||||
val regMask = codeGen.vmRegisters.nextFree()
|
val regMask = codeGen.vmRegisters.nextFree()
|
||||||
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
||||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value = mask)
|
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value = mask)
|
||||||
code += IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, labelSymbol = addressSymbol)
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird prefix operator")
|
else -> throw AssemblyError("weird prefix operator")
|
||||||
}
|
}
|
||||||
@ -147,19 +191,19 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ident!=null) {
|
if(ident!=null) {
|
||||||
val address = codeGen.addressOf(ident.targetName)
|
val addressOf = codeGen.addressOf(ident.targetName)
|
||||||
code += if(zero) {
|
code += if(zero) {
|
||||||
IRCodeInstruction(Opcode.STOREZM, vmDt, value = address)
|
IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = addressOf)
|
||||||
} else {
|
} else {
|
||||||
if (vmDt == VmDataType.FLOAT)
|
if (vmDt == VmDataType.FLOAT)
|
||||||
IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value = address)
|
IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = addressOf)
|
||||||
else
|
else
|
||||||
IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value = address)
|
IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = addressOf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(array!=null) {
|
else if(array!=null) {
|
||||||
val variable = array.variable.targetName
|
val variable = array.variable.targetName
|
||||||
var variableAddr = codeGen.addressOf(variable)
|
var variableAddrOf = codeGen.addressOf(variable)
|
||||||
val itemsize = codeGen.program.memsizer.memorySize(array.type)
|
val itemsize = codeGen.program.memsizer.memorySize(array.type)
|
||||||
|
|
||||||
if(array.variable.type==DataType.UWORD) {
|
if(array.variable.type==DataType.UWORD) {
|
||||||
@ -175,38 +219,38 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
resultRegister = codeGen.vmRegisters.nextFree()
|
resultRegister = codeGen.vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0)
|
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0)
|
||||||
}
|
}
|
||||||
code += IRCodeInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, value = variableAddr)
|
code += IRCodeInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = variableAddrOf)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
val fixedIndex = constIntValue(array.index)
|
val fixedIndex = constIntValue(array.index)
|
||||||
if(zero) {
|
if(zero) {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
variableAddr += fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
code += IRCodeInstruction(Opcode.STOREZM, vmDt, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = "$variableAddrOf+$offset")
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.vmRegisters.nextFree()
|
val indexReg = codeGen.vmRegisters.nextFree()
|
||||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||||
code += IRCodeInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variableAddrOf)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(vmDt== VmDataType.FLOAT) {
|
if(vmDt== VmDataType.FLOAT) {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
variableAddr += fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = "$variableAddrOf+$offset")
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.vmRegisters.nextFree()
|
val indexReg = codeGen.vmRegisters.nextFree()
|
||||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variableAddrOf)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
variableAddr += fixedIndex*itemsize
|
val offset = fixedIndex*itemsize
|
||||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = "$variableAddrOf+$offset")
|
||||||
} else {
|
} else {
|
||||||
val indexReg = codeGen.vmRegisters.nextFree()
|
val indexReg = codeGen.vmRegisters.nextFree()
|
||||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variableAddrOf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
is PtIdentifier -> {
|
is PtIdentifier -> {
|
||||||
val arrayAddress = addressOf(iterable.targetName)
|
val arrayAddress = addressOf(iterable.targetName)
|
||||||
val iterableVar = symbolTable.lookup(iterable.targetName) as StStaticVariable
|
val iterableVar = symbolTable.lookup(iterable.targetName) as StStaticVariable
|
||||||
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
|
val loopvarAddress = addressOf(loopvar.scopedName)
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
val tmpReg = vmRegisters.nextFree()
|
val tmpReg = vmRegisters.nextFree()
|
||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
@ -325,9 +325,9 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
// iterate over a zero-terminated string
|
// iterate over a zero-terminated string
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||||
code += IRCodeLabel(loopLabel)
|
code += IRCodeLabel(loopLabel)
|
||||||
code += IRCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, value = arrayAddress)
|
code += IRCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = arrayAddress)
|
||||||
code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel)
|
code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, value = loopvarAddress)
|
code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, labelSymbol = loopvarAddress)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
code += IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg)
|
code += IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg)
|
||||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = loopLabel)
|
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = loopLabel)
|
||||||
@ -342,16 +342,16 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes)
|
||||||
code += IRCodeLabel(loopLabel)
|
code += IRCodeLabel(loopLabel)
|
||||||
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, value=arrayAddress)
|
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=arrayAddress)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, value = loopvarAddress)
|
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarAddress)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
||||||
code += IRCodeInstruction(Opcode.BNE, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, labelSymbol = loopLabel)
|
code += IRCodeInstruction(Opcode.BNE, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, labelSymbol = loopLabel)
|
||||||
} else if(lengthBytes==256) {
|
} else if(lengthBytes==256) {
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||||
code += IRCodeLabel(loopLabel)
|
code += IRCodeLabel(loopLabel)
|
||||||
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, value=arrayAddress)
|
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=arrayAddress)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, value = loopvarAddress)
|
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarAddress)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
||||||
code += IRCodeInstruction(Opcode.BNZ, VmDataType.BYTE, reg1=indexReg, labelSymbol = loopLabel)
|
code += IRCodeInstruction(Opcode.BNZ, VmDataType.BYTE, reg1=indexReg, labelSymbol = loopLabel)
|
||||||
@ -365,10 +365,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun addressOf(targetName: List<String>): Int {
|
internal inline fun addressOf(targetName: List<String>): String = "&"+targetName.joinToString(".")
|
||||||
println("TODO: IR SUPPORT FOR ADDRESS-OF $targetName") // TODO address-of
|
|
||||||
return 4242
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk {
|
private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk {
|
||||||
val iterable = forLoop.iterable as PtRange
|
val iterable = forLoop.iterable as PtRange
|
||||||
@ -377,18 +374,18 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
throw AssemblyError("step 0")
|
throw AssemblyError("step 0")
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
val endvalueReg = vmRegisters.nextFree()
|
val endvalueReg = vmRegisters.nextFree()
|
||||||
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
|
val loopvarAddress = addressOf(loopvar.scopedName)
|
||||||
val loopvarDt = vmType(loopvar.dt)
|
val loopvarDt = vmType(loopvar.dt)
|
||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
val code = IRCodeChunk(forLoop.position)
|
val code = IRCodeChunk(forLoop.position)
|
||||||
|
|
||||||
code += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
code += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
||||||
code += expressionEval.translateExpression(iterable.from, indexReg, -1)
|
code += expressionEval.translateExpression(iterable.from, indexReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarAddress)
|
||||||
code += IRCodeLabel(loopLabel)
|
code += IRCodeLabel(loopLabel)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position)
|
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position)
|
||||||
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarAddress)
|
||||||
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
||||||
code += IRCodeInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel)
|
code += IRCodeInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel)
|
||||||
return code
|
return code
|
||||||
@ -396,7 +393,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
|
|
||||||
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk {
|
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): IRCodeChunk {
|
||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
val loopvarAddress = addressOf(loopvar.scopedName) // TODO name?
|
val loopvarAddress = addressOf(loopvar.scopedName)
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
val loopvarDt = vmType(loopvar.dt)
|
val loopvarDt = vmType(loopvar.dt)
|
||||||
val iterable = forLoop.iterable as PtRange
|
val iterable = forLoop.iterable as PtRange
|
||||||
@ -417,11 +414,11 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
endvalueReg = -1 // not used
|
endvalueReg = -1 // not used
|
||||||
}
|
}
|
||||||
code += IRCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
code += IRCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarAddress)
|
||||||
code += IRCodeLabel(loopLabel)
|
code += IRCodeLabel(loopLabel)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position)
|
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step, iterable.position)
|
||||||
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarAddress)
|
||||||
code += if(rangeEndWrapped==0) {
|
code += if(rangeEndWrapped==0) {
|
||||||
IRCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
IRCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
||||||
} else {
|
} else {
|
||||||
@ -504,16 +501,22 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun multiplyByConstFloatInplace(address: Int, factor: Float, position: Position): IRCodeChunk {
|
internal fun multiplyByConstFloatInplace(knownAddress: Int?, addressOfSymbol: String?, factor: Float, position: Position): IRCodeChunk {
|
||||||
val code = IRCodeChunk(position)
|
val code = IRCodeChunk(position)
|
||||||
if(factor==1f)
|
if(factor==1f)
|
||||||
return code
|
return code
|
||||||
if(factor==0f) {
|
if(factor==0f) {
|
||||||
code += IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, labelSymbol = addressOfSymbol)
|
||||||
} else {
|
} else {
|
||||||
val factorReg = vmRegisters.nextFreeFloat()
|
val factorReg = vmRegisters.nextFreeFloat()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||||
code += IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -544,28 +547,40 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun multiplyByConstInplace(dt: VmDataType, address: Int, factor: Int, position: Position): IRCodeChunk {
|
internal fun multiplyByConstInplace(dt: VmDataType, knownAddress: Int?, addressOfSymbol: String?, factor: Int, position: Position): IRCodeChunk {
|
||||||
val code = IRCodeChunk(position)
|
val code = IRCodeChunk(position)
|
||||||
if(factor==1)
|
if(factor==1)
|
||||||
return code
|
return code
|
||||||
val pow2 = powersOfTwo.indexOf(factor)
|
val pow2 = powersOfTwo.indexOf(factor)
|
||||||
if(pow2==1) {
|
if(pow2==1) {
|
||||||
// just shift 1 bit
|
// just shift 1 bit
|
||||||
code += IRCodeInstruction(Opcode.LSLM, dt, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSLM, dt, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSLM, dt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else if(pow2>=1) {
|
else if(pow2>=1) {
|
||||||
// just shift multiple bits
|
// just shift multiple bits
|
||||||
val pow2reg = vmRegisters.nextFree()
|
val pow2reg = vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||||
code += IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, labelSymbol = addressOfSymbol)
|
||||||
} else {
|
} else {
|
||||||
if (factor == 0) {
|
if (factor == 0) {
|
||||||
code += IRCodeInstruction(Opcode.STOREZM, dt, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.STOREZM, dt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.STOREZM, dt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val factorReg = vmRegisters.nextFree()
|
val factorReg = vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value = factor)
|
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value = factor)
|
||||||
code += IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -583,18 +598,24 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun divideByConstFloatInplace(address: Int, factor: Float, position: Position): IRCodeChunk {
|
internal fun divideByConstFloatInplace(knownAddress: Int?, addressOfSymbol: String?, factor: Float, position: Position): IRCodeChunk {
|
||||||
val code = IRCodeChunk(position)
|
val code = IRCodeChunk(position)
|
||||||
if(factor==1f)
|
if(factor==1f)
|
||||||
return code
|
return code
|
||||||
if(factor==0f) {
|
if(factor==0f) {
|
||||||
val maxvalueReg = vmRegisters.nextFreeFloat()
|
val maxvalueReg = vmRegisters.nextFreeFloat()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = maxvalueReg, fpValue = Float.MAX_VALUE)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = maxvalueReg, fpValue = Float.MAX_VALUE)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, labelSymbol = addressOfSymbol)
|
||||||
} else {
|
} else {
|
||||||
val factorReg = vmRegisters.nextFreeFloat()
|
val factorReg = vmRegisters.nextFreeFloat()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||||
code += IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -628,35 +649,58 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun divideByConstInplace(dt: VmDataType, address: Int, factor: Int, signed: Boolean, position: Position): IRCodeChunk {
|
internal fun divideByConstInplace(dt: VmDataType, knownAddress: Int?, addressOfSymbol: String?, factor: Int, signed: Boolean, position: Position): IRCodeChunk {
|
||||||
val code = IRCodeChunk(position)
|
val code = IRCodeChunk(position)
|
||||||
if(factor==1)
|
if(factor==1)
|
||||||
return code
|
return code
|
||||||
val pow2 = powersOfTwo.indexOf(factor)
|
val pow2 = powersOfTwo.indexOf(factor)
|
||||||
if(pow2==1 && !signed) {
|
if(pow2==1 && !signed) {
|
||||||
code += IRCodeInstruction(Opcode.LSRM, dt, value=address) // just simple bit shift
|
// just simple bit shift
|
||||||
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSRM, dt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSRM, dt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else if(pow2>=1 && !signed) {
|
else if(pow2>=1 && !signed) {
|
||||||
// just shift multiple bits
|
// just shift multiple bits
|
||||||
val pow2reg = vmRegisters.nextFree()
|
val pow2reg = vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||||
code += if(signed)
|
code += if(signed) {
|
||||||
IRCodeInstruction(Opcode.ASRNM, dt, reg1=pow2reg, value=address)
|
if(knownAddress!=null)
|
||||||
else
|
IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||||
IRCodeInstruction(Opcode.LSRNM, dt, reg1=pow2reg, value=address)
|
else
|
||||||
|
IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (factor == 0) {
|
if (factor == 0) {
|
||||||
val reg = vmRegisters.nextFree()
|
val reg = vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val factorReg = vmRegisters.nextFree()
|
val factorReg = vmRegisters.nextFree()
|
||||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||||
code += if(signed)
|
code += if(signed) {
|
||||||
IRCodeInstruction(Opcode.DIVSM, dt, reg1=factorReg, value=address)
|
if(knownAddress!=null)
|
||||||
else
|
IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, value = knownAddress)
|
||||||
IRCodeInstruction(Opcode.DIVM, dt, reg1=factorReg, value=address)
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -772,7 +816,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val vmDt = vmType(postIncrDecr.target.type)
|
val vmDt = vmType(postIncrDecr.target.type)
|
||||||
if(ident!=null) {
|
if(ident!=null) {
|
||||||
val address = addressOf(ident.targetName)
|
val address = addressOf(ident.targetName)
|
||||||
code += IRCodeInstruction(operationMem, vmDt, value = address)
|
code += IRCodeInstruction(operationMem, vmDt, labelSymbol = address)
|
||||||
} else if(memory!=null) {
|
} else if(memory!=null) {
|
||||||
if(memory.address is PtNumber) {
|
if(memory.address is PtNumber) {
|
||||||
val address = (memory.address as PtNumber).number.toInt()
|
val address = (memory.address as PtNumber).number.toInt()
|
||||||
@ -792,14 +836,14 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val fixedIndex = constIntValue(array.index)
|
val fixedIndex = constIntValue(array.index)
|
||||||
if(fixedIndex!=null) {
|
if(fixedIndex!=null) {
|
||||||
variableAddr += fixedIndex*itemsize
|
variableAddr += fixedIndex*itemsize
|
||||||
code += IRCodeInstruction(operationMem, vmDt, value=variableAddr)
|
code += IRCodeInstruction(operationMem, vmDt, labelSymbol=variableAddr)
|
||||||
} else {
|
} else {
|
||||||
val incReg = vmRegisters.nextFree()
|
val incReg = vmRegisters.nextFree()
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(array.index, indexReg, -1)
|
code += expressionEval.translateExpression(array.index, indexReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr)
|
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variableAddr)
|
||||||
code += IRCodeInstruction(operationRegister, vmDt, reg1=incReg)
|
code += IRCodeInstruction(operationRegister, vmDt, reg1=incReg)
|
||||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr)
|
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variableAddr)
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
throw AssemblyError("weird assigntarget")
|
throw AssemblyError("weird assigntarget")
|
||||||
|
@ -30,21 +30,21 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
}
|
}
|
||||||
is PtIdentifier -> {
|
is PtIdentifier -> {
|
||||||
val vmDt = codeGen.vmType(expr.type)
|
val vmDt = codeGen.vmType(expr.type)
|
||||||
val mem = codeGen.addressOf(expr.targetName)
|
val addrOf = codeGen.addressOf(expr.targetName)
|
||||||
code += if (expr.type in PassByValueDatatypes) {
|
code += if (expr.type in PassByValueDatatypes) {
|
||||||
if(vmDt==VmDataType.FLOAT)
|
if(vmDt==VmDataType.FLOAT)
|
||||||
IRCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, value = mem)
|
IRCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = addrOf)
|
||||||
else
|
else
|
||||||
IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, value = mem)
|
IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = addrOf)
|
||||||
} else {
|
} else {
|
||||||
// for strings and arrays etc., load the *address* of the value instead
|
// for strings and arrays etc., load the *address* of the value instead
|
||||||
IRCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, value = mem)
|
IRCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = addrOf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PtAddressOf -> {
|
is PtAddressOf -> {
|
||||||
val vmDt = codeGen.vmType(expr.type)
|
val vmDt = codeGen.vmType(expr.type)
|
||||||
val mem = codeGen.addressOf(expr.identifier.targetName)
|
val addrOf = codeGen.addressOf(expr.identifier.targetName)
|
||||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem)
|
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = addrOf)
|
||||||
}
|
}
|
||||||
is PtMemoryByte -> {
|
is PtMemoryByte -> {
|
||||||
if(expr.address is PtNumber) {
|
if(expr.address is PtNumber) {
|
||||||
@ -107,7 +107,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val vmDt = codeGen.vmType(arrayIx.type)
|
val vmDt = codeGen.vmType(arrayIx.type)
|
||||||
val code = IRCodeChunk(arrayIx.position)
|
val code = IRCodeChunk(arrayIx.position)
|
||||||
val idxReg = codeGen.vmRegisters.nextFree()
|
val idxReg = codeGen.vmRegisters.nextFree()
|
||||||
val arrayLocation = codeGen.addressOf(arrayIx.variable.targetName)
|
val arrayLocationExpr = codeGen.addressOf(arrayIx.variable.targetName)
|
||||||
|
|
||||||
if(arrayIx.variable.type==DataType.UWORD) {
|
if(arrayIx.variable.type==DataType.UWORD) {
|
||||||
// indexing a pointer var instead of a real array or string
|
// indexing a pointer var instead of a real array or string
|
||||||
@ -116,25 +116,24 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
if(arrayIx.index.type!=DataType.UBYTE)
|
if(arrayIx.index.type!=DataType.UBYTE)
|
||||||
throw AssemblyError("non-array var indexing requires bytes index")
|
throw AssemblyError("non-array var indexing requires bytes index")
|
||||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
code += IRCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayLocationExpr)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
if(arrayIx.index is PtNumber) {
|
if(arrayIx.index is PtNumber) {
|
||||||
// optimized code when index is known - just calculate the memory address here
|
val memOffset = ((arrayIx.index as PtNumber).number.toInt() * eltSize).toString()
|
||||||
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
|
|
||||||
if(vmDt==VmDataType.FLOAT)
|
if(vmDt==VmDataType.FLOAT)
|
||||||
code += IRCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, value=arrayLocation+memOffset)
|
code += IRCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol = "$arrayLocationExpr+$memOffset")
|
||||||
else
|
else
|
||||||
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
|
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = "$arrayLocationExpr+$memOffset")
|
||||||
} else {
|
} else {
|
||||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||||
if(eltSize>1)
|
if(eltSize>1)
|
||||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize, arrayIx.position)
|
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize, arrayIx.position)
|
||||||
if(vmDt==VmDataType.FLOAT)
|
if(vmDt==VmDataType.FLOAT)
|
||||||
code += IRCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, value = arrayLocation)
|
code += IRCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, labelSymbol = arrayLocationExpr)
|
||||||
else
|
else
|
||||||
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayLocationExpr)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -416,16 +415,22 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorShiftRightInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk {
|
internal fun operatorShiftRightInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
if(codeGen.isOne(operand)) {
|
if(codeGen.isOne(operand)) {
|
||||||
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
|
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
|
||||||
code += IRCodeInstruction(opc, vmDt, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(opc, vmDt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(opc, vmDt, labelSymbol = addressOfSymbol)
|
||||||
} else {
|
} else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM
|
val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM
|
||||||
code += IRCodeInstruction(opc, vmDt, reg1 = operandReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -444,14 +449,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorShiftLeftInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorShiftLeftInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
if(codeGen.isOne(operand)){
|
if(codeGen.isOne(operand)){
|
||||||
code += IRCodeInstruction(Opcode.LSLM, vmDt, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSLM, vmDt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSLM, vmDt, labelSymbol = addressOfSymbol)
|
||||||
} else {
|
} else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -470,11 +481,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorXorInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorXorInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,11 +506,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorAndInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorAndInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,11 +531,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorOrInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorOrInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,32 +605,48 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorDivideInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk {
|
internal fun operatorDivideInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, signed: Boolean, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==VmDataType.FLOAT) {
|
if(vmDt==VmDataType.FLOAT) {
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number.toFloat()
|
||||||
code += codeGen.divideByConstFloatInplace(address, factor, operand.position)
|
code += codeGen.divideByConstFloatInplace(knownAddress, addressOfSymbol, factor, operand.position)
|
||||||
} else {
|
} else {
|
||||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||||
code += translateExpression(operand, -1, operandFpReg)
|
code += translateExpression(operand, -1, operandFpReg)
|
||||||
code += if(signed)
|
code += if(signed) {
|
||||||
IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value=address)
|
if(knownAddress!=null)
|
||||||
else
|
IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||||
IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value=address)
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
val factor = constFactorRight.number.toInt()
|
val factor = constFactorRight.number.toInt()
|
||||||
code += codeGen.divideByConstInplace(vmDt, address, factor, signed, operand.position)
|
code += codeGen.divideByConstInplace(vmDt, knownAddress, addressOfSymbol, factor, signed, operand.position)
|
||||||
} else {
|
} else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += if(signed)
|
code += if(signed) {
|
||||||
IRCodeInstruction(Opcode.DIVSM, vmDt, reg1=operandReg, value = address)
|
if(knownAddress!=null)
|
||||||
else
|
IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||||
IRCodeInstruction(Opcode.DIVM, vmDt, reg1=operandReg, value = address)
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = addressOfSymbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -654,26 +690,32 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorMultiplyInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorMultiplyInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
val constFactorRight = operand as? PtNumber
|
val constFactorRight = operand as? PtNumber
|
||||||
if(vmDt==VmDataType.FLOAT) {
|
if(vmDt==VmDataType.FLOAT) {
|
||||||
if(constFactorRight!=null) {
|
if(constFactorRight!=null) {
|
||||||
val factor = constFactorRight.number.toFloat()
|
val factor = constFactorRight.number.toFloat()
|
||||||
code += codeGen.multiplyByConstFloatInplace(address, factor, constFactorRight.position)
|
code += codeGen.multiplyByConstFloatInplace(knownAddress, addressOfSymbol, factor, constFactorRight.position)
|
||||||
} else {
|
} else {
|
||||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||||
code += translateExpression(operand, -1, operandFpReg)
|
code += translateExpression(operand, -1, operandFpReg)
|
||||||
code += IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
val factor = constFactorRight.number.toInt()
|
val factor = constFactorRight.number.toInt()
|
||||||
code += codeGen.multiplyByConstInplace(vmDt, address, factor, constFactorRight.position)
|
code += codeGen.multiplyByConstInplace(vmDt, knownAddress, addressOfSymbol, factor, constFactorRight.position)
|
||||||
} else {
|
} else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -717,25 +759,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorMinusInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorMinusInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
if(vmDt==VmDataType.FLOAT) {
|
if(vmDt==VmDataType.FLOAT) {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
code += IRCodeInstruction(Opcode.DECM, vmDt, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||||
code += translateExpression(operand, -1, operandFpReg)
|
code += translateExpression(operand, -1, operandFpReg)
|
||||||
code += IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
code += IRCodeInstruction(Opcode.DECM, vmDt, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -787,25 +841,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun operatorPlusInplace(address: Int, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
internal fun operatorPlusInplace(knownAddress: Int?, addressOfSymbol: String?, vmDt: VmDataType, operand: PtExpression): IRCodeChunk {
|
||||||
val code = IRCodeChunk(operand.position)
|
val code = IRCodeChunk(operand.position)
|
||||||
if(vmDt==VmDataType.FLOAT) {
|
if(vmDt==VmDataType.FLOAT) {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
code += IRCodeInstruction(Opcode.INCM, vmDt, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||||
code += translateExpression(operand, -1, operandFpReg)
|
code += translateExpression(operand, -1, operandFpReg)
|
||||||
code += IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if((operand as? PtNumber)?.number==1.0) {
|
if((operand as? PtNumber)?.number==1.0) {
|
||||||
code += IRCodeInstruction(Opcode.INCM, vmDt, value = address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val operandReg = codeGen.vmRegisters.nextFree()
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(operand, operandReg, -1)
|
code += translateExpression(operand, operandReg, -1)
|
||||||
code += IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=address)
|
code += if(knownAddress!=null)
|
||||||
|
IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||||
|
else
|
||||||
|
IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = addressOfSymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -819,23 +885,23 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val paramDt = codeGen.vmType(parameter.type)
|
val paramDt = codeGen.vmType(parameter.type)
|
||||||
if(codeGen.isZero(arg)) {
|
if(codeGen.isZero(arg)) {
|
||||||
if (paramDt == VmDataType.FLOAT) {
|
if (paramDt == VmDataType.FLOAT) {
|
||||||
val mem = codeGen.addressOf(fcall.functionName + parameter.name)
|
val addrOf = codeGen.addressOf(fcall.functionName + parameter.name)
|
||||||
code += IRCodeInstruction(Opcode.STOREZM, paramDt, value = mem)
|
code += IRCodeInstruction(Opcode.STOREZM, paramDt, labelSymbol = addrOf)
|
||||||
} else {
|
} else {
|
||||||
val mem = codeGen.addressOf(fcall.functionName + parameter.name)
|
val mem = codeGen.addressOf(fcall.functionName + parameter.name)
|
||||||
code += IRCodeInstruction(Opcode.STOREZM, paramDt, value = mem)
|
code += IRCodeInstruction(Opcode.STOREZM, paramDt, labelSymbol = mem)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (paramDt == VmDataType.FLOAT) {
|
if (paramDt == VmDataType.FLOAT) {
|
||||||
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
|
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||||
code += translateExpression(arg, -1, argFpReg)
|
code += translateExpression(arg, -1, argFpReg)
|
||||||
val mem = codeGen.addressOf(fcall.functionName + parameter.name)
|
val addrOf = codeGen.addressOf(fcall.functionName + parameter.name)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem)
|
code += IRCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, labelSymbol = addrOf)
|
||||||
} else {
|
} else {
|
||||||
val argReg = codeGen.vmRegisters.nextFree()
|
val argReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(arg, argReg, -1)
|
code += translateExpression(arg, argReg, -1)
|
||||||
val mem = codeGen.addressOf(fcall.functionName + parameter.name)
|
val addrOf = codeGen.addressOf(fcall.functionName + parameter.name)
|
||||||
code += IRCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem)
|
code += IRCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, labelSymbol = addrOf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import kotlin.io.path.div
|
|||||||
class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IAssemblyProgram {
|
class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IAssemblyProgram {
|
||||||
|
|
||||||
// TODO once this is working, replace the codeGenVirtual by codeGenExperimental
|
// TODO once this is working, replace the codeGenVirtual by codeGenExperimental
|
||||||
// after that, remove the intermediate .p8ir file writing
|
// after that, add an option to the VmRunner to accept an IRProgram object directly and skip this intermediate .p8ir step when -emu is present
|
||||||
|
|
||||||
|
|
||||||
override fun assemble(options: CompilationOptions): Boolean {
|
override fun assemble(options: CompilationOptions): Boolean {
|
||||||
@ -48,7 +48,7 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA
|
|||||||
out.write("; BLOCK ${block.name} ${block.position}\n")
|
out.write("; BLOCK ${block.name} ${block.position}\n")
|
||||||
block.inlineAssembly.forEach { asm ->
|
block.inlineAssembly.forEach { asm ->
|
||||||
out.write("; ASM ${asm.position}\n")
|
out.write("; ASM ${asm.position}\n")
|
||||||
out.write(asm.asm)
|
out.write(asm.assembly)
|
||||||
out.write("\n")
|
out.write("\n")
|
||||||
}
|
}
|
||||||
block.subroutines.forEach { sub ->
|
block.subroutines.forEach { sub ->
|
||||||
@ -56,7 +56,9 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA
|
|||||||
out.write("_${sub.name}:\n")
|
out.write("_${sub.name}:\n")
|
||||||
sub.chunks.forEach { chunk ->
|
sub.chunks.forEach { chunk ->
|
||||||
if(chunk is IRInlineAsmChunk) {
|
if(chunk is IRInlineAsmChunk) {
|
||||||
out.write("; ASM ${chunk.position}\n${chunk.asm}\n")
|
out.write("; ASM ${chunk.position}\n")
|
||||||
|
out.write(processInlinedAsm(chunk.assembly, allocations))
|
||||||
|
out.write("\n")
|
||||||
} else {
|
} else {
|
||||||
chunk.lines.forEach { out.writeLine(it) }
|
chunk.lines.forEach { out.writeLine(it) }
|
||||||
}
|
}
|
||||||
@ -66,7 +68,7 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA
|
|||||||
block.asmSubroutines.forEach { sub ->
|
block.asmSubroutines.forEach { sub ->
|
||||||
out.write("; ASMSUB ${sub.name} ${sub.position}\n")
|
out.write("; ASMSUB ${sub.name} ${sub.position}\n")
|
||||||
out.write("_${sub.name}:\n")
|
out.write("_${sub.name}:\n")
|
||||||
out.write(sub.assembly)
|
out.write(processInlinedAsm(sub.assembly, allocations))
|
||||||
out.write("\n; END ASMSUB ${sub.name}\n")
|
out.write("\n; END ASMSUB ${sub.name}\n")
|
||||||
}
|
}
|
||||||
out.write("; END BLOCK ${block.name}\n")
|
out.write("; END BLOCK ${block.name}\n")
|
||||||
@ -74,6 +76,14 @@ class VmAssemblyProgram(override val name: String, val irProgram: IRProgram): IA
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun processInlinedAsm(asm: String, allocations: VmVariableAllocator): String {
|
||||||
|
// need to replace &X by address of X. TODO: this actually needs to be done by the vm assembler/loader. Then this can be omitted
|
||||||
|
return asm.replace("""&[a-zA-Z\d_\.]+""".toRegex()) { matchResult ->
|
||||||
|
// replace "&X" with the address of X
|
||||||
|
val name = matchResult.value.substring(1, matchResult.value.length).split('.')
|
||||||
|
allocations.get(name).toString() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BufferedWriter.writeLine(line: IRCodeLine) {
|
private fun BufferedWriter.writeLine(line: IRCodeLine) {
|
||||||
|
@ -49,7 +49,7 @@ class AssemblyProgram(override val name: String, private val allocations: Variab
|
|||||||
is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n")
|
is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n")
|
||||||
is VmCodeInlineAsm -> {
|
is VmCodeInlineAsm -> {
|
||||||
val asm = line.assembly.replace("""&[a-zA-Z\d_\.]+""".toRegex()) { matchResult ->
|
val asm = line.assembly.replace("""&[a-zA-Z\d_\.]+""".toRegex()) { matchResult ->
|
||||||
// "&X" -> address of X
|
// need to replace &X by address of X. TODO: this actually needs to be done by the vm assembler/loader. Then this can be omitted
|
||||||
val name = matchResult.value.substring(1, matchResult.value.length).split('.')
|
val name = matchResult.value.substring(1, matchResult.value.length).split('.')
|
||||||
allocations.get(name).toString() }
|
allocations.get(name).toString() }
|
||||||
write(asm+"\n")
|
write(asm+"\n")
|
||||||
|
@ -3,6 +3,8 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- IR: fix superfluous usage of addressOf()
|
||||||
|
- IR: addressOfSymbol -> just 'symbol'
|
||||||
- IR/VM: add address-of support (see CodeGen.addressOf()) syntax = &X
|
- IR/VM: add address-of support (see CodeGen.addressOf()) syntax = &X
|
||||||
- IR/VM: add proper memory mapped variables support
|
- IR/VM: add proper memory mapped variables support
|
||||||
- IR/VM: add proper memory slabs support
|
- IR/VM: add proper memory slabs support
|
||||||
|
@ -322,7 +322,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
|||||||
clobberRegs.toSet(),
|
clobberRegs.toSet(),
|
||||||
params,
|
params,
|
||||||
returns,
|
returns,
|
||||||
asm.asm)
|
asm.assembly)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseSubroutine(startline: String, lines: Iterator<String>, variables: List<StStaticVariable>): IRSubroutine {
|
private fun parseSubroutine(startline: String, lines: Iterator<String>, variables: List<StStaticVariable>): IRSubroutine {
|
||||||
|
@ -79,7 +79,7 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
|||||||
|
|
||||||
private fun writeInlineAsm(chunk: IRInlineAsmChunk) {
|
private fun writeInlineAsm(chunk: IRInlineAsmChunk) {
|
||||||
out.write("<INLINEASM POS=${chunk.position}>\n")
|
out.write("<INLINEASM POS=${chunk.position}>\n")
|
||||||
out.write(chunk.asm.trimStart('\n').trimEnd(' ', '\n'))
|
out.write(chunk.assembly.trimStart('\n').trimEnd(' ', '\n'))
|
||||||
out.write("\n</INLINEASM>\n")
|
out.write("\n</INLINEASM>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,9 +191,9 @@ class IRCodeChunk(position: Position): IRCodeChunkBase(position) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IRInlineAsmChunk(val asm: String, position: Position): IRCodeChunkBase(position) {
|
class IRInlineAsmChunk(val assembly: String, position: Position): IRCodeChunkBase(position) {
|
||||||
// note: no lines, asm is in the property
|
// note: no lines, asm is in the property
|
||||||
override fun isEmpty() = asm.isBlank()
|
override fun isEmpty() = assembly.isBlank()
|
||||||
override fun isNotEmpty() = asm.isNotBlank()
|
override fun isNotEmpty() = assembly.isNotBlank()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +477,10 @@ data class Instruction(
|
|||||||
result.add(",")
|
result.add(",")
|
||||||
}
|
}
|
||||||
labelSymbol?.let {
|
labelSymbol?.let {
|
||||||
result.add("_" + it.joinToString("."))
|
if(labelSymbol[0].startsWith('&'))
|
||||||
|
result.add(it.joinToString(".")) // address-of something
|
||||||
|
else
|
||||||
|
result.add("_" + it.joinToString("."))
|
||||||
}
|
}
|
||||||
if(result.last() == ",")
|
if(result.last() == ",")
|
||||||
result.removeLast()
|
result.removeLast()
|
||||||
|
Loading…
Reference in New Issue
Block a user