vm: remove BEQ opcode -> CMPI + BSTEQ

This commit is contained in:
Irmen de Jong 2023-09-23 00:47:48 +02:00
parent eb55da63ef
commit eb64d92333
6 changed files with 244 additions and 197 deletions

View File

@ -562,14 +562,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val resultRegister = codeGen.registers.nextFree() val resultRegister = codeGen.registers.nextFree()
val valueReg = codeGen.registers.nextFree() val valueReg = codeGen.registers.nextFree()
val label = codeGen.createLabelName() val label = codeGen.createLabelName()
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 1), null) result += IRCodeChunk(null, null).also {
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null) it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 1)
if (notEquals) { it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
addInstr(result, IRInstruction(Opcode.BNE, IRDataType.BYTE, reg1=valueReg, immediate = 0, labelSymbol = label), null) if (notEquals) {
} else { it += IRInstruction(Opcode.BNE, IRDataType.BYTE, reg1=valueReg, immediate = 0, labelSymbol = label)
addInstr(result, IRInstruction(Opcode.BEQ, IRDataType.BYTE, reg1=valueReg, immediate = 0, labelSymbol = label), null) } else {
it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=valueReg, immediate = 0)
it += IRInstruction(Opcode.BSTEQ, labelSymbol = label)
}
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0)
} }
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 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 {

View File

@ -415,13 +415,19 @@ class IRCodeGen(
if(choice.statements.children.isEmpty()) { if(choice.statements.children.isEmpty()) {
// no statements for this choice value, jump to the end immediately // no statements for this choice value, jump to the end immediately
choice.values.children.map { it as PtNumber }.sortedBy { it.number }.forEach { value -> choice.values.children.map { it as PtNumber }.sortedBy { it.number }.forEach { value ->
addInstr(result, IRInstruction(Opcode.BEQ, valueDt, reg1=valueTr.resultReg, immediate = value.number.toInt(), labelSymbol = endLabel), null) result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.CMPI, valueDt, reg1=valueTr.resultReg, immediate = value.number.toInt())
it += IRInstruction(Opcode.BSTEQ, labelSymbol = endLabel)
}
} }
} else { } else {
val choiceLabel = createLabelName() val choiceLabel = createLabelName()
choices.add(choiceLabel to choice) choices.add(choiceLabel to choice)
choice.values.children.map { it as PtNumber }.sortedBy { it.number }.forEach { value -> choice.values.children.map { it as PtNumber }.sortedBy { it.number }.forEach { value ->
addInstr(result, IRInstruction(Opcode.BEQ, valueDt, reg1=valueTr.resultReg, immediate = value.number.toInt(), labelSymbol = choiceLabel), null) result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.CMPI, valueDt, reg1=valueTr.resultReg, immediate = value.number.toInt())
it += IRInstruction(Opcode.BSTEQ, labelSymbol = choiceLabel)
}
} }
} }
} }
@ -464,7 +470,8 @@ class IRCodeGen(
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = indexReg, immediate = 0), null) addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = indexReg, immediate = 0), null)
result += IRCodeChunk(loopLabel, null).also { result += IRCodeChunk(loopLabel, null).also {
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1 = tmpReg, reg2 = indexReg, labelSymbol = iterable.name) it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1 = tmpReg, reg2 = indexReg, labelSymbol = iterable.name)
it += IRInstruction(Opcode.BEQ, IRDataType.BYTE, reg1 = tmpReg, immediate = 0, labelSymbol = endLabel) it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = tmpReg, immediate = 0)
it += IRInstruction(Opcode.BSTEQ, labelSymbol = endLabel)
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = tmpReg, labelSymbol = loopvarSymbol) it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = tmpReg, labelSymbol = loopvarSymbol)
} }
result += translateNode(forLoop.statements) result += translateNode(forLoop.statements)
@ -960,21 +967,30 @@ class IRCodeGen(
fpReg1 = leftTr.resultFpReg, fpReg1 = leftTr.resultFpReg,
fpReg2 = rightTr.resultFpReg fpReg2 = rightTr.resultFpReg
) )
val gotoOpcode = when (condition.operator) { when(condition.operator) {
"==" -> Opcode.BEQ // TODO: the converted list of operators
"!=" -> Opcode.BNE "==" -> {
"<" -> Opcode.BLTS it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = compResultReg, immediate = 0)
">" -> Opcode.BGTS it += branchInstr(goto, Opcode.BSTEQ)
"<=" -> Opcode.BLES }
">=" -> Opcode.BGES else -> {
else -> throw AssemblyError("weird operator") // TODO: the old list of operators, still to be converted
val gotoOpcode = when (condition.operator) {
"!=" -> Opcode.BNE
"<" -> Opcode.BLTS
">" -> Opcode.BGTS
"<=" -> Opcode.BLES
">=" -> Opcode.BGES
else -> throw AssemblyError("weird operator")
}
it += if (goto.address != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, address = goto.address?.toInt())
else if (goto.generatedLabel != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = goto.generatedLabel)
else
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = goto.identifier!!.name)
}
} }
it += if (goto.address != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, address = goto.address?.toInt())
else if (goto.generatedLabel != null)
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = goto.generatedLabel)
else
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = goto.identifier!!.name)
} }
return result return result
} else { } else {
@ -989,6 +1005,14 @@ class IRCodeGen(
} }
} }
// TODO use this everywhere
private fun branchInstr(goto: PtJump, branchOpcode: Opcode) = if (goto.address != null)
IRInstruction(branchOpcode, address = goto.address?.toInt())
else if (goto.generatedLabel != null)
IRInstruction(branchOpcode, labelSymbol = goto.generatedLabel)
else
IRInstruction(branchOpcode, labelSymbol = goto.identifier!!.name)
private fun ifZeroIntThenJump( private fun ifZeroIntThenJump(
result: MutableList<IRCodeChunkBase>, result: MutableList<IRCodeChunkBase>,
ifElse: PtIfElse, ifElse: PtIfElse,
@ -999,21 +1023,30 @@ class IRCodeGen(
val condition = ifElse.condition as PtBinaryExpression val condition = ifElse.condition as PtBinaryExpression
val leftTr = expressionEval.translateExpression(condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val opcode = when (condition.operator) { when(condition.operator) {
"==" -> Opcode.BEQ // TODO: converted list of operators
"!=" -> Opcode.BNE "==" -> {
"<" -> if (signed) Opcode.BLTS else Opcode.BLT addInstr(result, IRInstruction(Opcode.CMPI, irDtLeft, reg1 = leftTr.resultReg, immediate = 0), null)
">" -> if (signed) Opcode.BGTS else Opcode.BGT addInstr(result, branchInstr(goto, Opcode.BSTEQ), null)
"<=" -> if (signed) Opcode.BLES else Opcode.BLE }
">=" -> if (signed) Opcode.BGES else Opcode.BGE else -> {
else -> throw AssemblyError("invalid comparison operator") // TODO: to-be converted operators
val opcode = when (condition.operator) {
"!=" -> Opcode.BNE
"<" -> if (signed) Opcode.BLTS else Opcode.BLT
">" -> if (signed) Opcode.BGTS else Opcode.BGT
"<=" -> if (signed) Opcode.BLES else Opcode.BLE
">=" -> if (signed) Opcode.BGES else Opcode.BGE
else -> throw AssemblyError("invalid comparison operator")
}
if (goto.address != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, address = goto.address?.toInt()), null)
else if (goto.generatedLabel != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, labelSymbol = goto.generatedLabel), null)
else
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, labelSymbol = goto.identifier!!.name), null)
}
} }
if (goto.address != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, address = goto.address?.toInt()), null)
else if (goto.generatedLabel != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, labelSymbol = goto.generatedLabel), null)
else
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = leftTr.resultReg, immediate = 0, labelSymbol = goto.identifier!!.name), null)
} }
private fun ifNonZeroIntThenJump( private fun ifNonZeroIntThenJump(
@ -1036,30 +1069,39 @@ class IRCodeGen(
} else { } else {
val leftTr = expressionEval.translateExpression(condition.left) val leftTr = expressionEval.translateExpression(condition.left)
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val opcode: Opcode
val number = (condition.right as? PtNumber)?.number?.toInt() val number = (condition.right as? PtNumber)?.number?.toInt()
if(number!=null) { if(number!=null) {
val firstReg = leftTr.resultReg val firstReg = leftTr.resultReg
opcode = when (condition.operator) { when(condition.operator) {
"==" -> Opcode.BEQ // TODO: the converted operators
"!=" -> Opcode.BNE "==" -> {
"<" -> if(signed) Opcode.BLTS else Opcode.BLT addInstr(result, IRInstruction(Opcode.CMPI, irDtLeft, reg1 = firstReg, immediate = number), null)
">" -> if(signed) Opcode.BGTS else Opcode.BGT addInstr(result, branchInstr(goto, Opcode.BSTEQ), null)
"<=" -> if(signed) Opcode.BLES else Opcode.BLE }
">=" -> if(signed) Opcode.BGES else Opcode.BGE else -> {
else -> throw AssemblyError("invalid comparison operator") // TODO: to-be converted operators
val opcode = when (condition.operator) {
"!=" -> Opcode.BNE
"<" -> if(signed) Opcode.BLTS else Opcode.BLT
">" -> if(signed) Opcode.BGTS else Opcode.BGT
"<=" -> if(signed) Opcode.BLES else Opcode.BLE
">=" -> if(signed) Opcode.BGES else Opcode.BGE
else -> throw AssemblyError("invalid comparison operator")
}
if (goto.address != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, address = goto.address?.toInt()), null)
else if (goto.generatedLabel != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, labelSymbol = goto.generatedLabel), null)
else
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, labelSymbol = goto.identifier!!.name), null)
}
} }
if (goto.address != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, address = goto.address?.toInt()), null)
else if (goto.generatedLabel != null)
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, labelSymbol = goto.generatedLabel), null)
else
addInstr(result, IRInstruction(opcode, irDtLeft, reg1 = firstReg, immediate = number, labelSymbol = goto.identifier!!.name), null)
} else { } else {
val rightTr = expressionEval.translateExpression(condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, rightTr.resultReg, -1) addToResult(result, rightTr, rightTr.resultReg, -1)
val firstReg: Int val firstReg: Int
val secondReg: Int val secondReg: Int
val opcode: Opcode
when (condition.operator) { when (condition.operator) {
"==" -> { "==" -> {
opcode = Opcode.BEQR opcode = Opcode.BEQR
@ -1108,6 +1150,7 @@ class IRCodeGen(
private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { private fun translateIfElseZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val elseBranch: Opcode val elseBranch: Opcode
var useCmpi = false // for the branch opcodes that have been converted to CMPI + BSTxx form already
val compResultReg: Int val compResultReg: Int
val branchDt: IRDataType val branchDt: IRDataType
val condition = ifElse.condition as PtBinaryExpression val condition = ifElse.condition as PtBinaryExpression
@ -1121,13 +1164,16 @@ class IRCodeGen(
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, immediateFp = 0f) it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = rightFpReg, immediateFp = 0f)
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg) it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightFpReg)
} }
elseBranch = when (condition.operator) { when (condition.operator) {
"==" -> Opcode.BNE "==" -> elseBranch = Opcode.BNE
"!=" -> Opcode.BEQ "!=" -> {
"<" -> Opcode.BGES elseBranch = Opcode.BSTEQ
">" -> Opcode.BLES useCmpi = true
"<=" -> Opcode.BGTS }
">=" -> Opcode.BLTS "<" -> elseBranch = Opcode.BGES
">" -> elseBranch = Opcode.BLES
"<=" -> elseBranch = Opcode.BGTS
">=" -> elseBranch = Opcode.BLTS
else -> throw AssemblyError("weird operator") else -> throw AssemblyError("weird operator")
} }
} else { } else {
@ -1136,13 +1182,16 @@ class IRCodeGen(
val tr = expressionEval.translateExpression(condition.left) val tr = expressionEval.translateExpression(condition.left)
compResultReg = tr.resultReg compResultReg = tr.resultReg
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
elseBranch = when (condition.operator) { when (condition.operator) {
"==" -> Opcode.BNE "==" -> elseBranch = Opcode.BNE
"!=" -> Opcode.BEQ "!=" -> {
"<" -> if (signed) Opcode.BGES else Opcode.BGE elseBranch = Opcode.BSTEQ
">" -> if (signed) Opcode.BLES else Opcode.BLE useCmpi = true
"<=" -> if (signed) Opcode.BGTS else Opcode.BGT }
">=" -> if (signed) Opcode.BLTS else Opcode.BLT "<" -> elseBranch = if (signed) Opcode.BGES else Opcode.BGE
">" -> elseBranch = if (signed) Opcode.BLES else Opcode.BLE
"<=" -> elseBranch = if (signed) Opcode.BGTS else Opcode.BGT
">=" -> elseBranch = if (signed) Opcode.BLTS else Opcode.BLT
else -> throw AssemblyError("weird operator") else -> throw AssemblyError("weird operator")
} }
} }
@ -1150,14 +1199,26 @@ class IRCodeGen(
if(ifElse.elseScope.children.isEmpty()) { if(ifElse.elseScope.children.isEmpty()) {
// just if // just if
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr(result, IRInstruction(elseBranch, branchDt, reg1=compResultReg, immediate = 0, labelSymbol = afterIfLabel), null) if(useCmpi) {
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.CMPI, branchDt, reg1=compResultReg, immediate = 0)
it += IRInstruction(elseBranch, labelSymbol = afterIfLabel)
}
} else
addInstr(result, IRInstruction(elseBranch, branchDt, reg1=compResultReg, immediate = 0, labelSymbol = afterIfLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
result += IRCodeChunk(afterIfLabel, null) result += IRCodeChunk(afterIfLabel, null)
} else { } else {
// if and else // if and else
val elseLabel = createLabelName() val elseLabel = createLabelName()
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr(result, IRInstruction(elseBranch, branchDt, reg1=compResultReg, immediate = 0, labelSymbol = elseLabel), null) if(useCmpi) {
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.CMPI, branchDt, reg1=compResultReg, immediate = 0)
it += IRInstruction(elseBranch, labelSymbol = elseLabel)
}
} else
addInstr(result, IRInstruction(elseBranch, branchDt, reg1=compResultReg, immediate = 0, labelSymbol = elseLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null) addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel) result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
@ -1168,31 +1229,39 @@ class IRCodeGen(
private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks { private fun translateIfElseNonZeroComparison(ifElse: PtIfElse, irDtLeft: IRDataType, signed: Boolean): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val elseBranchOpcode: Opcode
val elseBranchFirstReg: Int val elseBranchFirstReg: Int
val elseBranchSecondReg: Int val elseBranchSecondReg: Int
val branchDt: IRDataType val branchDt: IRDataType
val condition = ifElse.condition as? PtBinaryExpression val condition = ifElse.condition as? PtBinaryExpression
if(condition==null) { if(condition==null) {
if(irDtLeft==IRDataType.FLOAT) throw AssemblyError("if-else condition is not a binaryexpression, should have been converted?")
throw AssemblyError("condition value should not be float") // if(irDtLeft==IRDataType.FLOAT)
val tr = expressionEval.translateExpression(ifElse.condition) // throw AssemblyError("condition value should not be float")
result += tr.chunks // val tr = expressionEval.translateExpression(ifElse.condition)
if(ifElse.elseScope.children.isNotEmpty()) { // result += tr.chunks
val elseLabel = createLabelName() // if(ifElse.elseScope.children.isNotEmpty()) {
val afterIfLabel = createLabelName() // val elseLabel = createLabelName()
addInstr(result, IRInstruction(Opcode.BEQ, irDtLeft, reg1=tr.resultReg, immediate = 0, labelSymbol = elseLabel), null) // result += IRCodeChunk(null, null).also {
result += translateNode(ifElse.ifScope) // it += IRInstruction(Opcode.CMPI, irDtLeft, reg1=tr.resultReg, immediate = 0)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null) // it += IRInstruction(Opcode.BSTEQ, labelSymbol = elseLabel)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel) // TODO("test this")
result += IRCodeChunk(afterIfLabel, null) // }
} else { // result += translateNode(ifElse.ifScope)
val afterIfLabel = createLabelName() // val afterIfLabel = createLabelName()
addInstr(result, IRInstruction(Opcode.BEQ, irDtLeft, reg1=tr.resultReg, immediate = 0, labelSymbol = afterIfLabel), null) // addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += translateNode(ifElse.ifScope) // result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
result += IRCodeChunk(afterIfLabel, null) // result += IRCodeChunk(afterIfLabel, null)
} // } else {
return result // val afterIfLabel = createLabelName()
// result += IRCodeChunk(null, null).also {
// it += IRInstruction(Opcode.CMPI, irDtLeft, reg1=tr.resultReg, immediate = 0)
// it += IRInstruction(Opcode.BSTEQ, labelSymbol = afterIfLabel)
// TODO("test this")
// }
// result += translateNode(ifElse.ifScope)
// result += IRCodeChunk(afterIfLabel, null)
// }
// return result
} else { } else {
if (irDtLeft == IRDataType.FLOAT) { if (irDtLeft == IRDataType.FLOAT) {
val leftTr = expressionEval.translateExpression(condition.left) val leftTr = expressionEval.translateExpression(condition.left)
@ -1200,35 +1269,32 @@ class IRCodeGen(
val rightTr = expressionEval.translateExpression(condition.right) val rightTr = expressionEval.translateExpression(condition.right)
addToResult(result, rightTr, -1, rightTr.resultFpReg) addToResult(result, rightTr, -1, rightTr.resultFpReg)
val compResultReg = registers.nextFree() val compResultReg = registers.nextFree()
addInstr( addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1 = compResultReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
result, val elseBranch: Opcode
IRInstruction( var useCmpi = false // for the branch opcodes that have been converted to CMPI + BSTxx form already
Opcode.FCOMP, when (condition.operator) {
IRDataType.FLOAT, "==" -> elseBranch = Opcode.BNE
reg1 = compResultReg, "!=" -> {
fpReg1 = leftTr.resultFpReg, elseBranch = Opcode.BSTEQ
fpReg2 = rightTr.resultFpReg useCmpi = true
), }
null "<" -> elseBranch = Opcode.BGES
) ">" -> elseBranch = Opcode.BLES
val elseBranch = when (condition.operator) { "<=" -> elseBranch = Opcode.BGTS
"==" -> Opcode.BNE ">=" -> elseBranch = Opcode.BLTS
"!=" -> Opcode.BEQ
"<" -> Opcode.BGES
">" -> Opcode.BLES
"<=" -> Opcode.BGTS
">=" -> Opcode.BLTS
else -> throw AssemblyError("weird operator") else -> throw AssemblyError("weird operator")
} }
if (ifElse.elseScope.children.isNotEmpty()) { if (ifElse.elseScope.children.isNotEmpty()) {
// if and else parts // if and else parts
val elseLabel = createLabelName() val elseLabel = createLabelName()
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( if(useCmpi) {
result, result += IRCodeChunk(null, null).also {
IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = elseLabel), it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = compResultReg, immediate = 0)
null it += IRInstruction(elseBranch, labelSymbol = elseLabel)
) }
} else
addInstr(result, IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = elseLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null) addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel) result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
@ -1236,11 +1302,13 @@ class IRCodeGen(
} else { } else {
// only if part // only if part
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( if(useCmpi) {
result, result += IRCodeChunk(null, null).also {
IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = afterIfLabel), it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1 = compResultReg, immediate = 0)
null it += IRInstruction(elseBranch, labelSymbol = afterIfLabel)
) }
} else
addInstr(result, IRInstruction(elseBranch, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = afterIfLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
result += IRCodeChunk(afterIfLabel, null) result += IRCodeChunk(afterIfLabel, null)
} }
@ -1251,26 +1319,31 @@ class IRCodeGen(
addToResult(result, leftTr, leftTr.resultReg, -1) addToResult(result, leftTr, leftTr.resultReg, -1)
val number = (condition.right as? PtNumber)?.number?.toInt() val number = (condition.right as? PtNumber)?.number?.toInt()
if (number!=null) { if (number!=null) {
elseBranchOpcode = when (condition.operator) { val elseBranch: Opcode
"==" -> Opcode.BNE var useCmpi = false // for the branch opcodes that have been converted to CMPI + BSTxx form already
"!=" -> Opcode.BEQ when (condition.operator) {
"<" -> if(signed) Opcode.BGES else Opcode.BGE "==" -> elseBranch = Opcode.BNE
">" -> if(signed) Opcode.BLES else Opcode.BLE "!=" -> {
"<=" -> if(signed) Opcode.BGTS else Opcode.BGT elseBranch = Opcode.BSTEQ
">=" -> if(signed) Opcode.BLTS else Opcode.BLT useCmpi = true
}
"<" -> elseBranch = if(signed) Opcode.BGES else Opcode.BGE
">" -> elseBranch = if(signed) Opcode.BLES else Opcode.BLE
"<=" -> elseBranch = if(signed) Opcode.BGTS else Opcode.BGT
">=" -> elseBranch = if(signed) Opcode.BLTS else Opcode.BLT
else -> throw AssemblyError("invalid comparison operator") else -> throw AssemblyError("invalid comparison operator")
} }
if (ifElse.elseScope.children.isNotEmpty()) { if (ifElse.elseScope.children.isNotEmpty()) {
// if and else parts // if and else parts
val elseLabel = createLabelName() val elseLabel = createLabelName()
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( if(useCmpi) {
result, IRInstruction( result += IRCodeChunk(null, null).also {
elseBranchOpcode, branchDt, it += IRInstruction(Opcode.CMPI, branchDt, reg1 = leftTr.resultReg, immediate = number)
reg1 = leftTr.resultReg, immediate = number, it += IRInstruction(elseBranch, labelSymbol = elseLabel)
labelSymbol = elseLabel }
), null } else
) addInstr(result, IRInstruction(elseBranch, branchDt, reg1 = leftTr.resultReg, immediate = number, labelSymbol = elseLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null) addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel) result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
@ -1278,52 +1351,53 @@ class IRCodeGen(
} else { } else {
// only if part // only if part
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( if(useCmpi) {
result, IRInstruction( result += IRCodeChunk(null, null).also {
elseBranchOpcode, branchDt, it += IRInstruction(Opcode.CMPI, branchDt, reg1 = leftTr.resultReg, immediate = number)
reg1 = leftTr.resultReg, immediate = number, it += IRInstruction(elseBranch, labelSymbol = afterIfLabel)
labelSymbol = afterIfLabel }
), null } else
) addInstr(result, IRInstruction(elseBranch, branchDt, reg1 = leftTr.resultReg, immediate = number, labelSymbol = afterIfLabel), null)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
result += IRCodeChunk(afterIfLabel, null) result += IRCodeChunk(afterIfLabel, null)
} }
} else { } else {
val rightTr = expressionEval.translateExpression(condition.right) val rightTr = expressionEval.translateExpression(condition.right)
val elseBranch: Opcode
addToResult(result, rightTr, rightTr.resultReg, -1) addToResult(result, rightTr, rightTr.resultReg, -1)
when (condition.operator) { when (condition.operator) {
"==" -> { "==" -> {
elseBranchOpcode = Opcode.BNER elseBranch = Opcode.BNER
elseBranchFirstReg = leftTr.resultReg elseBranchFirstReg = leftTr.resultReg
elseBranchSecondReg = rightTr.resultReg elseBranchSecondReg = rightTr.resultReg
} }
"!=" -> { "!=" -> {
elseBranchOpcode = Opcode.BEQR elseBranch = Opcode.BEQR
elseBranchFirstReg = leftTr.resultReg elseBranchFirstReg = leftTr.resultReg
elseBranchSecondReg = rightTr.resultReg elseBranchSecondReg = rightTr.resultReg
} }
"<" -> { "<" -> {
// else part when left >= right // else part when left >= right
elseBranchOpcode = if (signed) Opcode.BGESR else Opcode.BGER elseBranch = if (signed) Opcode.BGESR else Opcode.BGER
elseBranchFirstReg = leftTr.resultReg elseBranchFirstReg = leftTr.resultReg
elseBranchSecondReg = rightTr.resultReg elseBranchSecondReg = rightTr.resultReg
} }
">" -> { ">" -> {
// else part when left <= right --> right >= left // else part when left <= right --> right >= left
elseBranchOpcode = if (signed) Opcode.BGESR else Opcode.BGER elseBranch = if (signed) Opcode.BGESR else Opcode.BGER
elseBranchFirstReg = rightTr.resultReg elseBranchFirstReg = rightTr.resultReg
elseBranchSecondReg = leftTr.resultReg elseBranchSecondReg = leftTr.resultReg
} }
"<=" -> { "<=" -> {
// else part when left > right // else part when left > right
elseBranchOpcode = if (signed) Opcode.BGTSR else Opcode.BGTR elseBranch = if (signed) Opcode.BGTSR else Opcode.BGTR
elseBranchFirstReg = leftTr.resultReg elseBranchFirstReg = leftTr.resultReg
elseBranchSecondReg = rightTr.resultReg elseBranchSecondReg = rightTr.resultReg
} }
">=" -> { ">=" -> {
// else part when left < right --> right > left // else part when left < right --> right > left
elseBranchOpcode = if (signed) Opcode.BGTSR else Opcode.BGTR elseBranch = if (signed) Opcode.BGTSR else Opcode.BGTR
elseBranchFirstReg = rightTr.resultReg elseBranchFirstReg = rightTr.resultReg
elseBranchSecondReg = leftTr.resultReg elseBranchSecondReg = leftTr.resultReg
} }
@ -1333,13 +1407,7 @@ class IRCodeGen(
// if and else parts // if and else parts
val elseLabel = createLabelName() val elseLabel = createLabelName()
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( addInstr(result, IRInstruction(elseBranch, branchDt, reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg, labelSymbol = elseLabel), null)
result, IRInstruction(
elseBranchOpcode, branchDt,
reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg,
labelSymbol = elseLabel
), null
)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null) addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel), null)
result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel) result += labelFirstChunk(translateNode(ifElse.elseScope), elseLabel)
@ -1347,13 +1415,7 @@ class IRCodeGen(
} else { } else {
// only if part // only if part
val afterIfLabel = createLabelName() val afterIfLabel = createLabelName()
addInstr( addInstr(result, IRInstruction(elseBranch, branchDt, reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg, labelSymbol = afterIfLabel), null)
result, IRInstruction(
elseBranchOpcode, branchDt,
reg1 = elseBranchFirstReg, reg2 = elseBranchSecondReg,
labelSymbol = afterIfLabel
), null
)
result += translateNode(ifElse.ifScope) result += translateNode(ifElse.ifScope)
result += IRCodeChunk(afterIfLabel, null) result += IRCodeChunk(afterIfLabel, null)
} }
@ -1524,7 +1586,10 @@ class IRCodeGen(
addToResult(result, countTr, countTr.resultReg, -1) addToResult(result, countTr, countTr.resultReg, -1)
if(constIntValue(repeat.count)==null) { if(constIntValue(repeat.count)==null) {
// check if the counter is already zero // check if the counter is already zero
addInstr(result, IRInstruction(Opcode.BEQ, irDt, reg1=countTr.resultReg, immediate = 0, labelSymbol = skipRepeatLabel), null) result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.CMPI, irDt, reg1=countTr.resultReg, immediate = 0)
it += IRInstruction(Opcode.BSTEQ, labelSymbol = skipRepeatLabel)
}
} }
result += labelFirstChunk(translateNode(repeat.statements), repeatLabel) result += labelFirstChunk(translateNode(repeat.statements), repeatLabel)
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {

View File

@ -1,20 +1,12 @@
%import textio %import textio
%import floats
main { main {
ubyte begin = 10
ubyte end = 20
sub start() { sub start() {
ubyte xx float xx = 10.1
for xx in begin to end step 3 { ubyte yy= xx==10.1
txt.print_ub(xx) txt.print_ub(yy)
txt.spc() if xx==10.1
} txt.print("equal")
txt.nl()
for xx in end to begin step -3 {
txt.print_ub(xx)
txt.spc()
}
txt.nl()
} }
} }

View File

@ -84,7 +84,6 @@ bstneg address - branch to location if Status bit Negat
bstvc address - branch to location if Status bit Overflow is clear bstvc address - branch to location if Status bit Overflow is clear
bstvs address - branch to location if Status bit Overflow is set bstvs address - branch to location if Status bit Overflow is set
beqr reg1, reg2, address - jump to location in program given by location, if reg1 == reg2 beqr reg1, reg2, address - jump to location in program given by location, if reg1 == reg2
beq reg1, value, address - jump to location in program given by location, if reg1 == immediate value
bner reg1, reg2, address - jump to location in program given by location, if reg1 != reg2 bner reg1, reg2, address - jump to location in program given by location, if reg1 != reg2
bne reg1, value, address - jump to location in program given by location, if reg1 != immediate value bne reg1, value, address - jump to location in program given by location, if reg1 != immediate value
bgt reg1, value, address - jump to location in program given by location, if reg1 > immediate value (unsigned) bgt reg1, value, address - jump to location in program given by location, if reg1 > immediate value (unsigned)
@ -262,7 +261,6 @@ enum class Opcode {
BSTVC, BSTVC,
BSTVS, BSTVS,
BEQR, BEQR,
BEQ,
BNER, BNER,
BNE, BNE,
BGTR, BGTR,
@ -408,7 +406,6 @@ val OpcodesThatBranch = setOf(
Opcode.BSTVC, Opcode.BSTVC,
Opcode.BSTVS, Opcode.BSTVS,
Opcode.BEQR, Opcode.BEQR,
Opcode.BEQ,
Opcode.BNER, Opcode.BNER,
Opcode.BNE, Opcode.BNE,
Opcode.BGTR, Opcode.BGTR,
@ -559,7 +556,6 @@ val instructionFormats = mutableMapOf(
Opcode.BSTVC to InstructionFormat.from("N,<a"), Opcode.BSTVC to InstructionFormat.from("N,<a"),
Opcode.BSTVS to InstructionFormat.from("N,<a"), Opcode.BSTVS to InstructionFormat.from("N,<a"),
Opcode.BEQR to InstructionFormat.from("BW,<r1,<r2,<a"), Opcode.BEQR to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BEQ to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BNER to InstructionFormat.from("BW,<r1,<r2,<a"), Opcode.BNER to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BNE to InstructionFormat.from("BW,<r1,<i,<a"), Opcode.BNE to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BGTR to InstructionFormat.from("BW,<r1,<r2,<a"), Opcode.BGTR to InstructionFormat.from("BW,<r1,<r2,<a"),

View File

@ -23,10 +23,10 @@ class TestInstructions: FunSpec({
} }
test("with value") { test("with value") {
val ins = IRInstruction(Opcode.BEQ, IRDataType.BYTE, reg1=42, immediate = 0, address = 99) val ins = IRInstruction(Opcode.ADD, IRDataType.BYTE, reg1=42, immediate = 0, address = 99)
ins.opcode shouldBe Opcode.BEQ ins.opcode shouldBe Opcode.ADD
ins.type shouldBe IRDataType.BYTE ins.type shouldBe IRDataType.BYTE
ins.reg1direction shouldBe OperandDirection.READ ins.reg1direction shouldBe OperandDirection.READWRITE
ins.fpReg1direction shouldBe OperandDirection.UNUSED ins.fpReg1direction shouldBe OperandDirection.UNUSED
ins.reg1 shouldBe 42 ins.reg1 shouldBe 42
ins.reg2 shouldBe null ins.reg2 shouldBe null
@ -34,14 +34,14 @@ class TestInstructions: FunSpec({
ins.immediate shouldBe 0 ins.immediate shouldBe 0
ins.immediateFp shouldBe null ins.immediateFp shouldBe null
ins.labelSymbol shouldBe null ins.labelSymbol shouldBe null
ins.toString() shouldBe "beq.b r42,0,$63" ins.toString() shouldBe "add.b r42,0,$63"
} }
test("with label") { test("with label") {
val ins = IRInstruction(Opcode.BEQ, IRDataType.WORD, reg1=11, immediate = 0, labelSymbol = "a.b.c") val ins = IRInstruction(Opcode.ADD, IRDataType.WORD, reg1=11, immediate = 0, labelSymbol = "a.b.c")
ins.opcode shouldBe Opcode.BEQ ins.opcode shouldBe Opcode.ADD
ins.type shouldBe IRDataType.WORD ins.type shouldBe IRDataType.WORD
ins.reg1direction shouldBe OperandDirection.READ ins.reg1direction shouldBe OperandDirection.READWRITE
ins.fpReg1direction shouldBe OperandDirection.UNUSED ins.fpReg1direction shouldBe OperandDirection.UNUSED
ins.reg1 shouldBe 11 ins.reg1 shouldBe 11
ins.reg2 shouldBe null ins.reg2 shouldBe null
@ -49,7 +49,7 @@ class TestInstructions: FunSpec({
ins.immediate shouldBe 0 ins.immediate shouldBe 0
ins.immediateFp shouldBe null ins.immediateFp shouldBe null
ins.labelSymbol shouldBe "a.b.c" ins.labelSymbol shouldBe "a.b.c"
ins.toString() shouldBe "beq.w r11,0,a.b.c" ins.toString() shouldBe "add.w r11,0,a.b.c"
} }
test("with output registers") { test("with output registers") {
@ -106,19 +106,19 @@ class TestInstructions: FunSpec({
test("missing type should fail") { test("missing type should fail") {
shouldThrow<IllegalArgumentException> { shouldThrow<IllegalArgumentException> {
IRInstruction(Opcode.BEQ, reg1=42, address=99) IRInstruction(Opcode.ADD, reg1=42, address=99)
} }
} }
test("missing registers should fail") { test("missing registers should fail") {
shouldThrowWithMessage<IllegalArgumentException>("missing reg1") { shouldThrowWithMessage<IllegalArgumentException>("missing reg1") {
IRInstruction(Opcode.BEQ, IRDataType.BYTE, immediate = 0, address=99) IRInstruction(Opcode.ADD, IRDataType.BYTE, immediate = 0, address=99)
} }
} }
test("missing address should fail") { test("missing address should fail") {
shouldThrowWithMessage<IllegalArgumentException>("missing an address or labelsymbol") { shouldThrowWithMessage<IllegalArgumentException>("missing an address or labelsymbol") {
IRInstruction(Opcode.BEQ, IRDataType.BYTE, immediate = 0, reg1=42) IRInstruction(Opcode.INCM, IRDataType.BYTE)
} }
} }

View File

@ -197,7 +197,6 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BGTSR -> InsBGTSR(ins) Opcode.BGTSR -> InsBGTSR(ins)
Opcode.BGER -> InsBGER(ins) Opcode.BGER -> InsBGER(ins)
Opcode.BGESR -> InsBGESR(ins) Opcode.BGESR -> InsBGESR(ins)
Opcode.BEQ -> InsBEQ(ins)
Opcode.BNE -> InsBNE(ins) Opcode.BNE -> InsBNE(ins)
Opcode.BGT -> InsBGT(ins) Opcode.BGT -> InsBGT(ins)
Opcode.BLT -> InsBLT(ins) Opcode.BLT -> InsBLT(ins)
@ -679,14 +678,6 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc() nextPc()
} }
private fun InsBEQ(i: IRInstruction) {
val (left: UInt, right: UInt) = getBranchOperandsImmU(i)
if(left==right)
branchTo(i)
else
nextPc()
}
private fun InsBNER(i: IRInstruction) { private fun InsBNER(i: IRInstruction) {
val (left: Int, right: Int) = getBranchOperands(i) val (left: Int, right: Int) = getBranchOperands(i)
if(left!=right) if(left!=right)