diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt index 8f3348492..e9c4c01b6 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt @@ -90,6 +90,8 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio "|" -> return expressionEval.operatorOrInplace(address, vmDt, operand) "&" -> return expressionEval.operatorAndInplace(address, vmDt, operand) "^" -> return expressionEval.operatorXorInplace(address, vmDt, operand) + "<<" -> return expressionEval.operatorShiftLeftInplace(address, vmDt, operand) + ">>" -> return expressionEval.operatorShiftRightInplace(address, vmDt, signed, operand) else -> {} } return fallbackAssign(origAssign) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 029a857e7..ef2d65074 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -446,21 +446,13 @@ class CodeGen(internal val program: PtProgram, val pow2 = powersOfTwo.indexOf(factor) if(pow2==1) { // just shift 1 bit - // TODO use a memory shift instruction? - val reg = vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address) - code += VmCodeInstruction(Opcode.LSL, dt, reg1=reg) - code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address) + code += VmCodeInstruction(Opcode.LSLM, dt, value = address) } else if(pow2>=1) { // just shift multiple bits - // TODO use a memory shift instruction? - val reg = vmRegisters.nextFree() val pow2reg = vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address) code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) - code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg) - code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address) + code += VmCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=address) } else { if (factor == 0) { code += VmCodeInstruction(Opcode.STOREZM, dt, value=address) @@ -547,27 +539,19 @@ class CodeGen(internal val program: PtProgram, val pow2 = powersOfTwo.indexOf(factor) if(pow2==1) { // just shift 1 bit - // TODO use memory-shift instruction? - val reg = vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address) code += if(signed) - VmCodeInstruction(Opcode.ASR, dt, reg1=reg) + VmCodeInstruction(Opcode.ASRM, dt, value=address) else - VmCodeInstruction(Opcode.LSR, dt, reg1=reg) - code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address) + VmCodeInstruction(Opcode.LSRM, dt, value=address) } else if(pow2>=1) { // just shift multiple bits - // TODO use memory-shift instruction? - val reg = vmRegisters.nextFree() val pow2reg = vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address) code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2) code += if(signed) - VmCodeInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg) + VmCodeInstruction(Opcode.ASRNM, dt, reg1=pow2reg, value=address) else - VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg) - code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address) + VmCodeInstruction(Opcode.LSRNM, dt, reg1=pow2reg, value=address) } else { if (factor == 0) { val reg = vmRegisters.nextFree() diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index a968df16a..ccd890588 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -454,6 +454,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } + internal fun operatorShiftRightInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): VmCodeChunk { + val code = VmCodeChunk() + if(codeGen.isOne(operand)) { + val opc = if (signed) Opcode.ASRM else Opcode.LSRM + code += VmCodeInstruction(opc, vmDt, value=address) + } else { + val operandReg = codeGen.vmRegisters.nextFree() + code += translateExpression(operand, operandReg, -1) + val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM + code += VmCodeInstruction(opc, vmDt, reg1 = operandReg, value=address) + } + return code + } + private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() if(codeGen.isOne(binExpr.right)){ @@ -468,6 +482,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) { return code } + internal fun operatorShiftLeftInplace(address: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk { + val code = VmCodeChunk() + if(codeGen.isOne(operand)){ + code += VmCodeInstruction(Opcode.LSLM, vmDt, value=address) + } else { + val operandReg = codeGen.vmRegisters.nextFree() + code += translateExpression(operand, operandReg, -1) + code += VmCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=address) + } + return code + } + private fun operatorXor(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() val rightResultReg = codeGen.vmRegisters.nextFree() diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 25bd80bfd..fc2557d5c 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -435,16 +435,15 @@ internal fun asmGeneratorFor(program: Program, { if(options.experimentalCodegen) { if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) { - // TODO for now, use the new Intermediary Ast for this experimental codegen: val intermediateAst = IntermediateAstMaker(program).transform() return prog8.codegen.experimental.AsmGen(intermediateAst, symbolTable, options, errors) } } else { if (options.compTarget.machine.cpu in arrayOf(CpuType.CPU6502, CpuType.CPU65c02)) + // TODO rewrite 6502 codegen on new Intermediary Ast return prog8.codegen.cpu6502.AsmGen(program, symbolTable, options, errors) if (options.compTarget.name == VMTarget.NAME) { - // TODO for now, use the new Intermediary Ast for this codegen: val intermediateAst = IntermediateAstMaker(program).transform() return prog8.codegen.virtual.CodeGen(intermediateAst, symbolTable, options, errors) } diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 2366e58ae..83db22bf0 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -119,9 +119,9 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter, val comp val newSegments = psrc.segments newSegments += pipe.segments.single() return listOf(IAstModification.ReplaceNode(pipe as Node, Pipe(newSource, newSegments, pipe.position), parent)) - } - - return process(pipe, parent) + } else if(pipe.source is IPipe) + throw InternalCompilerException("pipe source should have been adjusted to be a normal expression") + return noModifications } override fun before(pipeExpr: PipeExpression, parent: Node): Iterable { @@ -132,46 +132,8 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter, val comp val newSegments = psrc.segments newSegments += pipeExpr.segments.single() return listOf(IAstModification.ReplaceNode(pipeExpr as Node, PipeExpression(newSource, newSegments, pipeExpr.position), parent)) - } - - return process(pipeExpr, parent) - } - - private fun process(pipe: IPipe, parent: Node): Iterable { - if(pipe.source is IPipe) + } else if(pipeExpr.source is IPipe) throw InternalCompilerException("pipe source should have been adjusted to be a normal expression") - return noModifications - -// TODO don't use artifical inserted args, fix the places that check for arg numbers instead. - // add the "missing" first argument to each function call in the pipe segments - // so that all function call related checks just pass - // might have to remove it again when entering code generation pass, or just replace it there - // with the proper output value of the previous pipe segment. - -// val mutations = mutableListOf() -// var valueDt = pipe.source.inferType(program).getOrElse { throw FatalAstException("invalid dt") } -// pipe.segments.forEach { call-> -// val dummyFirstArg = when (valueDt) { -// DataType.UBYTE -> FunctionCallExpression(IdentifierReference(listOf("rnd"), pipe.position), mutableListOf(), pipe.position) -// DataType.UWORD -> FunctionCallExpression(IdentifierReference(listOf("rndw"), pipe.position), mutableListOf(), pipe.position) -// DataType.BYTE, DataType.WORD -> IdentifierReference( -// getTempRegisterName(InferredTypes.InferredType.known(valueDt)), -// pipe.position -// ) // there's no builtin function we can abuse that returns a signed byte or word type // TODO maybe use a typecasted expression around rnd? -// DataType.FLOAT -> FunctionCallExpression(IdentifierReference(listOf("rndf"), pipe.position), mutableListOf(), pipe.position) -// else -> throw FatalAstException("invalid dt") -// } -// -// mutations += IAstModification.SetExpression( -// { newexpr -> call.args.add(0, newexpr) }, -// dummyFirstArg, parent -// ) -// -// if(call!==pipe.segments.last()) -// valueDt = call.inferType(program).getOrElse { throw FatalAstException("invalid dt") } -// } -// return mutations - } } diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt index e2125702c..99075e81e 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt @@ -227,11 +227,9 @@ internal class BeforeAsmAstChanger(val program: Program, // TODO: somehow figure out if the expr will result in stack-evaluation STILL after being split off, // in that case: do *not* split it off but just keep it as it is (otherwise code size increases) - // TODO: this should be replaced by a general expression-evaluation optimization step. - // the actual conditional expression in the statement should be no more than VARIABLE SIMPLE-EXPRESSION // NOTE: do NOT move this to an earler ast transform phase (such as StatementReorderer or StatementOptimizer) - it WILL result in larger code. - if(options.compTarget.name==VMTarget.NAME) + if(options.compTarget.name==VMTarget.NAME) // don't apply this optimizer for Vm target return CondExprSimplificationResult(null, null, null, null) var leftAssignment: Assignment? = null diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 56aed5396..8e33697e2 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- vm: implement the 4 rol/ror memory in-place instructions ... diff --git a/examples/test.p8 b/examples/test.p8 index 589ae3a07..89fb056a9 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -34,29 +34,39 @@ main { sub start() { ; mcCarthy() - ubyte bb - for bb in 250 to 255 { - txt.print_ub(bb) - txt.spc() - } + + ubyte @shared bb = %10110001 + byte @shared sb = -99 + bb *= 2 + bb /= 2 + bb *= 8 + bb /= 8 + txt.print_ub(bb) ; 17 + txt.nl() + + sb *= 2 + sb /= 2 + sb *= 8 + sb /= 8 + txt.print_b(sb) ; -3 txt.nl() ; ; a "pixelshader": - sys.gfx_enable(0) ; enable lo res screen - ubyte shifter - - repeat { - uword xx - uword yy = 0 - repeat 240 { - xx = 0 - repeat 320 { - sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte) - xx++ - } - yy++ - } - shifter+=4 - } +; sys.gfx_enable(0) ; enable lo res screen +; ubyte shifter +; +; repeat { +; uword xx +; uword yy = 0 +; repeat 240 { +; xx = 0 +; repeat 320 { +; sys.gfx_plot(xx, yy, xx*yy + shifter as ubyte) +; xx++ +; } +; yy++ +; } +; shifter+=4 +; } } } diff --git a/virtualmachine/src/prog8/vm/Assembler.kt b/virtualmachine/src/prog8/vm/Assembler.kt index 30de2448c..ec0009ab5 100644 --- a/virtualmachine/src/prog8/vm/Assembler.kt +++ b/virtualmachine/src/prog8/vm/Assembler.kt @@ -8,7 +8,9 @@ class Assembler { private val placeholders = mutableMapOf() init { - require(instructionFormats.size== Opcode.values().size) + require(instructionFormats.size== Opcode.values().size) { + "missing " + (Opcode.values().toSet() - instructionFormats.keys) + } } fun initializeMemory(memsrc: String, memory: Memory) { diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index ed06b1b3d..ff5d43bdb 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -128,17 +128,23 @@ xorm reg1, address - memory = memory bitwise xor reg1 not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0) notm address - memory = boolean not of that memory (0->1 , ~0 -> 0) lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit +lsrnm reg1, address - multi-shift memoryright by reg1 bits + set Carry to shifted bit asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit +asrnm reg1, address - multi-shift memory right by reg1 bits (signed) + set Carry to shifted bit lsln reg1, reg2 - reg1 = multi-shift reg1 left by reg2 bits + set Carry to shifted bit +lslnm reg1, address - multi-shift memory left by reg1 bits + set Carry to shifted bit lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit +lsrm address - shift memory right by 1 bits + set Carry to shifted bit asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit +asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit +lslm address - shift memory left by 1 bits + set Carry to shifted bit ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit -TODO: add memory-shift instructions? +TODO: add memory-rotate instructions? FLOATING POINT CONVERSIONS AND FUNCTIONS @@ -251,11 +257,17 @@ enum class Opcode { NOT, NOTM, ASRN, + ASRNM, LSRN, + LSRNM, LSLN, + LSLNM, ASR, + ASRM, LSR, + LSRM, LSL, + LSLM, ROR, ROXR, ROL, @@ -310,7 +322,13 @@ val OpcodesWithAddress = setOf( Opcode.NOTM, Opcode.ORM, Opcode.XORM, - Opcode.ANDM + Opcode.ANDM, + Opcode.ASRM, + Opcode.LSRM, + Opcode.LSLM, + Opcode.LSLNM, + Opcode.LSRNM, + Opcode.ASRNM ) @@ -524,11 +542,17 @@ val instructionFormats = mutableMapOf( Opcode.NOT to InstructionFormat.from("BW,r1"), Opcode.NOTM to InstructionFormat.from("BW,v"), Opcode.ASRN to InstructionFormat.from("BW,r1,r2"), + Opcode.ASRNM to InstructionFormat.from("BW,r1,v"), Opcode.LSRN to InstructionFormat.from("BW,r1,r2"), + Opcode.LSRNM to InstructionFormat.from("BW,r1,v"), Opcode.LSLN to InstructionFormat.from("BW,r1,r2"), + Opcode.LSLNM to InstructionFormat.from("BW,r1,v"), Opcode.ASR to InstructionFormat.from("BW,r1"), + Opcode.ASRM to InstructionFormat.from("BW,v"), Opcode.LSR to InstructionFormat.from("BW,r1"), + Opcode.LSRM to InstructionFormat.from("BW,v"), Opcode.LSL to InstructionFormat.from("BW,r1"), + Opcode.LSLM to InstructionFormat.from("BW,v"), Opcode.ROR to InstructionFormat.from("BW,r1"), Opcode.ROXR to InstructionFormat.from("BW,r1"), Opcode.ROL to InstructionFormat.from("BW,r1"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 1dbd7ce9d..50b53b4b2 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -95,7 +95,7 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.STOREM -> InsSTOREM(ins) Opcode.STOREX -> InsSTOREX(ins) Opcode.STOREI -> InsSTOREI(ins) - Opcode.STOREZM -> InsSTOREZ(ins) + Opcode.STOREZM -> InsSTOREZM(ins) Opcode.STOREZX -> InsSTOREZX(ins) Opcode.STOREZI -> InsSTOREZI(ins) Opcode.JUMP -> InsJUMP(ins) @@ -162,12 +162,18 @@ class VirtualMachine(val memory: Memory, program: List) { Opcode.XORM ->InsXORM(ins) Opcode.NOT -> InsNOT(ins) Opcode.NOTM -> InsNOTM(ins) - Opcode.ASRN -> InsASRM(ins) - Opcode.LSRN -> InsLSRM(ins) - Opcode.LSLN -> InsLSLM(ins) + Opcode.ASRN -> InsASRN(ins) + Opcode.LSRN -> InsLSRN(ins) + Opcode.LSLN -> InsLSLN(ins) Opcode.ASR -> InsASR(ins) Opcode.LSR -> InsLSR(ins) Opcode.LSL -> InsLSL(ins) + Opcode.ASRNM -> InsASRNM(ins) + Opcode.LSRNM -> InsLSRNM(ins) + Opcode.LSLNM -> InsLSLNM(ins) + Opcode.ASRM -> InsASRM(ins) + Opcode.LSRM -> InsLSRM(ins) + Opcode.LSLM -> InsLSLM(ins) Opcode.ROR -> InsROR(ins, false) Opcode.ROXR -> InsROR(ins, true) Opcode.ROL -> InsROL(ins, false) @@ -334,7 +340,7 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsSTOREZ(i: Instruction) { + private fun InsSTOREZM(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> memory.setUB(i.value!!, 0u) VmDataType.WORD -> memory.setUW(i.value!!, 0u) @@ -1162,7 +1168,7 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsASRM(i: Instruction) { + private fun InsASRN(i: Instruction) { val (left: Int, right: Int) = getLogicalOperandsS(i) statusCarry = (left and 1)!=0 when(i.type!!) { @@ -1173,6 +1179,25 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsASRNM(i: Instruction) { + val address = i.value!! + val operand = registers.getUB(i.reg1!!).toInt() + when(i.type!!) { + VmDataType.BYTE -> { + val memvalue = memory.getSB(address).toInt() + statusCarry = (memvalue and 1)!=0 + memory.setSB(address, (memvalue shr operand).toByte()) + } + VmDataType.WORD -> { + val memvalue = memory.getSW(address).toInt() + statusCarry = (memvalue and 1)!=0 + memory.setSW(address, (memvalue shr operand).toShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsASR(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> { @@ -1190,7 +1215,25 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsLSRM(i: Instruction) { + private fun InsASRM(i: Instruction) { + val address = i.value!! + when(i.type!!) { + VmDataType.BYTE -> { + val value = memory.getSB(address).toInt() + statusCarry = (value and 1)!=0 + memory.setSB(address, (value shr 1).toByte()) + } + VmDataType.WORD -> { + val value = memory.getSW(address).toInt() + statusCarry = (value and 1)!=0 + memory.setSW(address, (value shr 1).toShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + + private fun InsLSRN(i: Instruction) { val (left: UInt, right: UInt) = getLogicalOperandsU(i) statusCarry = (left and 1u)!=0u when(i.type!!) { @@ -1201,6 +1244,25 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsLSRNM(i: Instruction) { + val address = i.value!! + val operand = registers.getUB(i.reg1!!).toInt() + when(i.type!!) { + VmDataType.BYTE -> { + val memvalue = memory.getUB(address).toInt() + statusCarry = (memvalue and 1)!=0 + memory.setUB(address, (memvalue shr operand).toUByte()) + } + VmDataType.WORD -> { + val memvalue = memory.getUW(address).toInt() + statusCarry = (memvalue and 1)!=0 + memory.setUW(address, (memvalue shr operand).toUShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsLSR(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> { @@ -1218,7 +1280,25 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } - private fun InsLSLM(i: Instruction) { + private fun InsLSRM(i: Instruction) { + val address = i.value!! + when(i.type!!) { + VmDataType.BYTE -> { + val value = memory.getUB(address).toInt() + statusCarry = (value and 1)!=0 + memory.setUB(address, (value shr 1).toUByte()) + } + VmDataType.WORD -> { + val value = memory.getUW(address).toInt() + statusCarry = (value and 1)!=0 + memory.setUW(address, (value shr 1).toUShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + + private fun InsLSLN(i: Instruction) { val (left: UInt, right: UInt) = getLogicalOperandsU(i) when(i.type!!) { VmDataType.BYTE -> { @@ -1234,6 +1314,25 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsLSLNM(i: Instruction) { + val address = i.value!! + val operand = registers.getUB(i.reg1!!).toInt() + when(i.type!!) { + VmDataType.BYTE -> { + val memvalue = memory.getUB(address).toInt() + statusCarry = (memvalue and 0x80)!=0 + memory.setUB(address, (memvalue shl operand).toUByte()) + } + VmDataType.WORD -> { + val memvalue = memory.getUW(address).toInt() + statusCarry = (memvalue and 0x8000)!=0 + memory.setUW(address, (memvalue shl operand).toUShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsLSL(i: Instruction) { when(i.type!!) { VmDataType.BYTE -> { @@ -1251,6 +1350,24 @@ class VirtualMachine(val memory: Memory, program: List) { pc++ } + private fun InsLSLM(i: Instruction) { + val address = i.value!! + when(i.type!!) { + VmDataType.BYTE -> { + val value = memory.getUB(address).toInt() + statusCarry = (value and 0x80)!=0 + memory.setUB(address, (value shl 1).toUByte()) + } + VmDataType.WORD -> { + val value = memory.getUW(address).toInt() + statusCarry = (value and 0x8000)!=0 + memory.setUW(address, (value shl 1).toUShort()) + } + VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") + } + pc++ + } + private fun InsROR(i: Instruction, useCarry: Boolean) { val newStatusCarry: Boolean when (i.type!!) {