mirror of
https://github.com/irmen/prog8.git
synced 2025-01-25 12:30:09 +00:00
IR: small optimization
This commit is contained in:
parent
befe0fff2a
commit
c4f53fe525
@ -72,25 +72,25 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
|
|
||||||
private fun assignVarAugmented(symbol: String, assignment: PtAugmentedAssign): IRCodeChunks {
|
private fun assignVarAugmented(symbol: String, assignment: PtAugmentedAssign): IRCodeChunks {
|
||||||
val value = assignment.value
|
val value = assignment.value
|
||||||
val valueVmDt = codeGen.irType(value.type)
|
val targetDt = codeGen.irType(assignment.target.type)
|
||||||
return when (assignment.operator) {
|
return when (assignment.operator) {
|
||||||
"+=" -> expressionEval.operatorPlusInplace(null, symbol, valueVmDt, value)
|
"+=" -> expressionEval.operatorPlusInplace(null, symbol, targetDt, value)
|
||||||
"-=" -> expressionEval.operatorMinusInplace(null, symbol, valueVmDt, value)
|
"-=" -> expressionEval.operatorMinusInplace(null, symbol, targetDt, value)
|
||||||
"*=" -> expressionEval.operatorMultiplyInplace(null, symbol, valueVmDt, value)
|
"*=" -> expressionEval.operatorMultiplyInplace(null, symbol, targetDt, value)
|
||||||
"/=" -> expressionEval.operatorDivideInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
"/=" -> expressionEval.operatorDivideInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
"|=" -> expressionEval.operatorOrInplace(null, symbol, valueVmDt, value)
|
"|=" -> expressionEval.operatorOrInplace(null, symbol, targetDt, value)
|
||||||
"&=" -> expressionEval.operatorAndInplace(null, symbol, valueVmDt, value)
|
"&=" -> expressionEval.operatorAndInplace(null, symbol, targetDt, value)
|
||||||
"^=" -> expressionEval.operatorXorInplace(null, symbol, valueVmDt, value)
|
"^=" -> expressionEval.operatorXorInplace(null, symbol, targetDt, value)
|
||||||
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, valueVmDt, value)
|
"<<=" -> expressionEval.operatorShiftLeftInplace(null, symbol, targetDt, value)
|
||||||
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
">>=" -> expressionEval.operatorShiftRightInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
"%=" -> expressionEval.operatorModuloInplace(null, symbol, valueVmDt, value)
|
"%=" -> expressionEval.operatorModuloInplace(null, symbol, targetDt, value)
|
||||||
"==" -> expressionEval.operatorEqualsInplace(null, symbol, valueVmDt, value)
|
"==" -> expressionEval.operatorEqualsInplace(null, symbol, targetDt, value)
|
||||||
"!=" -> expressionEval.operatorNotEqualsInplace(null, symbol, valueVmDt, value)
|
"!=" -> expressionEval.operatorNotEqualsInplace(null, symbol, targetDt, value)
|
||||||
"<" -> expressionEval.operatorLessInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
"<" -> expressionEval.operatorLessInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
">" -> expressionEval.operatorGreaterInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
">" -> expressionEval.operatorGreaterInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
"<=" -> expressionEval.operatorLessEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
"<=" -> expressionEval.operatorLessEqualInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
">=" -> expressionEval.operatorGreaterEqualInplace(null, symbol, valueVmDt, value.type in SignedDatatypes, value)
|
">=" -> expressionEval.operatorGreaterEqualInplace(null, symbol, targetDt, value.type in SignedDatatypes, value)
|
||||||
in PrefixOperators -> inplacePrefix(assignment.operator, valueVmDt, null, symbol)
|
in PrefixOperators -> inplacePrefix(assignment.operator, targetDt, null, symbol)
|
||||||
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
else -> throw AssemblyError("invalid augmented assign operator ${assignment.operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
actualResultReg2 = tr.resultReg
|
actualResultReg2 = tr.resultReg
|
||||||
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
|
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
|
||||||
}
|
}
|
||||||
DataType.WORD -> { }
|
DataType.WORD -> {
|
||||||
|
actualResultReg2 = tr.resultReg
|
||||||
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.nextFree()
|
actualResultReg2 = codeGen.registers.nextFree()
|
||||||
addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOUW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
@ -288,7 +290,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
actualResultReg2 = tr.resultReg
|
actualResultReg2 = tr.resultReg
|
||||||
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
|
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.BYTE, reg1 = actualResultReg2), null)
|
||||||
}
|
}
|
||||||
DataType.UWORD -> { }
|
DataType.UWORD -> {
|
||||||
|
actualResultReg2 = tr.resultReg
|
||||||
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
actualResultReg2 = codeGen.registers.nextFree()
|
actualResultReg2 = codeGen.registers.nextFree()
|
||||||
addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FTOSW, IRDataType.FLOAT, reg1=actualResultReg2, fpReg1 = tr.resultFpReg), null)
|
||||||
@ -316,6 +320,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird cast type")
|
else -> throw AssemblyError("weird cast type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg2, actualResultFpReg2)
|
return ExpressionCodeResult(result, codeGen.irType(cast.type), actualResultReg2, actualResultFpReg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,17 +561,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
val rightTr = translateExpression(binExpr.right)
|
val rightTr = translateExpression(binExpr.right)
|
||||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||||
val resultRegister = codeGen.registers.nextFree()
|
val resultRegister = codeGen.registers.nextFree()
|
||||||
if (notEquals) {
|
|
||||||
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
|
||||||
} else {
|
|
||||||
val label = codeGen.createLabelName()
|
|
||||||
val valueReg = codeGen.registers.nextFree()
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
val label = codeGen.createLabelName()
|
||||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null)
|
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=1), null)
|
||||||
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
||||||
|
if (notEquals) {
|
||||||
|
addInstr(result, IRInstruction(Opcode.BNZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null)
|
||||||
|
} else {
|
||||||
addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null)
|
addInstr(result, IRInstruction(Opcode.BZ, IRDataType.BYTE, reg1=valueReg, labelSymbol = label), null)
|
||||||
|
}
|
||||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null)
|
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, value=0), null)
|
||||||
result += IRCodeChunk(label, null)
|
result += IRCodeChunk(label, null)
|
||||||
}
|
|
||||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
|
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
|
||||||
} else {
|
} else {
|
||||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||||
@ -1208,152 +1213,171 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun operatorEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
fun operatorEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
val tr = translateExpression(operand)
|
createInplaceFloatComparison(knownAddress, symbol, operand, Opcode.SEQ)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
|
||||||
if(knownAddress!=null) {
|
|
||||||
// @(address) = @(address) == operand
|
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
it += IRInstruction(Opcode.SEQ, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol == operand
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, Opcode.SEQ)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
it += IRInstruction(Opcode.SEQ, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun operatorNotEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
fun operatorNotEqualsInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
val tr = translateExpression(operand)
|
createInplaceFloatComparison(knownAddress, symbol, operand, Opcode.SNE)
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
|
||||||
if(knownAddress!=null) {
|
|
||||||
// @(address) = @(address) != operand
|
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
it += IRInstruction(Opcode.SNE, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol != operand
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, Opcode.SNE)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
it += IRInstruction(Opcode.SNE, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun operatorGreaterInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
fun operatorGreaterInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
|
||||||
val tr = translateExpression(operand)
|
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
|
||||||
val opcode = if(signed) Opcode.SGTS else Opcode.SGT
|
val opcode = if(signed) Opcode.SGTS else Opcode.SGT
|
||||||
if(knownAddress!=null) {
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
// @(address) = @(address) > operand
|
createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol > operand
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun operatorLessInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
fun operatorLessInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
|
||||||
val tr = translateExpression(operand)
|
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
|
||||||
val opcode = if(signed) Opcode.SLTS else Opcode.SLT
|
val opcode = if(signed) Opcode.SLTS else Opcode.SLT
|
||||||
if(knownAddress!=null) {
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
// @(address) = @(address) < operand
|
createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol < operand
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun operatorGreaterEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
fun operatorGreaterEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
|
||||||
val tr = translateExpression(operand)
|
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
|
||||||
val opcode = if(signed) Opcode.SGES else Opcode.SGE
|
val opcode = if(signed) Opcode.SGES else Opcode.SGE
|
||||||
if(knownAddress!=null) {
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
// @(address) = @(address) > operand
|
createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
|
||||||
|
} else {
|
||||||
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun operatorLessEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
||||||
|
val opcode = if(signed) Opcode.SLES else Opcode.SLE
|
||||||
|
return if(vmDt==IRDataType.FLOAT) {
|
||||||
|
createInplaceFloatComparison(knownAddress, symbol, operand, opcode)
|
||||||
|
} else {
|
||||||
|
createInplaceComparison(knownAddress, symbol, vmDt, operand, opcode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createInplaceComparison(
|
||||||
|
knownAddress: Int?,
|
||||||
|
symbol: String?,
|
||||||
|
vmDt: IRDataType,
|
||||||
|
operand: PtExpression,
|
||||||
|
compareAndSetOpcode: Opcode
|
||||||
|
): MutableList<IRCodeChunkBase> {
|
||||||
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val valueReg = codeGen.registers.nextFree()
|
val valueReg = codeGen.registers.nextFree()
|
||||||
|
if(operand is PtNumber) {
|
||||||
|
val numberReg = codeGen.registers.nextFree()
|
||||||
|
if (knownAddress != null) {
|
||||||
|
// in-place modify a memory location
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, value = knownAddress)
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, value=operand.number.toInt())
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, value = knownAddress)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol > operand
|
// in-place modify a symbol (variable)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, value=operand.number.toInt())
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, tr.resultReg, -1)
|
||||||
|
if (knownAddress != null) {
|
||||||
|
// in-place modify a memory location
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, value = knownAddress)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = tr.resultReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, value = knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in-place modify a symbol (variable)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = tr.resultReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun operatorLessEqualInplace(knownAddress: Int?, symbol: String?, vmDt: IRDataType, signed: Boolean, operand: PtExpression): IRCodeChunks {
|
private fun createInplaceFloatComparison(
|
||||||
|
knownAddress: Int?,
|
||||||
|
symbol: String?,
|
||||||
|
operand: PtExpression,
|
||||||
|
compareAndSetOpcode: Opcode
|
||||||
|
): MutableList<IRCodeChunkBase> {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val tr = translateExpression(operand)
|
val valueReg = codeGen.registers.nextFreeFloat()
|
||||||
addToResult(result, tr, tr.resultReg, -1)
|
val cmpReg = codeGen.registers.nextFree()
|
||||||
val opcode = if(signed) Opcode.SLES else Opcode.SLE
|
val zeroReg = codeGen.registers.nextFree()
|
||||||
if(knownAddress!=null) {
|
if(operand is PtNumber) {
|
||||||
// @(address) = @(address) > operand
|
val numberReg = codeGen.registers.nextFreeFloat()
|
||||||
val valueReg = codeGen.registers.nextFree()
|
if (knownAddress != null) {
|
||||||
|
// in-place modify a memory location
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, value=knownAddress)
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, value = knownAddress)
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, fpValue = operand.number.toFloat())
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, value=knownAddress)
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
|
||||||
|
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, value=knownAddress)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// symbol = symbol > operand
|
// in-place modify a symbol (variable)
|
||||||
val valueReg = codeGen.registers.nextFree()
|
|
||||||
result += IRCodeChunk(null, null).also {
|
result += IRCodeChunk(null, null).also {
|
||||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||||
it += IRInstruction(opcode, vmDt, reg1=valueReg, reg2=tr.resultReg)
|
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, fpValue = operand.number.toFloat())
|
||||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueReg, labelSymbol = symbol)
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
|
||||||
|
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val tr = translateExpression(operand)
|
||||||
|
addToResult(result, tr, -1, tr.resultFpReg)
|
||||||
|
if (knownAddress != null) {
|
||||||
|
// in-place modify a memory location
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, value = knownAddress)
|
||||||
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg)
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
|
||||||
|
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, value=knownAddress)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in-place modify a symbol (variable)
|
||||||
|
result += IRCodeChunk(null, null).also {
|
||||||
|
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||||
|
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg)
|
||||||
|
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, value=0)
|
||||||
|
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpReg, reg2=zeroReg)
|
||||||
|
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||||
|
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -410,8 +410,14 @@ private fun createAssemblyAndAssemble(program: PtProgram,
|
|||||||
else
|
else
|
||||||
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}")
|
throw NotImplementedError("no code generator for cpu ${compilerOptions.compTarget.machine.cpu}")
|
||||||
|
|
||||||
if(compilerOptions.useNewExprCode)
|
if(compilerOptions.useNewExprCode) {
|
||||||
|
if(compilerOptions.compTarget.machine.cpu !in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) {
|
||||||
|
// the IR code gen backend has its own, better, version of dealing with binary expressions.
|
||||||
|
throw IllegalArgumentException("'newexpr' expression rewrite should not be used with compilation target ${compilerOptions.compTarget.name}")
|
||||||
|
}
|
||||||
|
|
||||||
transformNewExpressions(program)
|
transformNewExpressions(program)
|
||||||
|
}
|
||||||
|
|
||||||
// printAst(program, true) { println(it) }
|
// printAst(program, true) { println(it) }
|
||||||
|
|
||||||
|
@ -163,6 +163,6 @@ main {
|
|||||||
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
|
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
|
||||||
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
|
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = false) shouldNotBe null
|
||||||
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
|
compileText(C64Target(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
|
||||||
compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
|
// no newexpr for IR targets: compileText(VMTarget(), true, text, writeAssembly = true, useNewExprCode = true) shouldNotBe null
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -1,19 +1,11 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
||||||
For next minor release
|
For next minor release
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
newxpr vm: vm/bsieve.p8 has wrong result
|
|
||||||
once everything works, disable -newexpr option for IR/virtual target because that already works without eval stack
|
|
||||||
and creates far superior code without the newexpr flattening.
|
|
||||||
|
|
||||||
IR (normal): fix reg1 out of bounds crash in compiler/test/comparisons/test_compares.p8
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
For 9.0 major changes
|
For 9.0 major changes
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
- get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8.
|
- get rid of the disknumber parameter everywhere in diskio, make it a configurable variable that defaults to 8.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user