ir: remove remaining SL* opcodes

This commit is contained in:
Irmen de Jong 2024-12-27 21:00:06 +01:00
parent af7930d494
commit 427451a23f
6 changed files with 53 additions and 86 deletions

View File

@ -869,7 +869,6 @@ 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)
@ -877,15 +876,29 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addToResult(result, rightTr, -1, rightTr.resultFpReg)
val resultRegister = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.FCOMP, IRDataType.FLOAT, reg1=resultRegister, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
val zeroRegister = codeGen.registers.nextFree()
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=zeroRegister, immediate = 0), null)
val ins = if (signed) {
if (greaterEquals) Opcode.SGES else Opcode.SGTS
addInstr(result, IRInstruction(Opcode.CMPI, IRDataType.BYTE, reg1=resultRegister, immediate = 0), null)
val other = codeGen.createLabelName()
val after = codeGen.createLabelName()
val resultReg = codeGen.registers.nextFree()
// TODO can this be done more efficiently? also see operatorLessThan
if(greaterEquals) {
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.BSTPOS, 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)
} else {
if (greaterEquals) Opcode.SGE else Opcode.SGT
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.BSTNEG, labelSymbol = other)
it += IRInstruction(Opcode.BSTEQ, labelSymbol = other)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = resultReg, immediate = 1)
it += IRInstruction(Opcode.JUMP, labelSymbol = after)
}
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=resultReg, immediate = 0), other)
}
addInstr(result, IRInstruction(ins, IRDataType.BYTE, reg1=cmpResultReg, reg2 = resultRegister, reg3 = zeroRegister), null)
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultReg, -1)
result += IRCodeChunk(after, null)
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
} else {
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")
@ -894,13 +907,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
addToResult(result, leftTr, leftTr.resultReg, -1)
val rightTr = translateExpression(binExpr.right)
addToResult(result, rightTr, rightTr.resultReg, -1)
val ins = if (signed) {
if (greaterEquals) Opcode.SGES else Opcode.SGTS
val branch = if (signed) {
if (greaterEquals) Opcode.BGESR else Opcode.BGTSR
} else {
if (greaterEquals) Opcode.SGE else Opcode.SGT
if (greaterEquals) Opcode.BGER else Opcode.BGTR
}
addInstr(result, IRInstruction(ins, vmDt, reg1=cmpResultReg, reg2 = leftTr.resultReg, reg3 = rightTr.resultReg), null)
return ExpressionCodeResult(result, IRDataType.BYTE, cmpResultReg, -1)
val resultReg = compareRegisterAsBooleanResult(branch, leftTr.dt, leftTr.resultReg, rightTr.resultReg, result)
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
}
}
}
@ -923,7 +936,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
val other = codeGen.createLabelName()
val after = codeGen.createLabelName()
val resultReg = codeGen.registers.nextFree()
// TODO can this be done more efficiently?
// TODO can this be done more efficiently? also see operatorGreaterThan
if(lessEquals) {
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.BSTNEG, labelSymbol = other)

View File

@ -351,15 +351,6 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
}
}
}
// a SNZ etc. whose target register is not used can be removed altogether
if(ins.opcode in OpcodesThatSetRegFromStatusbits) {
val usages = regUsages(ins.reg1!!)
if(usages.toList().sumOf { it.second } <= 1) {
chunk.instructions.removeAt(idx)
changed = true
}
}
}
return changed
}

View File

@ -1,6 +1,8 @@
TODO
====
- addUsedRegistersCounts() doesn't always determine the datatype correctly. --> GET RID OF THE Sxxx OPCODES FOR NOW?
- add paypal donation button as well?
- announce prog8 on the 6502.org site?
@ -54,9 +56,8 @@ 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?
- add BZ and BNZ instructions? To replace CMPI #0 + Branch?
- fix TODO("IR rol/ror on split words array")
- fix "<< in array" / ">> in array"
- implement missing operators in AssignmentGen (array shifts etc)

View File

@ -12,19 +12,34 @@ main {
cx16.r0 = $aaaa
cx16.r1 = $2222
f1 = 9999
cx16.r0=9999
txt.print_bool(f1 < 8000)
f1 = 10000
cx16.r0=10000
; true false false
; true true false
; times 2.
txt.print_bool(f1 > 8000)
txt.spc()
txt.print_bool(f1 < 10000)
txt.print_bool(f1 > 10000)
txt.spc()
txt.print_bool(f1 < 20000)
txt.print_bool(f1 > 20000)
txt.nl()
txt.print_bool(cx16.r0 < 8000)
txt.print_bool(f1 >= 8000)
txt.spc()
txt.print_bool(cx16.r0 < 10000)
txt.print_bool(f1 >= 10000)
txt.spc()
txt.print_bool(cx16.r0 < 20000)
txt.print_bool(f1 >= 20000)
txt.nl()
txt.print_bool(cx16.r0 > 8000)
txt.spc()
txt.print_bool(cx16.r0 > 10000)
txt.spc()
txt.print_bool(cx16.r0 > 20000)
txt.nl()
txt.print_bool(cx16.r0 >= 8000)
txt.spc()
txt.print_bool(cx16.r0 >= 10000)
txt.spc()
txt.print_bool(cx16.r0 >= 20000)
txt.nl()
cx16.r0L=0

View File

@ -123,12 +123,6 @@ 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
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)
ARITHMETIC
----------
@ -313,10 +307,6 @@ enum class Opcode {
BGESR,
BGES,
BLES,
SGT,
SGTS,
SGE,
SGES,
INC,
INCM,
@ -505,13 +495,6 @@ val OpcodesThatDependOnCarry = arrayOf(
Opcode.ROXRM,
)
val OpcodesThatSetRegFromStatusbits = arrayOf(
Opcode.SGT,
Opcode.SGTS,
Opcode.SGE,
Opcode.SGES
)
val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThatSetStatusbitsIncludingCarry
@ -662,10 +645,6 @@ 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.SGT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
Opcode.SGTS 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"),

View File

@ -236,10 +236,6 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.BLE -> InsBLE(ins)
Opcode.BGES -> InsBGES(ins)
Opcode.BLES -> InsBLES(ins)
Opcode.SGT -> InsSGT(ins)
Opcode.SGTS -> InsSGTS(ins)
Opcode.SGE -> InsSGE(ins)
Opcode.SGES -> InsSGES(ins)
Opcode.INC -> InsINC(ins)
Opcode.INCM -> InsINCM(ins)
Opcode.DEC -> InsDEC(ins)
@ -885,34 +881,6 @@ class VirtualMachine(irProgram: IRProgram) {
nextPc()
}
private fun InsSGT(i: IRInstruction) {
val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left>right) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsSGTS(i: IRInstruction) {
val (left, right) = getSetOnConditionOperands(i)
val value = if(left>right) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsSGE(i: IRInstruction) {
val (left, right) = getSetOnConditionOperandsU(i)
val value = if(left>=right) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsSGES(i: IRInstruction) {
val (left, right) = getSetOnConditionOperands(i)
val value = if(left>=right) 1 else 0
setResultReg(i.reg1!!, value, i.type!!)
nextPc()
}
private fun InsINC(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {