ir divmod returns its results on valuestack, to keep consistency with the rule that only 1 register can be a returnvalue

This commit is contained in:
Irmen de Jong 2023-04-10 15:23:20 +02:00
parent ac21e1be5c
commit 090820958e
4 changed files with 31 additions and 17 deletions

View File

@ -52,20 +52,28 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val result = mutableListOf<IRCodeChunkBase>()
val number = call.args[0]
val divident = call.args[1]
val divisionReg: Int
val remainderReg: Int
if(divident is PtNumber) {
val tr = exprGen.translateExpression(number)
addToResult(result, tr, tr.resultReg, -1)
addInstr(result, IRInstruction(Opcode.DIVMOD, type, reg1 = tr.resultReg, immediate = divident.number.toInt()), null)
divisionReg = tr.resultReg
remainderReg = codeGen.registers.nextFree()
} else {
val numTr = exprGen.translateExpression(number)
addToResult(result, numTr, numTr.resultReg, -1)
val dividentTr = exprGen.translateExpression(divident)
addToResult(result, dividentTr, dividentTr.resultReg, -1)
addInstr(result, IRInstruction(Opcode.DIVMODR, type, reg1 = numTr.resultReg, reg2=dividentTr.resultReg), null)
divisionReg = numTr.resultReg
remainderReg = dividentTr.resultReg
}
// DIVMOD result convention: division in r0, remainder in r1
result += assignRegisterTo(call.args[2], 0)
result += assignRegisterTo(call.args[3], 1)
// DIVMOD result convention: on value stack, division and remainder on top.
addInstr(result, IRInstruction(Opcode.POP, type, reg1=remainderReg), null)
addInstr(result, IRInstruction(Opcode.POP, type, reg1=divisionReg), null)
result += assignRegisterTo(call.args[2], divisionReg)
result += assignRegisterTo(call.args[3], remainderReg)
return ExpressionCodeResult(result, type, -1, -1)
}

View File

@ -3,6 +3,8 @@ TODO
For next minor release
^^^^^^^^^^^^^^^^^^^^^^
change syscalls to output results on value stack
change syscalls to take parameters on value stack (not in r65500+ registers)
...

View File

@ -130,8 +130,8 @@ divs reg1, value - signed division reg1 /= value not
divsm reg1, address - signed memory at address /= reg2 note: division by zero yields max signed int 127 / 32767
modr reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
mod reg1, value - remainder (modulo) of unsigned division reg1 %= value note: division by zero yields max signed int $ff/$ffff
divmodr reg1, reg2 - unsigned division reg1/reg2, storing division in r0 and remainder in r2 (by convention, because we can't specify enough registers in the instruction)
divmod reg1, value - unsigned division reg1/value, storing division in r0 and remainder in r2 (by convention, because we can't specify enough registers in the instruction)
divmodr reg1, reg2 - unsigned division reg1/reg2, storing division and remainder on value stack (so need to be POPped off)
divmod reg1, value - unsigned division reg1/value, storing division and remainder on value stack (so need to be POPped off)
sqrt reg1, reg2 - reg1 is the square root of reg2
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)

View File

@ -1188,8 +1188,8 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsDIVMODR(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> divAndModUByte(i.reg1!!, i.reg2!!) // output in r0+r1
IRDataType.WORD -> divAndModUWord(i.reg1!!, i.reg2!!) // output in r0+r1
IRDataType.BYTE -> divAndModUByte(i.reg1!!, i.reg2!!) // division+remainder results on value stack
IRDataType.WORD -> divAndModUWord(i.reg1!!, i.reg2!!) // division+remainder results on value stack
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@ -1197,8 +1197,8 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsDIVMOD(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> divAndModConstUByte(i.reg1!!, i.immediate!!.toUByte()) // output in r0+r1
IRDataType.WORD -> divAndModConstUWord(i.reg1!!, i.immediate!!.toUShort()) // output in r0+r1
IRDataType.BYTE -> divAndModConstUByte(i.reg1!!, i.immediate!!.toUByte()) // division+remainder results on value stack
IRDataType.WORD -> divAndModConstUWord(i.reg1!!, i.immediate!!.toUShort()) // division+remainder results on value stack
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@ -1375,16 +1375,16 @@ class VirtualMachine(irProgram: IRProgram) {
val right = registers.getUB(reg2)
val division = if(right==0.toUByte()) 0xffu else left / right
val remainder = if(right==0.toUByte()) 0xffu else left % right
registers.setUB(0, division.toUByte())
registers.setUB(1, remainder.toUByte())
valueStack.push(division.toUByte())
valueStack.push(remainder.toUByte())
}
private fun divAndModConstUByte(reg1: Int, value: UByte) {
val left = registers.getUB(reg1)
val division = if(value==0.toUByte()) 0xffu else left / value
val remainder = if(value==0.toUByte()) 0xffu else left % value
registers.setUB(0, division.toUByte())
registers.setUB(1, remainder.toUByte())
valueStack.push(division.toUByte())
valueStack.push(remainder.toUByte())
}
private fun divAndModUWord(reg1: Int, reg2: Int) {
@ -1392,16 +1392,20 @@ class VirtualMachine(irProgram: IRProgram) {
val right = registers.getUW(reg2)
val division = if(right==0.toUShort()) 0xffffu else left / right
val remainder = if(right==0.toUShort()) 0xffffu else left % right
registers.setUW(0, division.toUShort())
registers.setUW(1, remainder.toUShort())
valueStack.push((division and 255u).toUByte())
valueStack.push((division.toInt() ushr 8).toUByte())
valueStack.push((remainder and 255u).toUByte())
valueStack.push((remainder.toInt() ushr 8).toUByte())
}
private fun divAndModConstUWord(reg1: Int, value: UShort) {
val left = registers.getUW(reg1)
val division = if(value==0.toUShort()) 0xffffu else left / value
val remainder = if(value==0.toUShort()) 0xffffu else left % value
registers.setUW(0, division.toUShort())
registers.setUW(1, remainder.toUShort())
valueStack.push((division and 255u).toUByte())
valueStack.push((division.toInt() ushr 8).toUByte())
valueStack.push((remainder and 255u).toUByte())
valueStack.push((remainder.toInt() ushr 8).toUByte())
}
private fun divModByteUnsignedInplace(operator: String, reg1: Int, address: Int) {