mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
don't allow ~ on booleans, also introduce SZ and SNZ instructions in IR to complete the conditional-set instruction list.
This commit is contained in:
parent
1e6fa77633
commit
a7df094ff4
@ -72,27 +72,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
result
|
||||
}
|
||||
is PtTypeCast -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtPrefix -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtArrayIndexer -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtBuiltinFunctionCall -> {
|
||||
codeGen.translateBuiltinFunc(expr, resultRegister)
|
||||
}
|
||||
is PtFunctionCall -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtContainmentCheck -> {
|
||||
translate(expr, resultRegister, resultFpRegister)
|
||||
}
|
||||
is PtTypeCast -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtPrefix -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtArrayIndexer -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtBinaryExpression -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr, resultRegister)
|
||||
is PtFunctionCall -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtContainmentCheck -> translate(expr, resultRegister, resultFpRegister)
|
||||
is PtRange,
|
||||
is PtArray,
|
||||
is PtString -> throw AssemblyError("range/arrayliteral/string should no longer occur as expression")
|
||||
@ -430,11 +416,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
it += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value = 1)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.registers.nextFree()
|
||||
result += translateExpression(binExpr.left, resultRegister, -1)
|
||||
result += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null)
|
||||
if(constValue(binExpr.right)==0.0) {
|
||||
result += translateExpression(binExpr.left, resultRegister, -1)
|
||||
val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister), null)
|
||||
} else {
|
||||
val rightResultReg = codeGen.registers.nextFree()
|
||||
result += translateExpression(binExpr.left, resultRegister, -1)
|
||||
result += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
@ -835,6 +835,8 @@ internal class AstChecker(private val program: Program,
|
||||
else if(expr.operator == "~") {
|
||||
if(dt !in IntegerDatatypes)
|
||||
errors.err("can only use bitwise invert on integer types", expr.position)
|
||||
if(dt==DataType.BOOL)
|
||||
errors.err("bitwise invert is for integer types, use 'not' on booleans", expr.position)
|
||||
}
|
||||
super.visit(expr)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ For next release
|
||||
- make sure bool value is always 0 or 1 (all casts should convert), then:
|
||||
- rewrite bool=bool^1 into bool=not bool
|
||||
- should solve: bool bb = not bb -> larger code than bool bb ^= 1
|
||||
- should solve: bool xx = ~xx -> larger code than xx ^= 1
|
||||
|
||||
|
||||
...
|
||||
|
@ -85,16 +85,18 @@ bgts reg1, reg2, address - jump to location in program given by l
|
||||
bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned)
|
||||
bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed)
|
||||
( NOTE: there are no blt/ble instructions because these are equivalent to bgt/bge with the operands swapped around.)
|
||||
seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0
|
||||
sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0
|
||||
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0
|
||||
sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
|
||||
sges reg1, reg2 - set reg=1 if reg1 >= reg2 (signed), otherwise set reg1=0
|
||||
sz reg1, reg2 - set reg1=1 if reg2==0, otherwise set reg1=0
|
||||
snz reg1, reg2 - set reg1=1 if reg2!=0, otherwise set reg1=0
|
||||
seq reg1, reg2 - set reg1=1 if reg1 == reg2, otherwise set reg1=0
|
||||
sne reg1, reg2 - set reg1=1 if reg1 != reg2, otherwise set reg1=0
|
||||
slt reg1, reg2 - set reg1=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2 - set reg1=1 if reg1 < reg2 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2 - set reg1=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2 - set reg1=1 if reg1 <= reg2 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2 - set reg1=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2 - set reg1=1 if reg1 > reg2 (signed), otherwise set reg1=0
|
||||
sge reg1, reg2 - set reg1=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
|
||||
sges reg1, reg2 - set reg1=1 if reg1 >= reg2 (signed), otherwise set reg1=0
|
||||
|
||||
|
||||
ARITHMETIC
|
||||
@ -253,6 +255,8 @@ enum class Opcode {
|
||||
BGTS,
|
||||
BGE,
|
||||
BGES,
|
||||
SZ,
|
||||
SNZ,
|
||||
SEQ,
|
||||
SNE,
|
||||
SLT,
|
||||
@ -569,6 +573,8 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.BGTS to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGE to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
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"),
|
||||
|
@ -186,6 +186,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.BGTS -> InsBGTS(ins)
|
||||
Opcode.BGE -> InsBGEU(ins)
|
||||
Opcode.BGES -> InsBGES(ins)
|
||||
Opcode.SZ -> InsSZ(ins)
|
||||
Opcode.SNZ -> InsSNZ(ins)
|
||||
Opcode.SEQ -> InsSEQ(ins)
|
||||
Opcode.SNE -> InsSNE(ins)
|
||||
Opcode.SLT -> InsSLT(ins)
|
||||
@ -782,6 +784,20 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSZ(i: IRInstruction) {
|
||||
val (_: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
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 value = if(right!=0) 1 else 0
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSEQ(i: IRInstruction) {
|
||||
val (left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left==right) 1 else 0
|
||||
|
Loading…
Reference in New Issue
Block a user