diff --git a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt index 6241cffb4..723abf1d7 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt @@ -111,21 +111,21 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen: code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister) } DataType.BYTE -> { - val andReg = codeGen.vmRegisters.nextFree() val notNegativeLabel = codeGen.createLabelName() - code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80) - code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister) - code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=andReg, labelSymbol = notNegativeLabel) + val compareReg = codeGen.vmRegisters.nextFree() + code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=compareReg, reg2=resultRegister) + code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=compareReg, value=0x80) + code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=compareReg, labelSymbol = notNegativeLabel) code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister) code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister) code += VmCodeLabel(notNegativeLabel) } DataType.WORD -> { - val andReg = codeGen.vmRegisters.nextFree() val notNegativeLabel = codeGen.createLabelName() - code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000) - code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister) - code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=andReg, labelSymbol = notNegativeLabel) + val compareReg = codeGen.vmRegisters.nextFree() + code += VmCodeInstruction(Opcode.LOADR, VmDataType.WORD, reg1=compareReg, reg2=resultRegister) + code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=compareReg, value=0x8000) + code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=compareReg, labelSymbol = notNegativeLabel) code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister) code += VmCodeLabel(notNegativeLabel) } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index 50a4be922..3ad81d0ff 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -149,10 +149,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) { code += VmCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister) } "~" -> { - val regMask = codeGen.vmRegisters.nextFree() val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff - code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask) - code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask) + code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, value=mask) } else -> throw AssemblyError("weird prefix operator") } @@ -390,9 +388,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { code += translate(comparisonCall, resultRegister, -1) if(!notEquals) code += VmCodeInstruction(Opcode.INV, vmDt, reg1=resultRegister) - val maskReg = codeGen.vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=maskReg, value=1) - code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=maskReg) + code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1) } else { val rightResultReg = codeGen.vmRegisters.nextFree() code += translateExpression(binExpr.left, resultRegister, -1) @@ -462,10 +458,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun operatorXor(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - val rightResultReg = codeGen.vmRegisters.nextFree() - code += translateExpression(binExpr.left, resultRegister, -1) - code += translateExpression(binExpr.right, rightResultReg, -1) - code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=rightResultReg) + if(binExpr.right is PtNumber) { + code += translateExpression(binExpr.left, resultRegister, -1) + code += VmCodeInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) + } else { + val rightResultReg = codeGen.vmRegisters.nextFree() + code += translateExpression(binExpr.left, resultRegister, -1) + code += translateExpression(binExpr.right, rightResultReg, -1) + code += VmCodeInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) + } return code } @@ -479,10 +480,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - val rightResultReg = codeGen.vmRegisters.nextFree() - code += translateExpression(binExpr.left, resultRegister, -1) - code += translateExpression(binExpr.right, rightResultReg, -1) - code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=rightResultReg) + if(binExpr.right is PtNumber) { + code += translateExpression(binExpr.left, resultRegister, -1) + code += VmCodeInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) + } else { + val rightResultReg = codeGen.vmRegisters.nextFree() + code += translateExpression(binExpr.left, resultRegister, -1) + code += translateExpression(binExpr.right, rightResultReg, -1) + code += VmCodeInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) + } return code } @@ -496,10 +502,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun operatorOr(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - val rightResultReg = codeGen.vmRegisters.nextFree() - code += translateExpression(binExpr.left, resultRegister, -1) - code += translateExpression(binExpr.right, rightResultReg, -1) - code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=rightResultReg) + if(binExpr.right is PtNumber) { + code += translateExpression(binExpr.left, resultRegister, -1) + code += VmCodeInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt()) + } else { + val rightResultReg = codeGen.vmRegisters.nextFree() + code += translateExpression(binExpr.left, resultRegister, -1) + code += translateExpression(binExpr.right, rightResultReg, -1) + code += VmCodeInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg) + } return code } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 80dd49d4b..11e3168d1 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: add logical instructions taking immediate value as well +- fix compiler crash (abs(fl)) ; WHY IS THIS GETTING A BOOLEAN CAST??? +- vm why is bb = bb2 and true generating so large code? ... diff --git a/examples/test.p8 b/examples/test.p8 index cbe41fc5b..01f06abc5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,18 +1,13 @@ %import textio +%import floats %zeropage basicsafe main { sub start() { - bool @shared zz - ubyte xx - ubyte yy - - while xx<42 { - xx = yy+99 - xx = yy*5 - } - - txt.print_ub(xx) + float fl + fl = -3.14 + floats.print_f(abs(fl)) ; WHY IS THIS GETTING A BOOLEAN CAST??? + txt.nl() } } diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index 01b27cb31..67f216bf3 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -126,9 +126,12 @@ LOGICAL/BITWISE --------------- All have type b or w. -and reg1, reg2 - reg1 = reg1 bitwise and reg2 -or reg1, reg2 - reg1 = reg1 bitwise or reg2 -xor reg1, reg2 - reg1 = reg1 bitwise xor reg2 +andr reg1, reg2 - reg1 = reg1 bitwise and reg2 +and reg1, value - reg1 = reg1 bitwise and value +orr reg1, reg2 - reg1 = reg1 bitwise or reg2 +or reg1, value - reg1 = reg1 bitwise or value +xorr reg1, reg2 - reg1 = reg1 bitwise xor reg2 +xor reg1, value - reg1 = reg1 bitwise xor value inv reg1 - reg1 = bitwise invert of reg1 (all bits flipped) lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit @@ -265,10 +268,13 @@ enum class Opcode { EXT, EXTS, + ANDR, AND, ANDM, + ORR, OR, ORM, + XORR, XOR, XORM, INV, @@ -567,11 +573,14 @@ val instructionFormats = mutableMapOf( Opcode.CMP to InstructionFormat.from("BW,r1,r2"), Opcode.EXT to InstructionFormat.from("BW,r1"), Opcode.EXTS to InstructionFormat.from("BW,r1"), - Opcode.AND to InstructionFormat.from("BW,r1,r2"), + Opcode.ANDR to InstructionFormat.from("BW,r1,r2"), + Opcode.AND to InstructionFormat.from("BW,r1,v"), Opcode.ANDM to InstructionFormat.from("BW,r1,v"), - Opcode.OR to InstructionFormat.from("BW,r1,r2"), + Opcode.ORR to InstructionFormat.from("BW,r1,r2"), + Opcode.OR to InstructionFormat.from("BW,r1,v"), Opcode.ORM to InstructionFormat.from("BW,r1,v"), - Opcode.XOR to InstructionFormat.from("BW,r1,r2"), + Opcode.XORR to InstructionFormat.from("BW,r1,r2"), + Opcode.XOR to InstructionFormat.from("BW,r1,v"), Opcode.XORM to InstructionFormat.from("BW,r1,v"), Opcode.INV to InstructionFormat.from("BW,r1"), Opcode.INVM to InstructionFormat.from("BW,v"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 271220984..e7eeff361 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -163,10 +163,13 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.SQRT -> InsSQRT(ins) Opcode.EXT -> InsEXT(ins) Opcode.EXTS -> InsEXTS(ins) + Opcode.ANDR -> InsANDR(ins) Opcode.AND -> InsAND(ins) Opcode.ANDM -> InsANDM(ins) + Opcode.ORR -> InsORR(ins) Opcode.OR -> InsOR(ins) Opcode.ORM -> InsORM(ins) + Opcode.XORR -> InsXORR(ins) Opcode.XOR -> InsXOR(ins) Opcode.XORM ->InsXORM(ins) Opcode.INV -> InsINV(ins) @@ -1295,7 +1298,7 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsAND(i: Instruction) { + private fun InsANDR(i: Instruction) { val (left: UInt, right: UInt) = getLogicalOperandsU(i) when(i.type!!) { VmDataType.BYTE -> registers.setUB(i.reg1!!, (left and right).toUByte()) @@ -1305,6 +1308,15 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsAND(i: Instruction) { + when(i.type!!) { + VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) and i.value!!.toUByte()) + VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) and i.value!!.toUShort()) + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsANDM(i: Instruction) { val address = i.value!! when(i.type!!) { @@ -1323,7 +1335,7 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsOR(i: Instruction) { + private fun InsORR(i: Instruction) { val (left: UInt, right: UInt) = getLogicalOperandsU(i) when(i.type!!) { VmDataType.BYTE -> registers.setUB(i.reg1!!, (left or right).toUByte()) @@ -1333,6 +1345,15 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsOR(i: Instruction) { + when(i.type!!) { + VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) or i.value!!.toUByte()) + VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) or i.value!!.toUShort()) + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsORM(i: Instruction) { val address = i.value!! when(i.type!!) { @@ -1351,7 +1372,7 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsXOR(i: Instruction) { + private fun InsXORR(i: Instruction) { val (left: UInt, right: UInt) = getLogicalOperandsU(i) when(i.type!!) { VmDataType.BYTE -> registers.setUB(i.reg1!!, (left xor right).toUByte()) @@ -1361,6 +1382,15 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsXOR(i: Instruction) { + when(i.type!!) { + VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) xor i.value!!.toUByte()) + VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) xor i.value!!.toUShort()) + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsXORM(i: Instruction) { val address = i.value!! when(i.type!!) {