ir: remove a bunch of strange in-place assignment operators, and problematic opcodes

This commit is contained in:
Irmen de Jong 2024-12-27 18:22:15 +01:00
parent 942d3ee640
commit e2882d37bf
6 changed files with 87 additions and 392 deletions

View File

@ -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"))
}
}
}

View File

@ -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)) {

View File

@ -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")

View File

@ -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")
}
}

View File

@ -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"),

View File

@ -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