mirror of
https://github.com/irmen/prog8.git
synced 2026-04-21 02:16:41 +00:00
Merge branch 'master' into structs
# Conflicts: # codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt # codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt # examples/test.p8
This commit is contained in:
@@ -198,7 +198,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
chunks = when (augAssign.operator) {
|
||||
"+=" -> operatorPlusInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"-=" -> operatorMinusInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"*=" -> operatorMultiplyInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"*=" -> operatorMultiplyInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
"/=" -> operatorDivideInplace(symbol, array, constAddress, memTarget, targetDt, value, signed)
|
||||
"|=" -> operatorOrInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
"or=" -> operatorLogicalOrInplace(symbol, array, constAddress, memTarget, targetDt, value)
|
||||
@@ -296,7 +296,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val tr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
if(!array.splitWords && eltSize>1)
|
||||
result += codeGen.multiplyByConst(IRDataType.BYTE, tr.resultReg, eltSize)
|
||||
result += codeGen.multiplyByConst(DataType.UBYTE, tr.resultReg, eltSize)
|
||||
return tr.resultReg
|
||||
}
|
||||
|
||||
@@ -869,7 +869,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
return result
|
||||
}
|
||||
|
||||
private fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression): IRCodeChunks? {
|
||||
private fun operatorMultiplyInplace(symbol: String?, array: PtArrayIndexer?, constAddress: Int?, memory: PtMemoryByte?, vmDt: IRDataType, operand: PtExpression, signed: Boolean): IRCodeChunks? {
|
||||
if(array!=null) {
|
||||
val eltSize = codeGen.program.memsizer.memorySize(array.type, null)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
@@ -883,7 +883,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val valueReg=codeGen.registers.next(eltDt)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, eltDt, reg1=valueReg, immediate = constValue)
|
||||
it += IRInstruction(Opcode.MULM, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
|
||||
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
|
||||
it += IRInstruction(opcode, eltDt, reg1=valueReg, labelSymbol = array.variable.name, symbolOffset = constIndex*eltSize)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -903,22 +904,23 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val tr = expressionEval.translateExpression(operand)
|
||||
addToResult(result, tr, -1, tr.resultFpReg)
|
||||
addInstr(result, if(constAddress!=null)
|
||||
IRInstruction(Opcode.MULM, vmDt, fpReg1 = tr.resultFpReg, address = constAddress)
|
||||
IRInstruction(Opcode.MULSM, vmDt, fpReg1 = tr.resultFpReg, address = constAddress)
|
||||
else
|
||||
IRInstruction(Opcode.MULM, vmDt, fpReg1 = tr.resultFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULSM, vmDt, fpReg1 = tr.resultFpReg, labelSymbol = symbol)
|
||||
, null)
|
||||
}
|
||||
} else {
|
||||
if(constFactorRight!=null && !constFactorRight.type.isFloat) {
|
||||
val factor = constFactorRight.number.toInt()
|
||||
result += codeGen.multiplyByConstInplace(vmDt, constAddress, symbol, factor)
|
||||
result += codeGen.multiplyByConstInplace(vmDt, signed, constAddress, symbol, factor)
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(operand)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
|
||||
addInstr(result, if(constAddress!=null)
|
||||
IRInstruction(Opcode.MULM, vmDt, reg1=tr.resultReg, address = constAddress)
|
||||
IRInstruction(opcode, vmDt, reg1=tr.resultReg, address = constAddress)
|
||||
else
|
||||
IRInstruction(Opcode.MULM, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||
IRInstruction(opcode, vmDt, reg1=tr.resultReg, labelSymbol = symbol)
|
||||
, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataType
|
||||
import prog8.intermediate.*
|
||||
|
||||
|
||||
@@ -672,7 +673,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
if(eltSize>1)
|
||||
it += codeGen.multiplyByConst(IRDataType.BYTE, indexTr.resultReg, eltSize)
|
||||
it += codeGen.multiplyByConst(DataType.UBYTE, indexTr.resultReg, eltSize)
|
||||
if(msb)
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=indexTr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1=indexTr.resultReg, labelSymbol = target.variable.name)
|
||||
@@ -693,7 +694,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
if(eltSize>1)
|
||||
it += codeGen.multiplyByConst(IRDataType.BYTE, indexTr.resultReg, eltSize)
|
||||
it += codeGen.multiplyByConst(DataType.UBYTE, indexTr.resultReg, eltSize)
|
||||
if(msb)
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=indexTr.resultReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=valueTr.resultReg, reg2=indexTr.resultReg, labelSymbol = target.variable.name)
|
||||
|
||||
@@ -2,10 +2,7 @@ package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.*
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.Cx16VirtualRegisters
|
||||
import prog8.code.core.Statusflag
|
||||
import prog8.code.core.*
|
||||
import prog8.intermediate.*
|
||||
|
||||
|
||||
@@ -126,7 +123,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
indexReg = indexTr.resultReg
|
||||
}
|
||||
it += codeGen.multiplyByConst(IRDataType.WORD, indexReg, eltSize)
|
||||
it += codeGen.multiplyByConst(DataType.UWORD, indexReg, eltSize)
|
||||
it += IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1 = pointerReg, reg2 = indexReg)
|
||||
}
|
||||
}
|
||||
@@ -190,7 +187,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
indexReg = indexTr.resultReg
|
||||
}
|
||||
it += codeGen.multiplyByConst(IRDataType.WORD, indexReg, struct.size.toInt())
|
||||
it += codeGen.multiplyByConst(DataType.UWORD, indexReg, struct.size.toInt())
|
||||
it += IRInstruction(Opcode.ADDR, IRDataType.WORD, reg1 = pointerReg, reg2 = indexReg)
|
||||
}
|
||||
}
|
||||
@@ -574,7 +571,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val indexWordReg = codeGen.registers.next(IRDataType.WORD)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=indexWordReg, reg2=indexByteTr.resultReg), null)
|
||||
if(eltSize>1)
|
||||
result += codeGen.multiplyByConst(IRDataType.WORD, indexWordReg, eltSize)
|
||||
result += codeGen.multiplyByConst(DataType.UWORD, indexWordReg, eltSize)
|
||||
val pointerTr = translateExpression(arrayIx.variable)
|
||||
result += pointerTr.chunks
|
||||
val pointerReg = pointerTr.resultReg
|
||||
@@ -591,7 +588,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
// indexing an array or string type
|
||||
if(eltSize>1)
|
||||
result += codeGen.multiplyByConst(IRDataType.BYTE, indexByteTr.resultReg, eltSize)
|
||||
result += codeGen.multiplyByConst(DataType.UBYTE, indexByteTr.resultReg, eltSize)
|
||||
if(vmDt==IRDataType.FLOAT) {
|
||||
resultFpRegister = codeGen.registers.next(IRDataType.FLOAT)
|
||||
addInstr(result, IRInstruction(Opcode.LOADX, IRDataType.FLOAT, fpReg1 = resultFpRegister, reg1=indexByteTr.resultReg, labelSymbol = arrayVarSymbol), null)
|
||||
@@ -782,8 +779,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
return when(binExpr.operator) {
|
||||
"+" -> operatorPlus(binExpr, vmDt)
|
||||
"-" -> operatorMinus(binExpr, vmDt)
|
||||
"*" -> operatorMultiply(binExpr, vmDt)
|
||||
"/" -> operatorDivide(binExpr, vmDt, signed)
|
||||
"*" -> operatorMultiply(binExpr, binExpr.left.type)
|
||||
"/" -> operatorDivide(binExpr, binExpr.left.type)
|
||||
"%" -> operatorModulo(binExpr, vmDt)
|
||||
"|" -> operatorOr(binExpr, vmDt, true)
|
||||
"&" -> operatorAnd(binExpr, vmDt, true)
|
||||
@@ -1444,7 +1441,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: IRDataType, signed: Boolean): ExpressionCodeResult {
|
||||
private fun operatorDivide(binExpr: PtBinaryExpression, dt: DataType): ExpressionCodeResult {
|
||||
val vmDt = irType(dt)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val constFactorRight = binExpr.right as? PtNumber
|
||||
if(vmDt==IRDataType.FLOAT) {
|
||||
@@ -1459,7 +1457,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||
addInstr(result, if(signed)
|
||||
addInstr(result, if(dt.isSigned)
|
||||
IRInstruction(Opcode.DIVSR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2=rightTr.resultFpReg)
|
||||
else
|
||||
IRInstruction(Opcode.DIVR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2=rightTr.resultFpReg)
|
||||
@@ -1471,13 +1469,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val tr = translateExpression(binExpr.left)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val factor = constFactorRight.number.toInt()
|
||||
result += codeGen.divideByConst(vmDt, tr.resultReg, factor, signed)
|
||||
result += codeGen.divideByConst(vmDt, tr.resultReg, factor, dt.isSigned)
|
||||
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
|
||||
} else {
|
||||
if(binExpr.right is PtNumber) {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
addInstr(result, if (signed)
|
||||
addInstr(result, if (dt.isSigned)
|
||||
IRInstruction(Opcode.DIVS, vmDt, reg1 = leftTr.resultReg, immediate = (binExpr.right as PtNumber).number.toInt())
|
||||
else
|
||||
IRInstruction(Opcode.DIV, vmDt, reg1 = leftTr.resultReg, immediate = (binExpr.right as PtNumber).number.toInt())
|
||||
@@ -1488,7 +1486,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||
addInstr(result, if (signed)
|
||||
addInstr(result, if (dt.isSigned)
|
||||
IRInstruction(Opcode.DIVSR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg)
|
||||
else
|
||||
IRInstruction(Opcode.DIVR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg)
|
||||
@@ -1499,7 +1497,8 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun operatorMultiply(binExpr: PtBinaryExpression, vmDt: IRDataType): ExpressionCodeResult {
|
||||
private fun operatorMultiply(binExpr: PtBinaryExpression, dt: DataType): ExpressionCodeResult {
|
||||
val vmDt = irType(dt)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val constFactorLeft = binExpr.left as? PtNumber
|
||||
val constFactorRight = binExpr.right as? PtNumber
|
||||
@@ -1521,7 +1520,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
addToResult(result, leftTr, -1, leftTr.resultFpReg)
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, -1, rightTr.resultFpReg)
|
||||
addInstr(result, IRInstruction(Opcode.MULR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
||||
addInstr(result, IRInstruction(Opcode.MULSR, vmDt, fpReg1 = leftTr.resultFpReg, fpReg2 = rightTr.resultFpReg), null)
|
||||
ExpressionCodeResult(result, vmDt, -1, leftTr.resultFpReg)
|
||||
}
|
||||
} else {
|
||||
@@ -1529,20 +1528,21 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val tr = translateExpression(binExpr.right)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val factor = constFactorLeft.number.toInt()
|
||||
result += codeGen.multiplyByConst(vmDt, tr.resultReg, factor)
|
||||
result += codeGen.multiplyByConst(dt, tr.resultReg, factor)
|
||||
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
|
||||
} else if(constFactorRight!=null && !constFactorRight.type.isFloat) {
|
||||
val tr = translateExpression(binExpr.left)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val factor = constFactorRight.number.toInt()
|
||||
result += codeGen.multiplyByConst(vmDt, tr.resultReg, factor)
|
||||
result += codeGen.multiplyByConst(dt, tr.resultReg, factor)
|
||||
ExpressionCodeResult(result, vmDt, tr.resultReg, -1)
|
||||
} else {
|
||||
val leftTr = translateExpression(binExpr.left)
|
||||
addToResult(result, leftTr, leftTr.resultReg, -1)
|
||||
val rightTr = translateExpression(binExpr.right)
|
||||
addToResult(result, rightTr, rightTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.MULR, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
|
||||
val opcode = if(dt.isSigned) Opcode.MULSR else Opcode.MULR
|
||||
addInstr(result, IRInstruction(opcode, vmDt, reg1 = leftTr.resultReg, reg2 = rightTr.resultReg), null)
|
||||
ExpressionCodeResult(result, vmDt, leftTr.resultReg, -1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,7 +784,7 @@ class IRCodeGen(
|
||||
code += if(factor==0.0) {
|
||||
IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = 0.0)
|
||||
} else {
|
||||
IRInstruction(Opcode.MUL, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
||||
IRInstruction(Opcode.MULS, IRDataType.FLOAT, fpReg1 = fpReg, immediateFp = factor)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@@ -802,38 +802,40 @@ class IRCodeGen(
|
||||
val factorReg = registers.next(IRDataType.FLOAT)
|
||||
code += IRInstruction(Opcode.LOAD, IRDataType.FLOAT, fpReg1=factorReg, immediateFp = factor)
|
||||
code += if(knownAddress!=null)
|
||||
IRInstruction(Opcode.MULM, IRDataType.FLOAT, fpReg1 = factorReg, address = knownAddress)
|
||||
IRInstruction(Opcode.MULSM, IRDataType.FLOAT, fpReg1 = factorReg, address = knownAddress)
|
||||
else
|
||||
IRInstruction(Opcode.MULM, IRDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULSM, IRDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
internal fun multiplyByConst(dt: IRDataType, reg: Int, factor: Int): IRCodeChunk {
|
||||
internal fun multiplyByConst(dt: DataType, reg: Int, factor: Int): IRCodeChunk {
|
||||
val irdt = irType(dt)
|
||||
val code = IRCodeChunk(null, null)
|
||||
if(factor==1)
|
||||
return code
|
||||
val pow2 = powersOfTwoInt.indexOf(factor)
|
||||
if(pow2==1) {
|
||||
// just shift 1 bit
|
||||
code += IRInstruction(Opcode.LSL, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.LSL, irdt, reg1=reg)
|
||||
}
|
||||
else if(pow2>=1) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = registers.next(IRDataType.BYTE)
|
||||
code += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=pow2reg, immediate = pow2)
|
||||
code += IRInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
|
||||
code += IRInstruction(Opcode.LSLN, irdt, reg1=reg, reg2=pow2reg)
|
||||
} else {
|
||||
code += if (factor == 0) {
|
||||
IRInstruction(Opcode.LOAD, dt, reg1=reg, immediate = 0)
|
||||
IRInstruction(Opcode.LOAD, irdt, reg1=reg, immediate = 0)
|
||||
} else {
|
||||
IRInstruction(Opcode.MUL, dt, reg1=reg, immediate = factor)
|
||||
val opcode = if(dt.isSigned) Opcode.MULS else Opcode.MUL
|
||||
IRInstruction(opcode, irdt, reg1=reg, immediate = factor)
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
internal fun multiplyByConstInplace(dt: IRDataType, knownAddress: Int?, symbol: String?, factor: Int): IRCodeChunk {
|
||||
internal fun multiplyByConstInplace(dt: IRDataType, signed: Boolean, knownAddress: Int?, symbol: String?, factor: Int): IRCodeChunk {
|
||||
val code = IRCodeChunk(null, null)
|
||||
if(factor==1)
|
||||
return code
|
||||
@@ -863,10 +865,11 @@ class IRCodeGen(
|
||||
else {
|
||||
val factorReg = registers.next(dt)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, immediate = factor)
|
||||
val opcode = if(signed) Opcode.MULSM else Opcode.MULM
|
||||
code += if(knownAddress!=null)
|
||||
IRInstruction(Opcode.MULM, dt, reg1=factorReg, address = knownAddress)
|
||||
IRInstruction(opcode, dt, reg1=factorReg, address = knownAddress)
|
||||
else
|
||||
IRInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = symbol)
|
||||
IRInstruction(opcode, dt, reg1=factorReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return code
|
||||
|
||||
@@ -357,7 +357,7 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
when (ins.opcode) {
|
||||
Opcode.DIV, Opcode.DIVS, Opcode.MUL, Opcode.MOD -> {
|
||||
Opcode.DIV, Opcode.DIVS, Opcode.MUL, Opcode.MULS, Opcode.MOD -> {
|
||||
if (ins.immediate == 1) {
|
||||
chunk.instructions.removeAt(idx)
|
||||
changed = true
|
||||
|
||||
@@ -505,17 +505,19 @@ main {
|
||||
l2.n=10
|
||||
|
||||
^^List l3 = List()
|
||||
cx16.r0L = n.next.n
|
||||
cx16.r0L = l3.next.n
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(VMTarget(), true, src, outputDir, writeAssembly = false)!!
|
||||
val st = result.compilerAst.entrypoint.statements
|
||||
st.size shouldBe 6
|
||||
st.size shouldBe 9
|
||||
(st[0] as VarDecl).name shouldBe "l1"
|
||||
(st[2] as VarDecl).name shouldBe "l2"
|
||||
st[4] shouldBe instanceOf<Assignment>()
|
||||
st[5] shouldBe instanceOf<Assignment>()
|
||||
(st[6] as VarDecl).name shouldBe "l3"
|
||||
st[8] shouldBe instanceOf<Assignment>()
|
||||
}
|
||||
|
||||
test("indexing pointers with index 0 is just a direct pointer dereference") {
|
||||
|
||||
@@ -136,6 +136,9 @@ class CallGraph(private val program: Program) : IAstVisitor {
|
||||
allIdentifiersAndTargets.add(identifier to scopeTarget)
|
||||
break
|
||||
} else if(scopeTarget is StructFieldRef) {
|
||||
val vd = scope.lookup(name.take(1))
|
||||
if(vd is VarDecl)
|
||||
allIdentifiersAndTargets.add(identifier to vd)
|
||||
allIdentifiersAndTargets.add(identifier to scopeTarget)
|
||||
break
|
||||
}
|
||||
|
||||
+11
-137
@@ -1,142 +1,16 @@
|
||||
%option enable_floats
|
||||
|
||||
main {
|
||||
^^bool g_bp
|
||||
^^word g_bw
|
||||
^^float g_floats
|
||||
|
||||
struct List {
|
||||
^^uword s
|
||||
ubyte n
|
||||
^^List next
|
||||
}
|
||||
sub start() {
|
||||
^^bool l_bp
|
||||
^^word l_bw
|
||||
^^float l_floats
|
||||
^^List l1 = List()
|
||||
^^List l2 = List()
|
||||
l1.s[2] = 1
|
||||
l2.n=10
|
||||
|
||||
assign_pointers()
|
||||
assign_values()
|
||||
assign_inplace()
|
||||
assign_deref()
|
||||
assign_uwords()
|
||||
assign_same_ptrs()
|
||||
assign_different_ptrs()
|
||||
|
||||
sub assign_pointers() {
|
||||
cx16.r0 = l_bp
|
||||
cx16.r1 = l_bw
|
||||
cx16.r2 = l_floats
|
||||
cx16.r0 = g_bp
|
||||
cx16.r1 = g_bw
|
||||
cx16.r2 = g_floats
|
||||
cx16.r0 = other.g_bp
|
||||
cx16.r1 = other.g_bw
|
||||
cx16.r2 = other.g_floats
|
||||
cx16.r0 = other.func.l_bp
|
||||
cx16.r1 = other.func.l_bw
|
||||
cx16.r2 = other.func.l_floats
|
||||
}
|
||||
|
||||
sub assign_deref() {
|
||||
float f
|
||||
bool b
|
||||
word w
|
||||
b = l_bp^^
|
||||
w = l_bw^^
|
||||
f = l_floats^^
|
||||
b = g_bp^^
|
||||
w = g_bw^^
|
||||
f = g_floats^^
|
||||
b = other.g_bp^^
|
||||
w = other.g_bw^^
|
||||
f = other.g_floats^^
|
||||
b = other.func.l_bp^^
|
||||
w = other.func.l_bw^^
|
||||
f = other.func.l_floats^^
|
||||
}
|
||||
|
||||
sub assign_values() {
|
||||
l_bp^^ = true
|
||||
l_bw^^ = -1234
|
||||
l_floats^^ = 5.678
|
||||
g_bp^^ = true
|
||||
g_bw^^ = -1234
|
||||
g_floats^^ = 5.678
|
||||
other.g_bp^^ = true
|
||||
other.g_bw^^ = -1234
|
||||
other.g_floats^^ = 5.678
|
||||
other.func.l_bp^^ = true
|
||||
other.func.l_bw^^ = -1234
|
||||
other.func.l_floats^^ = 5.678
|
||||
}
|
||||
|
||||
sub assign_same_ptrs() {
|
||||
l_bp = g_bp
|
||||
l_bw = g_bw
|
||||
l_floats = g_floats
|
||||
g_bp = other.g_bp
|
||||
g_bw = other.g_bw
|
||||
g_floats = other.g_floats
|
||||
other.g_bp = other.func.l_bp
|
||||
other.g_bw = other.func.l_bw
|
||||
other.g_floats = other.func.l_floats
|
||||
}
|
||||
|
||||
sub assign_different_ptrs() {
|
||||
l_bp = g_floats as ^^bool
|
||||
l_bw = g_floats as ^^word
|
||||
l_floats = g_bp as ^^float
|
||||
other.g_bp = l_floats as ^^bool
|
||||
other.g_bw = l_floats as ^^word
|
||||
other.g_floats = l_bp as ^^float
|
||||
}
|
||||
|
||||
sub assign_inplace() {
|
||||
bool b
|
||||
l_bp^^ = l_bp^^ xor b
|
||||
l_bw^^ += -1234
|
||||
l_floats^^ += 5.678
|
||||
g_bp^^ = g_bp^^ xor b
|
||||
g_bw^^ += -1234
|
||||
g_floats^^ += 5.678
|
||||
other.g_bp^^ = other.g_bp^^ xor b
|
||||
other.g_bw^^ += -1234
|
||||
other.g_floats^^ += 5.678
|
||||
other.func.l_bp^^ = other.func.l_bp^^ xor b
|
||||
other.func.l_bw^^ += -1234
|
||||
other.func.l_floats^^ += 5.678
|
||||
|
||||
l_bw^^ /= 3
|
||||
l_floats^^ /= 3.0
|
||||
g_bw^^ /= 3
|
||||
g_floats^^ /= 3.0
|
||||
other.g_bw^^ /= 3
|
||||
other.g_floats^^ /= 3.0
|
||||
other.func.l_bw^^ /= 3
|
||||
other.func.l_floats^^ /= 3.0
|
||||
}
|
||||
|
||||
sub assign_uwords() {
|
||||
l_bp = $9000
|
||||
l_bw = $9000
|
||||
l_floats = $9000
|
||||
g_bp = $9000
|
||||
g_bw = $9000
|
||||
g_floats = $9000
|
||||
other.g_bp = $9000
|
||||
other.g_bw = $9000
|
||||
other.g_floats = $9000
|
||||
other.func.l_bp = $9000
|
||||
other.func.l_bw = $9000
|
||||
other.func.l_floats = $9000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
other {
|
||||
^^bool g_bp
|
||||
^^word g_bw
|
||||
^^float g_floats
|
||||
|
||||
sub func() {
|
||||
^^bool l_bp
|
||||
^^word l_bw
|
||||
^^float l_floats
|
||||
^^List l3 = List()
|
||||
cx16.r0L = l3.next.n
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,13 +146,16 @@ subr reg1, reg2 - reg1 -= reg2
|
||||
sub reg1, value - reg1 -= value
|
||||
subm reg1, address - memory at address -= reg1
|
||||
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
mulsr reg1, reg2 - signed multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
mul reg1, value - unsigned multiply reg1 *= value note: byte*byte->byte, no type extension to word!
|
||||
mulm reg1, address - memory at address *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
muls reg1, value - signed multiply reg1 *= value note: byte*byte->byte, no type extension to word!
|
||||
mulm reg1, address - unsigned memory at address *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
mulsm reg1, address - signed memory at address *= reg2 note: byte*byte->byte, no type extension to word!
|
||||
divr reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max int $ff/$ffff
|
||||
div reg1, value - unsigned division reg1 /= value note: division by zero yields max int $ff/$ffff
|
||||
divm reg1, address - memory at address /= reg2 note: division by zero yields max int $ff/$ffff
|
||||
divsr reg1, reg2 - signed division reg1 /= reg2 note: division by zero yields max signed int 127 / 32767
|
||||
div reg1, value - unsigned division reg1 /= value note: division by zero yields max int $ff/$ffff
|
||||
divs reg1, value - signed division reg1 /= value note: division by zero yields max signed int 127 / 32767
|
||||
divm reg1, address - memory at address /= reg2 note: division by zero yields max int $ff/$ffff
|
||||
divsm reg1, address - signed memory at address /= reg2 note: division by zero yields max signed int 127 / 32767
|
||||
modr reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
|
||||
mod reg1, value - remainder (modulo) of unsigned division reg1 %= value note: division by zero yields max signed int $ff/$ffff
|
||||
@@ -327,6 +330,9 @@ enum class Opcode {
|
||||
MULR,
|
||||
MUL,
|
||||
MULM,
|
||||
MULSR,
|
||||
MULS,
|
||||
MULSM,
|
||||
DIVR,
|
||||
DIV,
|
||||
DIVM,
|
||||
@@ -664,9 +670,12 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.SUBR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.SUB to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
|
||||
Opcode.SUBM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
|
||||
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
|
||||
Opcode.MULM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
|
||||
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,<>r1,<i"),
|
||||
Opcode.MULM to InstructionFormat.from("BW,<r1,<>a"),
|
||||
Opcode.MULSR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.MULS to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
|
||||
Opcode.MULSM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
|
||||
Opcode.DIVR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.DIV to InstructionFormat.from("BW,<>r1,<i"),
|
||||
Opcode.DIVM to InstructionFormat.from("BW,<r1,<>a"),
|
||||
|
||||
@@ -258,6 +258,9 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.MULR -> InsMULR(ins)
|
||||
Opcode.MUL -> InsMUL(ins)
|
||||
Opcode.MULM -> InsMULM(ins)
|
||||
Opcode.MULSR -> InsMULSR(ins)
|
||||
Opcode.MULS -> InsMULS(ins)
|
||||
Opcode.MULSM -> InsMULSM(ins)
|
||||
Opcode.DIVR -> InsDIVR(ins)
|
||||
Opcode.DIV -> InsDIV(ins)
|
||||
Opcode.DIVM -> InsDIVM(ins)
|
||||
@@ -1118,6 +1121,48 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsMULSR(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> plusMinusMultAnyByteSigned("*", i.reg1!!, i.reg2!!)
|
||||
IRDataType.WORD -> plusMinusMultAnyWordSigned("*", i.reg1!!, i.reg2!!)
|
||||
IRDataType.FLOAT -> {
|
||||
val left = registers.getFloat(i.fpReg1!!)
|
||||
val right = registers.getFloat(i.fpReg2!!)
|
||||
val result = arithFloat(left, "*", right)
|
||||
registers.setFloat(i.fpReg1!!, result)
|
||||
}
|
||||
}
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsMULS(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> plusMinusMultConstByteSigned("*", i.reg1!!, i.immediate!!.toByte())
|
||||
IRDataType.WORD -> plusMinusMultConstWordSigned("*", i.reg1!!, i.immediate!!.toShort())
|
||||
IRDataType.FLOAT -> {
|
||||
val left = registers.getFloat(i.fpReg1!!)
|
||||
val result = arithFloat(left, "*", i.immediateFp!!)
|
||||
registers.setFloat(i.fpReg1!!, result)
|
||||
}
|
||||
}
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsMULSM(i: IRInstruction) {
|
||||
val address = i.address!!
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> plusMinusMultAnyByteSignedInplace("*", i.reg1!!, address)
|
||||
IRDataType.WORD -> plusMinusMultAnyWordSignedInplace("*", i.reg1!!, address)
|
||||
IRDataType.FLOAT -> {
|
||||
val left = memory.getFloat(address)
|
||||
val right = registers.getFloat(i.fpReg1!!)
|
||||
val result = arithFloat(left, "*", right)
|
||||
memory.setFloat(address, result)
|
||||
}
|
||||
}
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsDIVR(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> divOrModByteUnsigned("/", i.reg1!!, i.reg2!!)
|
||||
@@ -1355,6 +1400,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
registers.setUB(reg1, result.toUByte())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyByteSigned(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getSB(reg1)
|
||||
val right = registers.getSB(reg2)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
"*" -> left * right
|
||||
else -> throw IllegalArgumentException("operator byte $operator")
|
||||
}
|
||||
registers.setSB(reg1, result.toByte())
|
||||
}
|
||||
|
||||
private fun plusMinusMultConstByte(operator: String, reg1: Int, value: UByte) {
|
||||
val left = registers.getUB(reg1)
|
||||
val result = when(operator) {
|
||||
@@ -1366,6 +1423,17 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
registers.setUB(reg1, result.toUByte())
|
||||
}
|
||||
|
||||
private fun plusMinusMultConstByteSigned(operator: String, reg1: Int, value: Byte) {
|
||||
val left = registers.getSB(reg1)
|
||||
val result = when(operator) {
|
||||
"+" -> left + value
|
||||
"-" -> left - value
|
||||
"*" -> left * value
|
||||
else -> throw IllegalArgumentException("operator byte $operator")
|
||||
}
|
||||
registers.setSB(reg1, result.toByte())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyByteInplace(operator: String, reg1: Int, address: Int) {
|
||||
val memvalue = memory.getUB(address)
|
||||
val operand = registers.getUB(reg1)
|
||||
@@ -1378,6 +1446,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
memory.setUB(address, result.toUByte())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyByteSignedInplace(operator: String, reg1: Int, address: Int) {
|
||||
val memvalue = memory.getSB(address)
|
||||
val operand = registers.getSB(reg1)
|
||||
val result = when(operator) {
|
||||
"+" -> memvalue + operand
|
||||
"-" -> memvalue - operand
|
||||
"*" -> memvalue * operand
|
||||
else -> throw IllegalArgumentException("operator byte $operator")
|
||||
}
|
||||
memory.setSB(address, result.toByte())
|
||||
}
|
||||
|
||||
private fun divModByteSigned(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getSB(reg1)
|
||||
val right = registers.getSB(reg2)
|
||||
@@ -1528,6 +1608,22 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
registers.setUW(reg1, result.toUShort())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyWordSigned(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getSW(reg1)
|
||||
val right = registers.getSW(reg2)
|
||||
val result: Int
|
||||
when(operator) {
|
||||
"+" -> result = left + right
|
||||
"-" -> result = left - right
|
||||
"*" -> {
|
||||
result = left.toInt() * right
|
||||
mul16LastUpper = result.toUInt() shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
registers.setSW(reg1, result.toShort())
|
||||
}
|
||||
|
||||
private fun plusMinusMultConstWord(operator: String, reg1: Int, value: UShort) {
|
||||
val left = registers.getUW(reg1)
|
||||
val result: UInt
|
||||
@@ -1543,6 +1639,21 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
registers.setUW(reg1, result.toUShort())
|
||||
}
|
||||
|
||||
private fun plusMinusMultConstWordSigned(operator: String, reg1: Int, value: Short) {
|
||||
val left = registers.getSW(reg1)
|
||||
val result: Int
|
||||
when(operator) {
|
||||
"+" -> result = left + value
|
||||
"-" -> result = left - value
|
||||
"*" -> {
|
||||
result = left.toInt() * value
|
||||
mul16LastUpper = result.toUInt() shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
registers.setSW(reg1, result.toShort())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyWordInplace(operator: String, reg1: Int, address: Int) {
|
||||
val memvalue = memory.getUW(address)
|
||||
val operand = registers.getUW(reg1)
|
||||
@@ -1559,6 +1670,22 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
memory.setUW(address, result.toUShort())
|
||||
}
|
||||
|
||||
private fun plusMinusMultAnyWordSignedInplace(operator: String, reg1: Int, address: Int) {
|
||||
val memvalue = memory.getSW(address)
|
||||
val operand = registers.getSW(reg1)
|
||||
val result: Int
|
||||
when(operator) {
|
||||
"+" -> result = memvalue + operand
|
||||
"-" -> result = memvalue - operand
|
||||
"*" -> {
|
||||
result = memvalue.toInt() * operand
|
||||
mul16LastUpper = result.toUInt() shr 16
|
||||
}
|
||||
else -> throw IllegalArgumentException("operator word $operator")
|
||||
}
|
||||
memory.setSW(address, result.toShort())
|
||||
}
|
||||
|
||||
private fun divOrModWordUnsigned(operator: String, reg1: Int, reg2: Int) {
|
||||
val left = registers.getUW(reg1)
|
||||
val right = registers.getUW(reg2)
|
||||
|
||||
Reference in New Issue
Block a user