mirror of
https://github.com/irmen/prog8.git
synced 2025-02-13 18:31:04 +00:00
ir: remove a bunch of strange in-place assignment operators, and problematic opcodes
This commit is contained in:
parent
942d3ee640
commit
e2882d37bf
@ -98,12 +98,6 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
"<<=" -> operatorShiftLeftInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
">>=" -> operatorShiftRightInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
"%=" -> operatorModuloInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"==" -> operatorEqualsInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"!=" -> operatorNotEqualsInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"<" -> operatorLessInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
">" -> operatorGreaterInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
"<=" -> operatorLessEqualInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
">=" -> operatorGreaterEqualInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
in PrefixOperators -> inplacePrefix(augAssign.operator, symbol, array, constAddress, memTarget, targetDt)
|
||||
|
||||
else -> throw AssemblyError("invalid augmented assign operator ${augAssign.operator}")
|
||||
@ -1140,293 +1134,4 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun operatorEqualsInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, "==")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, Opcode.SEQ)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, Opcode.SEQ)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun operatorNotEqualsInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, "!=")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, Opcode.SNE)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, Opcode.SNE)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun operatorGreaterInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, ">")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val opcode = if(signed) Opcode.SGTS else Opcode.SGT
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, opcode)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, opcode)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun operatorLessInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, "<")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val opcode = if(signed) Opcode.SLTS else Opcode.SLT
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, opcode)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, opcode)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun operatorGreaterEqualInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, ">=")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val opcode = if(signed) Opcode.SGES else Opcode.SGE
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, opcode)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, opcode)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun operatorLessEqualInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
|
||||
if(array!=null)
|
||||
return createInplaceArrayComparison(array, operand, "<=")
|
||||
if(constAddress==null && memory!=null)
|
||||
return null // TODO("optimized memory in-place compare"")
|
||||
|
||||
val opcode = if(signed) Opcode.SLES else Opcode.SLE
|
||||
val chunks = if(vmDt==IRDataType.FLOAT) {
|
||||
createInplaceFloatComparison(constAddress, symbol, operand, opcode)
|
||||
} else {
|
||||
createInplaceComparison(constAddress, symbol, vmDt, operand, opcode)
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
private fun createInplaceComparison(
|
||||
constAddress: Int?,
|
||||
symbol: String?,
|
||||
vmDt: IRDataType,
|
||||
operand: PtExpression,
|
||||
compareAndSetOpcode: Opcode
|
||||
): MutableList<IRCodeChunkBase> {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val valueReg = codeGen.registers.nextFree()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if(operand is PtNumber || operand is PtBool) {
|
||||
|
||||
if(operand is PtNumber && operand.number==0.0 && compareAndSetOpcode in arrayOf(Opcode.SEQ, Opcode.SNE)) {
|
||||
// ==0 or !=0 optimized case
|
||||
val compareAndSetOpcodeZero = if(compareAndSetOpcode==Opcode.SEQ) Opcode.SZ else Opcode.SNZ
|
||||
if (constAddress != null) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress)
|
||||
it += IRInstruction(compareAndSetOpcodeZero, vmDt, reg1 = cmpResultReg, reg2 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress)
|
||||
}
|
||||
} else {
|
||||
// in-place modify a symbol (variable)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||
it += IRInstruction(compareAndSetOpcodeZero, vmDt, reg1=cmpResultReg, reg2 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// compare against number that is not 0
|
||||
val numberReg = codeGen.registers.nextFree()
|
||||
val value = if(operand is PtNumber) operand.number.toInt() else if(operand is PtBool) operand.asInt() else throw AssemblyError("wrong operand type")
|
||||
if (constAddress != null) {
|
||||
// in-place modify a memory location
|
||||
val innervalue = if(operand is PtNumber) operand.number.toInt() else if(operand is PtBool) operand.asInt() else throw AssemblyError("wrong operand type")
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress)
|
||||
it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, immediate = innervalue)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = cmpResultReg, reg2 = valueReg, reg3 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress)
|
||||
}
|
||||
} else {
|
||||
// in-place modify a symbol (variable)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||
it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, immediate = value)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(operand)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
if (constAddress != null) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = constAddress)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = constAddress)
|
||||
}
|
||||
} 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=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createInplaceFloatComparison(
|
||||
constAddress: Int?,
|
||||
symbol: String?,
|
||||
operand: PtExpression,
|
||||
compareAndSetOpcode: Opcode
|
||||
): MutableList<IRCodeChunkBase> {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val valueReg = codeGen.registers.nextFreeFloat()
|
||||
val cmpReg = codeGen.registers.nextFree()
|
||||
val zeroReg = codeGen.registers.nextFree()
|
||||
if(operand is PtNumber) {
|
||||
val numberReg = codeGen.registers.nextFreeFloat()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if (constAddress != null) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number)
|
||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress)
|
||||
}
|
||||
} 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.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number)
|
||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = numberReg)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(operand)
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
addToResult(result, tr, -1, tr.resultFpReg)
|
||||
if (constAddress != null) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress)
|
||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg, fpReg2 = tr.resultFpReg)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroReg, immediate = 0)
|
||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, address = constAddress)
|
||||
}
|
||||
} 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, immediate = 0)
|
||||
it += IRInstruction(compareAndSetOpcode, IRDataType.BYTE, reg1=cmpResultReg, reg2=cmpReg, reg3=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpResultReg, fpReg1 = valueReg)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.FLOAT, fpReg1 = valueReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun createInplaceArrayComparison(array: PtArrayIndexer, value: PtExpression, comparisonOperator: String): IRCodeChunks? {
|
||||
if(array.type.isFloat)
|
||||
return null // TODO("optimized in-place compare on float arrays"))
|
||||
|
||||
val eltSize = codeGen.program.memsizer.memorySize(array.type, null)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
if(array.splitWords)
|
||||
TODO("inplace compare for split word array")
|
||||
val vmDt = irType(array.type)
|
||||
val constIndex = array.index.asConstInteger()
|
||||
val constValue = value.asConstInteger()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if(constIndex!=null) {
|
||||
if(constValue==0) {
|
||||
// comparison against zero.
|
||||
val valueReg = codeGen.registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
|
||||
it += when(comparisonOperator) {
|
||||
"==" -> IRInstruction(Opcode.SZ, vmDt, reg1=cmpResultReg, reg2=valueReg)
|
||||
"!=" -> IRInstruction(Opcode.SNZ, vmDt, reg1=cmpResultReg, reg2=valueReg)
|
||||
"<" -> return null // TODO("array <0 inplace"))
|
||||
"<=" -> return null // TODO("array <=0 inplace"))
|
||||
">" -> return null // TODO("array >0 inplace"))
|
||||
">=" -> return null // TODO("array >=0 inplace"))
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
}
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return null // TODO("compare against non-zero value"))
|
||||
}
|
||||
} else {
|
||||
if(constValue==0) {
|
||||
// comparison against zero.
|
||||
val valueReg = codeGen.registers.nextFree()
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, vmDt, reg1=valueReg, reg2=indexTr.resultReg, labelSymbol = array.variable.name)
|
||||
it += when(comparisonOperator) {
|
||||
"==" -> IRInstruction(Opcode.SZ, vmDt, reg1=cmpResultReg, reg2=valueReg)
|
||||
"!=" -> IRInstruction(Opcode.SNZ, vmDt, reg1=cmpResultReg, reg2=valueReg)
|
||||
"<" -> return null // TODO("array <0 inplace"))
|
||||
"<=" -> return null // TODO("array <=0 inplace"))
|
||||
">" -> return null // TODO("array >0 inplace"))
|
||||
">=" -> return null // TODO("array >=0 inplace"))
|
||||
else -> throw AssemblyError("invalid operator")
|
||||
}
|
||||
it += IRInstruction(Opcode.STOREX, vmDt, reg1=valueReg, reg2=indexTr.resultReg, labelSymbol = array.variable.name)
|
||||
}
|
||||
return result
|
||||
}
|
||||
else
|
||||
return null // TODO("compare against non-zero value"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -429,10 +429,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
BaseDataType.BOOL -> {
|
||||
when {
|
||||
valueDt.isByte -> {
|
||||
// loadStatusAsBooleanResult(Opcode.BSTNE, result)
|
||||
actualResultReg2 = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg), null)
|
||||
}
|
||||
valueDt.isWord -> {
|
||||
// loadStatusAsBooleanResult(Opcode.BSTNE, result)
|
||||
actualResultReg2 = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(Opcode.SNZ, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg), null)
|
||||
}
|
||||
@ -720,7 +722,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
finalReturnRegister = codeGen.registers.nextFree()
|
||||
when(statusFlagResult) {
|
||||
Statusflag.Pc -> {
|
||||
addInstr(result, IRInstruction(Opcode.SCS, returnRegSpec.dt, reg1=finalReturnRegister), null)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, returnRegSpec.dt, reg1 = finalReturnRegister, immediate = 0)
|
||||
it += IRInstruction(Opcode.ROXL, returnRegSpec.dt, reg1 = finalReturnRegister)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val branchOpcode = when(statusFlagResult) {
|
||||
@ -956,14 +961,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val valueReg = codeGen.registers.nextFree()
|
||||
val label = codeGen.createLabelName()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 1)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0)
|
||||
it += IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=valueReg, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg)
|
||||
it += IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=valueReg, immediate = 0)
|
||||
it += if (notEquals)
|
||||
IRInstruction(Opcode.BSTNE, labelSymbol = label)
|
||||
else
|
||||
IRInstruction(Opcode.BSTEQ, labelSymbol = label)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultRegister, immediate = 0)
|
||||
else
|
||||
IRInstruction(Opcode.BSTNE, labelSymbol = label)
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=resultRegister)
|
||||
}
|
||||
result += IRCodeChunk(label, null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
|
||||
@ -971,27 +976,41 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(binExpr.left.type.isString || binExpr.right.type.isString) {
|
||||
throw AssemblyError("str compares should have been replaced with builtin function call to do the compare")
|
||||
} else {
|
||||
return if(binExpr.right.asConstValue()==0.0) {
|
||||
val tr = translateExpression(binExpr.left)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultReg, reg2 = tr.resultReg), null)
|
||||
val rightConst = binExpr.right.asConstValue()
|
||||
return if(rightConst!=null) {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.CMPI, leftTr.dt, reg1 = leftTr.resultReg, immediate = rightConst.toInt()), null)
|
||||
val resultReg = loadStatusAsBooleanResult(if(notEquals) Opcode.BSTNE else Opcode.BSTEQ, result)
|
||||
ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
} else {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultReg, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null)
|
||||
addInstr(result, IRInstruction(Opcode.CMP, leftTr.dt, reg1=leftTr.resultReg, reg2=rightTr.resultReg), null)
|
||||
val resultReg = loadStatusAsBooleanResult(if(notEquals) Opcode.BSTNE else Opcode.BSTEQ, result)
|
||||
ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadStatusAsBooleanResult(branchForTrue: Opcode, result: MutableList<IRCodeChunkBase>): Int {
|
||||
// TODO this used to be a single instruction like SCC, SCS, SZ etc but those were problematic
|
||||
val other = codeGen.createLabelName()
|
||||
val after = codeGen.createLabelName()
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(branchForTrue, labelSymbol = other)
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.JUMP, labelSymbol = after)
|
||||
}
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultReg, immediate = 1), other)
|
||||
result += IRCodeChunk(after, null)
|
||||
return resultReg
|
||||
}
|
||||
|
||||
private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
return if(codeGen.isOne(binExpr.right)) {
|
||||
|
@ -54,6 +54,7 @@ Future Things and Ideas
|
||||
|
||||
IR/VM
|
||||
-----
|
||||
- add BZ and BNZ instructions? To replace CMPI #0 + Branch?
|
||||
- getting it in shape for code generation...: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!)
|
||||
- addUsedRegistersCounts() doesn't always determine the datatype correctly. --> GET RID OF THE Sxxx OPCODES FOR NOW?
|
||||
- fix TODO("IR rol/ror on split words array")
|
||||
|
@ -1,32 +1,63 @@
|
||||
%import textio
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
cx16.r2 = $eeee
|
||||
txt.print_uwhex(cx16.r2, true)
|
||||
txt.nl()
|
||||
cx16.r2,void = thing2() ; TODO fix IR+6502 codegen missing an ext.b (it is present when thing only returns single returnvalue)
|
||||
txt.print_uwhex(cx16.r2, true)
|
||||
txt.nl()
|
||||
cx16.r2 = thing() ; codegen does ext.b correctly here
|
||||
txt.print_uwhex(cx16.r2, true)
|
||||
txt.nl()
|
||||
}
|
||||
bool derp
|
||||
|
||||
asmsub thing() -> ubyte @A {
|
||||
%asm {{
|
||||
lda #$44
|
||||
rts
|
||||
}}
|
||||
}
|
||||
float @shared f1,f2
|
||||
txt.nl()
|
||||
|
||||
asmsub thing2() -> ubyte @A, bool @Pc {
|
||||
%asm {{
|
||||
lda #$aa
|
||||
clc
|
||||
rts
|
||||
}}
|
||||
|
||||
derp = cx16.r0L as bool
|
||||
cx16.r0++
|
||||
derp = cx16.r0 as bool
|
||||
|
||||
cx16.r0L=0
|
||||
derp=true
|
||||
if cx16.r0L==0 and derp
|
||||
txt.print("fl is 0\n")
|
||||
else
|
||||
txt.print("fl is not 0\n")
|
||||
if cx16.r0L!=0 and derp
|
||||
txt.print("fl is not 0\n")
|
||||
else
|
||||
txt.print("fl is 0\n")
|
||||
|
||||
cx16.r0L = 1
|
||||
if cx16.r0L==0 and derp
|
||||
txt.print("fl is 0\n")
|
||||
else
|
||||
txt.print("fl is not 0\n")
|
||||
if cx16.r0L!=0 and derp
|
||||
txt.print("fl is not 0\n")
|
||||
else
|
||||
txt.print("fl is 0\n")
|
||||
|
||||
|
||||
|
||||
cx16.r0L=99
|
||||
derp=true
|
||||
if cx16.r0L==99 and derp
|
||||
txt.print("fl is 99\n")
|
||||
else
|
||||
txt.print("fl is not 99\n")
|
||||
if cx16.r0L!=99 and derp
|
||||
txt.print("fl is not 99\n")
|
||||
else
|
||||
txt.print("fl is 99\n")
|
||||
|
||||
cx16.r0L = 122
|
||||
if cx16.r0L==99 and derp
|
||||
txt.print("fl is 99\n")
|
||||
else
|
||||
txt.print("fl is not 99\n")
|
||||
if cx16.r0L!=99 and derp
|
||||
txt.print("fl is not 99\n")
|
||||
else
|
||||
txt.print("fl is 99\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,12 +123,7 @@ bles reg1, value, address - jump to location in program given by l
|
||||
bgesr reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed)
|
||||
'blesr' reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) ==> use bgesr with swapped operands
|
||||
|
||||
scc reg1 - set reg1=1 if Carry flag is clear, else 0
|
||||
scs reg1 - set reg1=1 if Carry flag is set, else 0
|
||||
sz reg1, reg2 - set reg1=1 if reg2==0, else 0
|
||||
snz reg1, reg2 - set reg1=1 if reg2!=0, else 0
|
||||
seq reg1, reg2, reg3 - set reg1=1 if reg2 == reg3, else 0
|
||||
sne reg1, reg2, reg3 - set reg1=1 if reg2 != reg3, else 0
|
||||
slt reg1, reg2, reg3 - set reg1=1 if reg2 < reg3 (unsigned), else 0
|
||||
slts reg1, reg2, reg3 - set reg1=1 if reg2 < reg3 (signed), else 0
|
||||
sle reg1, reg2, reg3 - set reg1=1 if reg2 <= reg3 (unsigned), else 0
|
||||
@ -323,12 +318,7 @@ enum class Opcode {
|
||||
BGESR,
|
||||
BGES,
|
||||
BLES,
|
||||
SCC,
|
||||
SCS,
|
||||
SZ,
|
||||
SNZ,
|
||||
SEQ,
|
||||
SNE,
|
||||
SLT,
|
||||
SLTS,
|
||||
SGT,
|
||||
@ -526,12 +516,7 @@ val OpcodesThatDependOnCarry = arrayOf(
|
||||
)
|
||||
|
||||
val OpcodesThatSetRegFromStatusbits = arrayOf(
|
||||
Opcode.SCC,
|
||||
Opcode.SCS,
|
||||
Opcode.SZ,
|
||||
Opcode.SNZ,
|
||||
Opcode.SEQ,
|
||||
Opcode.SNE,
|
||||
Opcode.SLT,
|
||||
Opcode.SLTS,
|
||||
Opcode.SGT,
|
||||
@ -692,12 +677,7 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.BGESR to InstructionFormat.from("BW,<r1,<r2,<a"),
|
||||
Opcode.BGES to InstructionFormat.from("BW,<r1,<i,<a"),
|
||||
Opcode.BLES to InstructionFormat.from("BW,<r1,<i,<a"),
|
||||
Opcode.SCC to InstructionFormat.from("BW,>r1"),
|
||||
Opcode.SCS to InstructionFormat.from("BW,>r1"),
|
||||
Opcode.SZ to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.SNZ to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
|
@ -236,12 +236,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.BLE -> InsBLE(ins)
|
||||
Opcode.BGES -> InsBGES(ins)
|
||||
Opcode.BLES -> InsBLES(ins)
|
||||
Opcode.SCC -> InsSCC(ins)
|
||||
Opcode.SCS -> InsSCS(ins)
|
||||
Opcode.SZ -> InsSZ(ins)
|
||||
Opcode.SNZ -> InsSNZ(ins)
|
||||
Opcode.SEQ -> InsSEQ(ins)
|
||||
Opcode.SNE -> InsSNE(ins)
|
||||
Opcode.SLT -> InsSLT(ins)
|
||||
Opcode.SLTS -> InsSLTS(ins)
|
||||
Opcode.SGT -> InsSGT(ins)
|
||||
@ -895,28 +890,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSCC(i: IRInstruction) {
|
||||
setResultReg(i.reg1!!, if(statusCarry) 0 else 1, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSCS(i: IRInstruction) {
|
||||
setResultReg(i.reg1!!, if(statusCarry) 1 else 0, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSZ(i: IRInstruction) {
|
||||
val right = when(i.type) {
|
||||
IRDataType.BYTE -> registers.getSB(i.reg2!!).toInt()
|
||||
IRDataType.WORD -> registers.getSW(i.reg2!!).toInt()
|
||||
IRDataType.FLOAT -> throw IllegalArgumentException("can't use float here")
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
val value = if(right==0) 1 else 0
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSNZ(i: IRInstruction) {
|
||||
val right = when(i.type) {
|
||||
IRDataType.BYTE -> registers.getSB(i.reg2!!).toInt()
|
||||
@ -929,20 +902,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSEQ(i: IRInstruction) {
|
||||
val (left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left==right) 1 else 0
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSNE(i: IRInstruction) {
|
||||
val (left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left!=right) 1 else 0
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSLT(i: IRInstruction) {
|
||||
val (left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left<right) 1 else 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user