mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
vm: implemented in-memory bit shift instructions
This commit is contained in:
parent
0a48ef3030
commit
b646f50265
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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<IAstModification> {
|
||||
@ -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<IAstModification> {
|
||||
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<IAstModification>()
|
||||
// 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
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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 <COMPARISON-OPERATOR> 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
|
||||
|
@ -3,6 +3,7 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: implement the 4 rol/ror memory in-place instructions
|
||||
...
|
||||
|
||||
|
||||
|
@ -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
|
||||
; }
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ class Assembler {
|
||||
private val placeholders = mutableMapOf<Int, String>()
|
||||
|
||||
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) {
|
||||
|
@ -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"),
|
||||
|
@ -95,7 +95,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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<Instruction>) {
|
||||
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!!) {
|
||||
|
Loading…
Reference in New Issue
Block a user