mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
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:
parent
ac21e1be5c
commit
090820958e
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
...
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user