mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
IR: sXX, CONCAT instructions now use 3 register format
This commit is contained in:
parent
7136b33f2e
commit
c7d54570cc
@ -330,10 +330,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
addToResult(result, msbTr, msbTr.resultReg, -1)
|
||||
val lsbTr = exprGen.translateExpression(call.args[1])
|
||||
addToResult(result, lsbTr, lsbTr.resultReg, -1)
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1 = lsbTr.resultReg, reg2 = msbTr.resultReg)
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=resultReg, reg2 = lsbTr.resultReg, reg3 = msbTr.resultReg)
|
||||
}
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, lsbTr.resultReg, -1)
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcClamp(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
|
@ -166,13 +166,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
require(vmDt==IRDataType.WORD)
|
||||
val arrayLength = codeGen.symbolTable.getLength(arrayIx.variable.name)
|
||||
resultRegister = codeGen.registers.nextFree()
|
||||
val finalResultReg = codeGen.registers.nextFree()
|
||||
if(arrayIx.index is PtNumber) {
|
||||
val memOffset = (arrayIx.index as PtNumber).number.toInt()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val tmpRegMsb = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_lsb+$memOffset")
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=tmpRegMsb, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_msb+$memOffset")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=resultRegister, reg2=tmpRegMsb)
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=finalResultReg, reg2=resultRegister, reg3=tmpRegMsb)
|
||||
}
|
||||
} else {
|
||||
val tr = translateExpression(arrayIx.index)
|
||||
@ -181,10 +182,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val tmpRegMsb = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=resultRegister, reg2 = tr.resultReg, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_lsb")
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2 = tr.resultReg, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_msb")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=resultRegister, reg2=tmpRegMsb)
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=finalResultReg, reg2=resultRegister, reg3=tmpRegMsb)
|
||||
}
|
||||
}
|
||||
return ExpressionCodeResult(result, vmDt, resultRegister, -1)
|
||||
return ExpressionCodeResult(result, vmDt, finalResultReg, -1)
|
||||
}
|
||||
|
||||
var resultFpRegister = -1
|
||||
@ -454,6 +455,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
greaterEquals: Boolean
|
||||
): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if(vmDt==IRDataType.FLOAT) {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||
@ -468,8 +470,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
|
||||
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1=cmpResultReg, reg2 = resultRegister, reg3 = zeroRegister), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultReg, -1)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR || binExpr.right.type==DataType.STR) {
|
||||
throw AssemblyError("str compares should have been replaced with builtin function call to do the compare")
|
||||
@ -483,8 +485,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
addInstr(result, IRInstruction(ins, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, leftTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(ins, vmDt, reg1=cmpResultReg, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultReg, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,6 +498,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
lessEquals: Boolean
|
||||
): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val cmpResultRegister = codeGen.registers.nextFree()
|
||||
if(vmDt==IRDataType.FLOAT) {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||
@ -510,8 +513,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultRegister, -1)
|
||||
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1=cmpResultRegister, reg2 = resultRegister, reg3 = zeroRegister), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultRegister, -1)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR || binExpr.right.type==DataType.STR) {
|
||||
throw AssemblyError("str compares should have been replaced with builtin function call to do the compare")
|
||||
@ -525,8 +528,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
addInstr(result, IRInstruction(ins, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, leftTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(ins, vmDt, reg1=cmpResultRegister, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultRegister, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -568,8 +571,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
|
||||
ExpressionCodeResult(result, IRDataType.BYTE, leftTr.resultReg, -1)
|
||||
val resultReg = codeGen.registers.nextFree()
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultReg, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null)
|
||||
ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1239,6 +1243,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
): MutableList<IRCodeChunkBase> {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val valueReg = codeGen.registers.nextFree()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if(operand is PtNumber) {
|
||||
val numberReg = codeGen.registers.nextFree()
|
||||
if (knownAddress != null) {
|
||||
@ -1246,16 +1251,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = knownAddress)
|
||||
it += IRInstruction(Opcode.LOAD, vmDt, reg1=numberReg, immediate = operand.number.toInt())
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, address = knownAddress)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = cmpResultReg, reg2 = valueReg, reg3 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = knownAddress)
|
||||
}
|
||||
} 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 = operand.number.toInt())
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, labelSymbol = symbol)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = numberReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1265,15 +1270,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, vmDt, reg1 = valueReg, address = knownAddress)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1 = valueReg, reg2 = tr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueReg, address = knownAddress)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, address = 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)
|
||||
it += IRInstruction(compareAndSetOpcode, vmDt, reg1=cmpResultReg, reg2 = valueReg, reg3 = tr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREM, vmDt, reg1 = cmpResultReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1292,6 +1297,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val zeroReg = codeGen.registers.nextFree()
|
||||
if(operand is PtNumber) {
|
||||
val numberReg = codeGen.registers.nextFreeFloat()
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
if (knownAddress != null) {
|
||||
// in-place modify a memory location
|
||||
result += IRCodeChunk(null, null).also {
|
||||
@ -1299,8 +1305,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number.toFloat())
|
||||
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=cmpReg, reg2=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||
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 = knownAddress)
|
||||
}
|
||||
} else {
|
||||
@ -1310,13 +1316,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
it += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = numberReg, immediateFp = operand.number.toFloat())
|
||||
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=cmpReg, reg2=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||
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 = translateExpression(operand)
|
||||
val cmpResultReg = codeGen.registers.nextFree()
|
||||
addToResult(result, tr, -1, tr.resultFpReg)
|
||||
if (knownAddress != null) {
|
||||
// in-place modify a memory location
|
||||
@ -1324,8 +1331,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.FLOAT, fpReg1 = valueReg, address = knownAddress)
|
||||
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=cmpReg, reg2=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||
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 = knownAddress)
|
||||
}
|
||||
} else {
|
||||
@ -1334,8 +1341,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
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=cmpReg, reg2=zeroReg)
|
||||
it += IRInstruction(Opcode.FFROMUB, IRDataType.FLOAT, reg1=cmpReg, fpReg1 = valueReg)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +177,7 @@ class IRCodeGen(
|
||||
old.type,
|
||||
old.reg1,
|
||||
old.reg2,
|
||||
old.reg3,
|
||||
old.fpReg1,
|
||||
old.fpReg2,
|
||||
immediate = immediateValue,
|
||||
@ -476,10 +477,11 @@ class IRCodeGen(
|
||||
result += IRCodeChunk(loopLabel, null).also {
|
||||
val tmpRegLsb = registers.nextFree()
|
||||
val tmpRegMsb = registers.nextFree()
|
||||
val concatReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegLsb, reg2=indexReg, immediate = iterableLength, labelSymbol=iterable.name+"_lsb")
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2=indexReg, immediate = iterableLength, labelSymbol=iterable.name+"_msb")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=tmpRegLsb, reg2=tmpRegMsb)
|
||||
it += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=tmpRegLsb, labelSymbol = loopvarSymbol)
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=concatReg, reg2=tmpRegLsb, reg3=tmpRegMsb)
|
||||
it += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=concatReg, labelSymbol = loopvarSymbol)
|
||||
}
|
||||
result += translateNode(forLoop.statements)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
|
@ -1,7 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register.
|
||||
- IR: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction
|
||||
|
||||
...
|
||||
|
@ -99,16 +99,16 @@ bles reg1, value, address - jump to location in program given by l
|
||||
( NOTE: there are no bltr/bler instructions because these are equivalent to bgtr/bger with the register operands swapped around.)
|
||||
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 - set reg1=1 if reg1 == reg2, else 0
|
||||
sne reg1, reg2 - set reg1=1 if reg1 != reg2, else 0
|
||||
slt reg1, reg2 - set reg1=1 if reg1 < reg2 (unsigned), else 0
|
||||
slts reg1, reg2 - set reg1=1 if reg1 < reg2 (signed), else 0
|
||||
sle reg1, reg2 - set reg1=1 if reg1 <= reg2 (unsigned), else 0
|
||||
sles reg1, reg2 - set reg1=1 if reg1 <= reg2 (signed), else 0
|
||||
sgt reg1, reg2 - set reg1=1 if reg1 > reg2 (unsigned), else 0
|
||||
sgts reg1, reg2 - set reg1=1 if reg1 > reg2 (signed), else 0
|
||||
sge reg1, reg2 - set reg1=1 if reg1 >= reg2 (unsigned), else 0
|
||||
sges reg1, reg2 - set reg1=1 if reg1 >= reg2 (signed), 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
|
||||
sles reg1, reg2, reg3 - set reg1=1 if reg2 <= reg3 (signed), else 0
|
||||
sgt reg1, reg2, reg3 - set reg1=1 if reg2 > reg3 (unsigned), else 0
|
||||
sgts reg1, reg2, reg3 - set reg1=1 if reg2 > reg3 (signed), else 0
|
||||
sge reg1, reg2, reg3 - set reg1=1 if reg2 >= reg3 (unsigned), else 0
|
||||
sges reg1, reg2, reg3 - set reg1=1 if reg2 >= reg3 (signed), else 0
|
||||
(note: on the M68k these instructions will set all bits to 1 (so value=-1 instead of 1), but the boolean logic here requires it to be 0 or 1 in this IR)
|
||||
|
||||
|
||||
@ -220,7 +220,7 @@ sec - set Carry status bit
|
||||
nop - do nothing
|
||||
breakpoint - trigger a breakpoint
|
||||
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
|
||||
concat [b, w] reg1, reg2 - reg1 = concatenated lsb/lsw of reg1 (as lsb) and lsb/lsw of reg2 (as msb) into word or int (int not yet implemented; requires 32bits regs)
|
||||
concat [b, w] reg1, reg2, reg3 - reg1.w = concatenated lsb/lsw of reg2 (as lsb) and lsb/lsw of reg3 (as msb) into word or int (int not yet implemented; requires 32bits regs)
|
||||
push [b, w, f] reg1 - push value in reg1 on the stack
|
||||
pop [b, w, f] reg1 - pop value from stack into reg1
|
||||
*/
|
||||
@ -454,6 +454,7 @@ enum class OperandDirection {
|
||||
data class InstructionFormat(val datatype: IRDataType?,
|
||||
val reg1: OperandDirection,
|
||||
val reg2: OperandDirection,
|
||||
val reg3: OperandDirection,
|
||||
val fpReg1: OperandDirection,
|
||||
val fpReg2: OperandDirection,
|
||||
val address: OperandDirection,
|
||||
@ -466,6 +467,7 @@ data class InstructionFormat(val datatype: IRDataType?,
|
||||
for(part in spec.split('|').map{ it.trim() }) {
|
||||
var reg1 = OperandDirection.UNUSED
|
||||
var reg2 = OperandDirection.UNUSED
|
||||
var reg3 = OperandDirection.UNUSED
|
||||
var fpreg1 = OperandDirection.UNUSED
|
||||
var fpreg2 = OperandDirection.UNUSED
|
||||
var address = OperandDirection.UNUSED
|
||||
@ -480,6 +482,7 @@ data class InstructionFormat(val datatype: IRDataType?,
|
||||
">r1" -> reg1 = OperandDirection.WRITE
|
||||
"<>r1" -> reg1 = OperandDirection.READWRITE
|
||||
"<r2" -> reg2 = OperandDirection.READ
|
||||
"<r3" -> reg3 = OperandDirection.READ
|
||||
"<fr1" -> fpreg1 = OperandDirection.READ
|
||||
">fr1" -> fpreg1 = OperandDirection.WRITE
|
||||
"<>fr1" -> fpreg1 = OperandDirection.READWRITE
|
||||
@ -496,13 +499,13 @@ data class InstructionFormat(val datatype: IRDataType?,
|
||||
}
|
||||
|
||||
if(typespec=="N")
|
||||
result[null] = InstructionFormat(null, reg1, reg2, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
result[null] = InstructionFormat(null, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
if('B' in typespec)
|
||||
result[IRDataType.BYTE] = InstructionFormat(IRDataType.BYTE, reg1, reg2, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
result[IRDataType.BYTE] = InstructionFormat(IRDataType.BYTE, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
if('W' in typespec)
|
||||
result[IRDataType.WORD] = InstructionFormat(IRDataType.WORD, reg1, reg2, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
result[IRDataType.WORD] = InstructionFormat(IRDataType.WORD, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
if('F' in typespec)
|
||||
result[IRDataType.FLOAT] = InstructionFormat(IRDataType.FLOAT, reg1, reg2, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
result[IRDataType.FLOAT] = InstructionFormat(IRDataType.FLOAT, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -566,16 +569,16 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.BLES to InstructionFormat.from("BW,<r1,<i,<a"),
|
||||
Opcode.SZ to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.SNZ to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGES 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"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.SGES to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.INC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
Opcode.INCM to InstructionFormat.from("BW,<>a | F,<>a"),
|
||||
Opcode.DEC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
@ -663,7 +666,7 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.MSIG to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.PUSH to InstructionFormat.from("BW,<r1 | F,<fr1"),
|
||||
Opcode.POP to InstructionFormat.from("BW,>r1 | F,>fr1"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
|
||||
Opcode.CLC to InstructionFormat.from("N"),
|
||||
Opcode.SEC to InstructionFormat.from("N"),
|
||||
Opcode.BREAKPOINT to InstructionFormat.from("N"),
|
||||
@ -683,6 +686,7 @@ data class IRInstruction(
|
||||
val type: IRDataType?=null,
|
||||
val reg1: Int?=null, // 0-$ffff
|
||||
val reg2: Int?=null, // 0-$ffff
|
||||
val reg3: Int?=null, // 0-$ffff
|
||||
val fpReg1: Int?=null, // 0-$ffff
|
||||
val fpReg2: Int?=null, // 0-$ffff
|
||||
val immediate: Int?=null, // 0-$ff or $ffff if word
|
||||
@ -696,6 +700,7 @@ data class IRInstruction(
|
||||
// This knowledge is useful in IL assembly optimizers to see how registers are used.
|
||||
val reg1direction: OperandDirection
|
||||
val reg2direction: OperandDirection
|
||||
val reg3direction: OperandDirection
|
||||
val fpReg1direction: OperandDirection
|
||||
val fpReg2direction: OperandDirection
|
||||
|
||||
@ -703,9 +708,12 @@ data class IRInstruction(
|
||||
require(labelSymbol?.first()!='_') {"label/symbol should not start with underscore $labelSymbol"}
|
||||
require(reg1==null || reg1 in 0..65536) {"reg1 out of bounds"}
|
||||
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
|
||||
require(reg3==null || reg3 in 0..65536) {"reg3 out of bounds"}
|
||||
require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"}
|
||||
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
|
||||
if(reg1!=null && reg2!=null) require(reg1!=reg2) {"reg1 must not be same as reg2"} // note: this is ok for fpRegs as these are always the same type
|
||||
if(reg1!=null && reg3!=null) require(reg1!=reg3) {"reg1 must not be same as reg3"} // note: this is ok for fpRegs as these are always the same type
|
||||
if(reg2!=null && reg3!=null) require(reg2!=reg3) {"reg2 must not be same as reg3"} // note: this is ok for fpRegs as these are always the same type
|
||||
|
||||
val formats = instructionFormats.getValue(opcode)
|
||||
require (type != null || formats.containsKey(null)) { "missing type" }
|
||||
@ -713,10 +721,12 @@ data class IRInstruction(
|
||||
val format = formats.getOrElse(type) { throw IllegalArgumentException("type $type invalid for $opcode") }
|
||||
if(format.reg1!=OperandDirection.UNUSED) require(reg1!=null) { "missing reg1" }
|
||||
if(format.reg2!=OperandDirection.UNUSED) require(reg2!=null) { "missing reg2" }
|
||||
if(format.reg3!=OperandDirection.UNUSED) require(reg3!=null) { "missing reg3" }
|
||||
if(format.fpReg1!=OperandDirection.UNUSED) require(fpReg1!=null) { "missing fpReg1" }
|
||||
if(format.fpReg2!=OperandDirection.UNUSED) require(fpReg2!=null) { "missing fpReg2" }
|
||||
if(format.reg1==OperandDirection.UNUSED) require(reg1==null) { "invalid reg1" }
|
||||
if(format.reg2==OperandDirection.UNUSED) require(reg2==null) { "invalid reg2" }
|
||||
if(format.reg3==OperandDirection.UNUSED) require(reg3==null) { "invalid reg3" }
|
||||
if(format.fpReg1==OperandDirection.UNUSED) require(fpReg1==null) { "invalid fpReg1" }
|
||||
if(format.fpReg2==OperandDirection.UNUSED) require(fpReg2==null) { "invalid fpReg2" }
|
||||
if(format.immediate) {
|
||||
@ -747,6 +757,7 @@ data class IRInstruction(
|
||||
|
||||
reg1direction = format.reg1
|
||||
reg2direction = format.reg2
|
||||
reg3direction = format.reg3
|
||||
fpReg1direction = format.fpReg1
|
||||
fpReg2direction = format.fpReg2
|
||||
|
||||
@ -814,6 +825,19 @@ data class IRInstruction(
|
||||
}
|
||||
else -> throw IllegalArgumentException("reg2 can only be read")
|
||||
}
|
||||
when (this.reg3direction) {
|
||||
OperandDirection.UNUSED -> {}
|
||||
OperandDirection.READ -> {
|
||||
writeRegsCounts[this.reg3!!] = writeRegsCounts.getValue(this.reg3)+1
|
||||
if(type!=null) {
|
||||
var types = regsTypes[this.reg3]
|
||||
if(types==null) types = mutableSetOf()
|
||||
types += type
|
||||
regsTypes[this.reg3] = types
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("reg3 can only be read")
|
||||
}
|
||||
when (this.fpReg1direction) {
|
||||
OperandDirection.UNUSED -> {}
|
||||
OperandDirection.READ -> {
|
||||
@ -927,6 +951,10 @@ data class IRInstruction(
|
||||
result.add("r$it")
|
||||
result.add(",")
|
||||
}
|
||||
reg3?.let {
|
||||
result.add("r$it")
|
||||
result.add(",")
|
||||
}
|
||||
fpReg1?.let {
|
||||
result.add("fr$it")
|
||||
result.add(",")
|
||||
|
@ -115,6 +115,7 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
val operands = if(rest.isBlank()) emptyList() else rest.split(",").map{ it.trim() }.toMutableList()
|
||||
var reg1: Int? = null
|
||||
var reg2: Int? = null
|
||||
var reg3: Int? = null
|
||||
var fpReg1: Int? = null
|
||||
var fpReg2: Int? = null
|
||||
var immediateInt: Int? = null
|
||||
@ -143,6 +144,7 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
else if (oper[0] in "rR") {
|
||||
if (reg1 == null) reg1 = oper.substring(1).toInt()
|
||||
else if (reg2 == null) reg2 = oper.substring(1).toInt()
|
||||
else if (reg3 == null) reg3 = oper.substring(1).toInt()
|
||||
else throw IRParseException("too many register operands")
|
||||
} else if (oper[0] in "fF" && oper[1] in "rR") {
|
||||
if (fpReg1 == null) fpReg1 = oper.substring(2).toInt()
|
||||
@ -179,6 +181,8 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
throw IRParseException("needs reg1 for $line")
|
||||
if(format.reg2!=OperandDirection.UNUSED && reg2==null)
|
||||
throw IRParseException("needs reg2 for $line")
|
||||
if(format.reg3!=OperandDirection.UNUSED && reg3==null)
|
||||
throw IRParseException("needs reg3 for $line")
|
||||
if(format.fpReg1!=OperandDirection.UNUSED && fpReg1==null)
|
||||
throw IRParseException("needs fpReg1 for $line")
|
||||
if(format.fpReg2!=OperandDirection.UNUSED && fpReg2==null)
|
||||
@ -189,6 +193,8 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
throw IRParseException("invalid reg1 for $line")
|
||||
if(format.reg2==OperandDirection.UNUSED && reg2!=null)
|
||||
throw IRParseException("invalid reg2 for $line")
|
||||
if(format.reg3==OperandDirection.UNUSED && reg3!=null)
|
||||
throw IRParseException("invalid reg3 for $line")
|
||||
if(format.fpReg1==OperandDirection.UNUSED && fpReg1!=null)
|
||||
throw IRParseException("invalid fpReg1 for $line")
|
||||
if(format.fpReg2==OperandDirection.UNUSED && fpReg2!=null)
|
||||
@ -218,7 +224,7 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
|
||||
throw IRParseException("labelsymbol confused with register?: $labelSymbol")
|
||||
}
|
||||
|
||||
return left(IRInstruction(opcode, type, reg1, reg2, fpReg1, fpReg2, immediateInt, immediateFp, address, labelSymbol = labelSymbol))
|
||||
return left(IRInstruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, immediateInt, immediateFp, address, labelSymbol = labelSymbol))
|
||||
}
|
||||
|
||||
private class ParsedCall(
|
||||
|
@ -808,14 +808,24 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
}
|
||||
|
||||
private fun InsSZ(i: IRInstruction) {
|
||||
val (_: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
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 (_: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
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()
|
||||
@ -889,7 +899,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
val value = if(left>=right) 1 else 0
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
nextPc()
|
||||
|
||||
}
|
||||
|
||||
private fun InsINC(i: IRInstruction) {
|
||||
@ -2106,8 +2115,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
private fun InsCONCAT(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> {
|
||||
val lsb = registers.getUB(i.reg1!!)
|
||||
val msb = registers.getUB(i.reg2!!)
|
||||
val lsb = registers.getUB(i.reg2!!)
|
||||
val msb = registers.getUB(i.reg3!!)
|
||||
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
}
|
||||
IRDataType.WORD -> throw IllegalArgumentException("concat.w not yet supported, requires 32-bits registers")
|
||||
@ -2305,8 +2314,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun getSetOnConditionOperands(ins: IRInstruction): Pair<Int, Int> {
|
||||
return when(ins.type) {
|
||||
IRDataType.BYTE -> Pair(registers.getSB(ins.reg1!!).toInt(), registers.getSB(ins.reg2!!).toInt())
|
||||
IRDataType.WORD -> Pair(registers.getSW(ins.reg1!!).toInt(), registers.getSW(ins.reg2!!).toInt())
|
||||
IRDataType.BYTE -> Pair(registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
||||
IRDataType.WORD -> Pair(registers.getSW(ins.reg2!!).toInt(), registers.getSW(ins.reg3!!).toInt())
|
||||
IRDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
@ -2316,8 +2325,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun getSetOnConditionOperandsU(ins: IRInstruction): Pair<UInt, UInt> {
|
||||
return when(ins.type) {
|
||||
IRDataType.BYTE -> Pair(registers.getUB(ins.reg1!!).toUInt(), registers.getUB(ins.reg2!!).toUInt())
|
||||
IRDataType.WORD -> Pair(registers.getUW(ins.reg1!!).toUInt(), registers.getUW(ins.reg2!!).toUInt())
|
||||
IRDataType.BYTE -> Pair(registers.getUB(ins.reg2!!).toUInt(), registers.getUB(ins.reg3!!).toUInt())
|
||||
IRDataType.WORD -> Pair(registers.getUW(ins.reg2!!).toUInt(), registers.getUW(ins.reg3!!).toUInt())
|
||||
IRDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user