mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16:16 +00:00
implement long << >> expressions
This commit is contained in:
@@ -400,7 +400,9 @@ enum class RegisterOrPair {
|
|||||||
FAC2,
|
FAC2,
|
||||||
// cx16 virtual registers:
|
// cx16 virtual registers:
|
||||||
R0, R1, R2, R3, R4, R5, R6, R7,
|
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||||
R8, R9, R10, R11, R12, R13, R14, R15;
|
R8, R9, R10, R11, R12, R13, R14, R15,
|
||||||
|
// combined virtual registers to store 32 bits longs:
|
||||||
|
R0R1_32, R2R3_32, R4R5_32, R6R7_32, R8R9_32, R10R11_32, R12R13_32, R14R15_32;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val names by lazy { entries.map { it.toString()} }
|
val names by lazy { entries.map { it.toString()} }
|
||||||
@@ -427,12 +429,13 @@ enum class RegisterOrPair {
|
|||||||
BaseDataType.BYTE -> "sL"
|
BaseDataType.BYTE -> "sL"
|
||||||
BaseDataType.WORD -> "s"
|
BaseDataType.WORD -> "s"
|
||||||
BaseDataType.UWORD, null -> ""
|
BaseDataType.UWORD, null -> ""
|
||||||
else -> throw IllegalArgumentException("invalid register param type")
|
else -> throw IllegalArgumentException("invalid register param type for cx16 virtual reg")
|
||||||
}
|
}
|
||||||
return listOf("cx16", name.lowercase()+suffix)
|
return listOf("cx16", name.lowercase()+suffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isWord() = this==AX || this == AY || this==XY || this in Cx16VirtualRegisters
|
fun isWord() = this==AX || this == AY || this==XY || this in Cx16VirtualRegisters
|
||||||
|
fun isLong() = this in combinedLongRegisters
|
||||||
|
|
||||||
} // only used in parameter and return value specs in asm subroutines
|
} // only used in parameter and return value specs in asm subroutines
|
||||||
|
|
||||||
@@ -469,6 +472,17 @@ val Cx16VirtualRegisters = arrayOf(
|
|||||||
RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15
|
RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val combinedLongRegisters = arrayOf(
|
||||||
|
RegisterOrPair.R0R1_32,
|
||||||
|
RegisterOrPair.R2R3_32,
|
||||||
|
RegisterOrPair.R4R5_32,
|
||||||
|
RegisterOrPair.R6R7_32,
|
||||||
|
RegisterOrPair.R8R9_32,
|
||||||
|
RegisterOrPair.R10R11_32,
|
||||||
|
RegisterOrPair.R12R13_32,
|
||||||
|
RegisterOrPair.R14R15_32
|
||||||
|
)
|
||||||
|
|
||||||
val CpuRegisters = arrayOf(
|
val CpuRegisters = arrayOf(
|
||||||
RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y,
|
RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y,
|
||||||
RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY
|
RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY
|
||||||
|
|||||||
@@ -914,8 +914,7 @@ class AsmGen6502Internal (
|
|||||||
when (target.kind) {
|
when (target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
out(" lda $valuesym | sta ${target.asmVarname}")
|
out(" lda $valuesym | sta ${target.asmVarname}")
|
||||||
signExtendVariableLsb(target.asmVarname, value.value.type.base)
|
signExtendLongVariable(target.asmVarname, value.value.type.base)
|
||||||
signExtendLongVariableMsw(target.asmVarname, value.value.type.base)
|
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
||||||
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
||||||
@@ -931,11 +930,20 @@ class AsmGen6502Internal (
|
|||||||
sta ${target.asmVarname}
|
sta ${target.asmVarname}
|
||||||
lda $valuesym+1
|
lda $valuesym+1
|
||||||
sta ${target.asmVarname}+1""")
|
sta ${target.asmVarname}+1""")
|
||||||
signExtendLongVariableMsw(target.asmVarname, value.value.type.base)
|
signExtendLongVariable(target.asmVarname, value.value.type.base)
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
||||||
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
||||||
TargetStorageKind.REGISTER -> TODO("32 bits register assign? (we have no 32 bits registers right now) ${target.position}")
|
TargetStorageKind.REGISTER -> {
|
||||||
|
require(target.register in combinedLongRegisters)
|
||||||
|
val startreg = target.register.toString().take(2).lowercase()
|
||||||
|
out("""
|
||||||
|
lda $valuesym
|
||||||
|
sta cx16.$startreg
|
||||||
|
lda $valuesym+1
|
||||||
|
sta cx16.$startreg+1""")
|
||||||
|
signExtendLongVariable("cx16.$startreg", value.value.type.base)
|
||||||
|
}
|
||||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||||
}
|
}
|
||||||
@@ -1384,7 +1392,7 @@ $repeatLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun signExtendLongVariableMsw(asmvar: String, valueDt: BaseDataType) {
|
internal fun signExtendLongVariable(asmvar: String, valueDt: BaseDataType) {
|
||||||
// sign extend signed word in a var to a full long in that variable
|
// sign extend signed word in a var to a full long in that variable
|
||||||
when(valueDt) {
|
when(valueDt) {
|
||||||
BaseDataType.UBYTE -> {
|
BaseDataType.UBYTE -> {
|
||||||
@@ -1421,7 +1429,7 @@ $repeatLabel""")
|
|||||||
+ sta $asmvar+2
|
+ sta $asmvar+2
|
||||||
sta $asmvar+3""")
|
sta $asmvar+3""")
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("need byte type")
|
else -> throw AssemblyError("need byte or word type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,18 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
val dt = if(signed) DataType.WORD else DataType.UWORD
|
val dt = if(signed) DataType.WORD else DataType.UWORD
|
||||||
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, dt, scope, pos, register = registers)
|
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, dt, scope, pos, register = registers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisterOrPair.R0R1_32,
|
||||||
|
RegisterOrPair.R2R3_32,
|
||||||
|
RegisterOrPair.R4R5_32,
|
||||||
|
RegisterOrPair.R6R7_32,
|
||||||
|
RegisterOrPair.R8R9_32,
|
||||||
|
RegisterOrPair.R10R11_32,
|
||||||
|
RegisterOrPair.R12R13_32,
|
||||||
|
RegisterOrPair.R14R15_32 -> {
|
||||||
|
val dt = if(signed) DataType.LONG else TODO("unsigned long")
|
||||||
|
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, dt, scope, pos, register = registers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -656,7 +656,7 @@ internal class AssignmentAsmGen(
|
|||||||
}
|
}
|
||||||
returnDt== BaseDataType.LONG -> {
|
returnDt== BaseDataType.LONG -> {
|
||||||
// longs are in R0:R1 (r0=lsw, r1=msw)
|
// longs are in R0:R1 (r0=lsw, r1=msw)
|
||||||
assignRegisterLong(target, RegisterOrPair.R0, RegisterOrPair.R1)
|
assignRegisterLong(target, RegisterOrPair.R0R1_32)
|
||||||
}
|
}
|
||||||
returnDt==BaseDataType.FLOAT -> {
|
returnDt==BaseDataType.FLOAT -> {
|
||||||
// float result from function sits in FAC1
|
// float result from function sits in FAC1
|
||||||
@@ -1244,7 +1244,7 @@ internal class AssignmentAsmGen(
|
|||||||
asmgen.out(" jsr prog8_math.asl_byte_A")
|
asmgen.out(" jsr prog8_math.asl_byte_A")
|
||||||
assignRegisterByte(target, CpuRegister.A, signed, true)
|
assignRegisterByte(target, CpuRegister.A, signed, true)
|
||||||
return true
|
return true
|
||||||
} else {
|
} else if(dt.isWord) {
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
|
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
|
||||||
asmgen.restoreRegisterStack(CpuRegister.X, true)
|
asmgen.restoreRegisterStack(CpuRegister.X, true)
|
||||||
if(expr.operator==">>")
|
if(expr.operator==">>")
|
||||||
@@ -1256,6 +1256,12 @@ internal class AssignmentAsmGen(
|
|||||||
asmgen.out(" jsr prog8_math.asl_word_AY")
|
asmgen.out(" jsr prog8_math.asl_word_AY")
|
||||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
return true
|
return true
|
||||||
|
} else if(dt.isLong) {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.R0R1_32, signed)
|
||||||
|
asmgen.out(" pla | sta P8ZP_SCRATCH_REG")
|
||||||
|
augmentableAsmGen.inplacemodificationLongWithVariable("cx16.r0", expr.operator, "P8ZP_SCRATCH_REG")
|
||||||
|
assignRegisterLong(target, RegisterOrPair.R0R1_32)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1375,6 +1381,11 @@ internal class AssignmentAsmGen(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if(dt.isLong) {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.R0R1_32, signed)
|
||||||
|
augmentableAsmGen.inplacemodificationLongWithLiteralval("cx16.r0", expr.operator, shifts)
|
||||||
|
assignRegisterLong(target, RegisterOrPair.R0R1_32)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -1787,7 +1798,11 @@ internal class AssignmentAsmGen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
TODO("add/subtract long ${target.position} - use simple expressions and temporary variables for now")
|
assignExpressionToRegister(expr.left, RegisterOrPair.R2R3_32, expr.left.type.isSigned)
|
||||||
|
assignExpressionToRegister(expr.right, RegisterOrPair.R0R1_32, expr.right.type.isSigned)
|
||||||
|
augmentableAsmGen.inplacemodificationLongWithVariable("cx16.r2", expr.operator, "cx16.r0")
|
||||||
|
assignRegisterLong(target, RegisterOrPair.R2R3_32)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2519,8 +2534,8 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(targetDt.isInteger && valueDt.isByteOrBool && valueDt.isAssignableTo(targetDt)) {
|
if(targetDt.isInteger && valueDt.isByteOrBool && valueDt.isAssignableTo(targetDt)) {
|
||||||
require(targetDt.isWord) {
|
require(targetDt.isWord || targetDt.isLong) {
|
||||||
"should be byte to word assignment ${origTypeCastExpression.position}"
|
"should be byte to word or long assignment ${origTypeCastExpression.position}"
|
||||||
}
|
}
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
// TargetStorageKind.VARIABLE -> {
|
// TargetStorageKind.VARIABLE -> {
|
||||||
@@ -2541,7 +2556,7 @@ $endLabel""")
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
TargetStorageKind.REGISTER -> {
|
TargetStorageKind.REGISTER -> {
|
||||||
// byte to word, just assign to registers
|
// byte to word or long, just assign to registers
|
||||||
assignExpressionToRegister(value, target.register!!, targetDt.isSigned)
|
assignExpressionToRegister(value, target.register!!, targetDt.isSigned)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2686,7 +2701,7 @@ $endLabel""")
|
|||||||
BaseDataType.LONG -> {
|
BaseDataType.LONG -> {
|
||||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
|
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
|
||||||
asmgen.signExtendVariableLsb(targetAsmVarName, BaseDataType.BYTE)
|
asmgen.signExtendVariableLsb(targetAsmVarName, BaseDataType.BYTE)
|
||||||
asmgen.signExtendLongVariableMsw(targetAsmVarName, BaseDataType.WORD)
|
asmgen.signExtendLongVariable(targetAsmVarName, BaseDataType.WORD)
|
||||||
}
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@@ -2752,7 +2767,7 @@ $endLabel""")
|
|||||||
sta $targetAsmVarName
|
sta $targetAsmVarName
|
||||||
lda $sourceAsmVarName+1
|
lda $sourceAsmVarName+1
|
||||||
sta $targetAsmVarName+1""")
|
sta $targetAsmVarName+1""")
|
||||||
asmgen.signExtendLongVariableMsw(targetAsmVarName, BaseDataType.WORD)
|
asmgen.signExtendLongVariable(targetAsmVarName, BaseDataType.WORD)
|
||||||
}
|
}
|
||||||
BaseDataType.FLOAT -> {
|
BaseDataType.FLOAT -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@@ -3124,22 +3139,89 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignVariableLong(target: AsmAssignTarget, varName: String, sourceDt: DataType) {
|
private fun assignVariableLong(target: AsmAssignTarget, varName: String, sourceDt: DataType) {
|
||||||
require(sourceDt.isLong)
|
require(sourceDt.isByte || sourceDt.isWord || sourceDt.isLong) {
|
||||||
|
"need byte/word/long as source value to assign to long variable $varName ${target.position}"
|
||||||
|
}
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
asmgen.out("""
|
when(sourceDt) {
|
||||||
lda $varName
|
DataType.BYTE -> {
|
||||||
sta ${target.asmVarname}
|
TODO("signed byte to long var")
|
||||||
lda $varName+1
|
}
|
||||||
sta ${target.asmVarname}+1
|
DataType.UBYTE -> {
|
||||||
lda $varName+2
|
TODO("ubyte to long var")
|
||||||
sta ${target.asmVarname}+2
|
}
|
||||||
lda $varName+3
|
DataType.WORD -> {
|
||||||
sta ${target.asmVarname}+3""")
|
TODO("signed word to long var")
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
TODO("ubyte to long var")
|
||||||
|
}
|
||||||
|
DataType.LONG -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varName
|
||||||
|
sta ${target.asmVarname}
|
||||||
|
lda $varName+1
|
||||||
|
sta ${target.asmVarname}+1
|
||||||
|
lda $varName+2
|
||||||
|
sta ${target.asmVarname}+2
|
||||||
|
lda $varName+3
|
||||||
|
sta ${target.asmVarname}+3""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("wrong dt ${target.position}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
TargetStorageKind.ARRAY -> TODO("assign long to array ${target.position}")
|
||||||
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
||||||
TargetStorageKind.REGISTER -> TODO("32 bits register assign? (we have no 32 bits registers right now) ${target.position}")
|
TargetStorageKind.REGISTER -> {
|
||||||
|
require(target.register in combinedLongRegisters)
|
||||||
|
val regstart = target.register.toString().take(2).lowercase()
|
||||||
|
when(sourceDt) {
|
||||||
|
DataType.BYTE -> {
|
||||||
|
asmgen.out(" lda $varName | sta cx16.$regstart")
|
||||||
|
asmgen.signExtendLongVariable("cx16.$regstart", sourceDt.base)
|
||||||
|
}
|
||||||
|
DataType.UBYTE -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varName
|
||||||
|
sta cx16.$regstart
|
||||||
|
lda #0
|
||||||
|
sta cx16.$regstart+1
|
||||||
|
sta cx16.$regstart+2
|
||||||
|
sta cx16.$regstart+3""")
|
||||||
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varName
|
||||||
|
sta cx16.$regstart
|
||||||
|
lda $varName+1
|
||||||
|
sta cx16.$regstart+1""")
|
||||||
|
asmgen.signExtendLongVariable("cx16.$regstart", sourceDt.base)
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varName
|
||||||
|
sta cx16.$regstart
|
||||||
|
lda $varName+1
|
||||||
|
sta cx16.$regstart+1
|
||||||
|
lda #0
|
||||||
|
sta cx16.$regstart+2
|
||||||
|
sta cx16.$regstart+3""")
|
||||||
|
}
|
||||||
|
DataType.LONG -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varName
|
||||||
|
sta cx16.$regstart
|
||||||
|
lda $varName+1
|
||||||
|
sta cx16.$regstart+1
|
||||||
|
lda $varName+2
|
||||||
|
sta cx16.$regstart+2
|
||||||
|
lda $varName+3
|
||||||
|
sta cx16.$regstart+3""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("wrong dt ${target.position}")
|
||||||
|
}
|
||||||
|
}
|
||||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||||
}
|
}
|
||||||
@@ -3624,18 +3706,22 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignRegisterLong(target: AsmAssignTarget, lsw: RegisterOrPair, msw: RegisterOrPair) {
|
internal fun assignRegisterLong(target: AsmAssignTarget, pairedRegisters: RegisterOrPair) {
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
asmgen.out("""
|
if(pairedRegisters in combinedLongRegisters) {
|
||||||
lda cx16.r0L
|
val startreg = pairedRegisters.name.take(2).lowercase()
|
||||||
sta ${target.asmVarname}
|
asmgen.out("""
|
||||||
lda cx16.r0H
|
lda cx16.$startreg
|
||||||
sta ${target.asmVarname}+1
|
sta ${target.asmVarname}
|
||||||
lda cx16.r1L
|
lda cx16.$startreg+1
|
||||||
sta ${target.asmVarname}+2
|
sta ${target.asmVarname}+1
|
||||||
lda cx16.r1H
|
lda cx16.$startreg+2
|
||||||
sta ${target.asmVarname}+3""")
|
sta ${target.asmVarname}+2
|
||||||
|
lda cx16.$startreg+3
|
||||||
|
sta ${target.asmVarname}+3""")
|
||||||
|
}
|
||||||
|
else throw AssemblyError("only combined vreg allowed as long target ${target.position}")
|
||||||
}
|
}
|
||||||
TargetStorageKind.ARRAY -> {
|
TargetStorageKind.ARRAY -> {
|
||||||
TODO("assign 32 bits int in R0:R1 into array ${target.position}")
|
TODO("assign 32 bits int in R0:R1 into array ${target.position}")
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplacemodificationLongWithVariable(targetVar: String, operator: String, sourceVar: String) {
|
internal fun inplacemodificationLongWithVariable(targetVar: String, operator: String, sourceVar: String) {
|
||||||
when(operator) {
|
when(operator) {
|
||||||
"+" -> {
|
"+" -> {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
@@ -658,7 +658,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplacemodificationLongWithLiteralval(variable: String, operator: String, value: Int) {
|
internal fun inplacemodificationLongWithLiteralval(variable: String, operator: String, value: Int) {
|
||||||
|
|
||||||
fun inplaceLongShiftLeft() {
|
fun inplaceLongShiftLeft() {
|
||||||
when {
|
when {
|
||||||
|
|||||||
@@ -797,11 +797,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
BaseDataType.UWORD -> {
|
BaseDataType.UWORD -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
||||||
addInstr(result, IRInstruction(Opcode.EXTS, type = IRDataType.WORD, reg1 = actualResultReg2, reg2=tr.resultReg), null)
|
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.WORD, reg1 = actualResultReg2, reg2=tr.resultReg), null)
|
||||||
}
|
}
|
||||||
BaseDataType.WORD -> {
|
BaseDataType.WORD -> {
|
||||||
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
actualResultReg2 = codeGen.registers.next(IRDataType.LONG)
|
||||||
addInstr(result, IRInstruction(Opcode.EXT, type = IRDataType.WORD, reg1 = actualResultReg2, reg2=tr.resultReg), null)
|
addInstr(result, IRInstruction(Opcode.EXTS, type = IRDataType.WORD, reg1 = actualResultReg2, reg2=tr.resultReg), null)
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird cast value type ${cast.position}")
|
else -> throw AssemblyError("weird cast value type ${cast.position}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,14 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
|
|||||||
|
|
||||||
override fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> {
|
override fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> {
|
||||||
|
|
||||||
if(numLiteral.type==BaseDataType.LONG && parent !is Assignment && parent !is VarDecl) {
|
if(numLiteral.type==BaseDataType.LONG) {
|
||||||
// see if LONG values may be reduced to something smaller
|
// see if LONG values may be reduced to something smaller
|
||||||
val smaller = NumericLiteral.optimalInteger(numLiteral.number.toInt(), numLiteral.position)
|
val smaller = NumericLiteral.optimalInteger(numLiteral.number.toInt(), numLiteral.position)
|
||||||
if(smaller.type!=BaseDataType.LONG) {
|
if(smaller.type!=BaseDataType.LONG) {
|
||||||
return listOf(IAstModification.ReplaceNode(numLiteral, smaller, parent))
|
if(parent !is Assignment || !parent.target.inferType(program).isLong) {
|
||||||
|
// do NOT reduce the type if the target of the assignment is a long
|
||||||
|
return listOf(IAstModification.ReplaceNode(numLiteral, smaller, parent))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1554,7 +1554,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
} else if(leftDt.isBool && rightDt.isByte || leftDt.isByte && rightDt.isBool) {
|
} else if(leftDt.isBool && rightDt.isByte || leftDt.isByte && rightDt.isBool) {
|
||||||
// expression with one side BOOL other side (U)BYTE is allowed; bool==byte
|
// expression with one side BOOL other side (U)BYTE is allowed; bool==byte
|
||||||
} else if((expr.operator == "<<" || expr.operator == ">>")
|
} else if((expr.operator == "<<" || expr.operator == ">>")
|
||||||
&& (leftDt.isWord && rightDt.isByte || leftDt.isLong && rightDt.isByte || leftDt.isLong && rightDt.isWord)) {
|
&& (leftDt.isByte && rightDt.isByte ||
|
||||||
|
leftDt.isWord && rightDt.isByte ||
|
||||||
|
leftDt.isWord && rightDt.isWord ||
|
||||||
|
leftDt.isLong && rightDt.isByte ||
|
||||||
|
leftDt.isLong && rightDt.isWord)) {
|
||||||
// exception allowed: shifting a word by a byte, long by a word or byte
|
// exception allowed: shifting a word by a byte, long by a word or byte
|
||||||
} else if((expr.operator in BitwiseOperators) && (leftDt.isInteger && rightDt.isInteger)) {
|
} else if((expr.operator in BitwiseOperators) && (leftDt.isInteger && rightDt.isInteger)) {
|
||||||
// exception allowed: bitwise operations with any integers
|
// exception allowed: bitwise operations with any integers
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ TODO
|
|||||||
LONG TYPE
|
LONG TYPE
|
||||||
---------
|
---------
|
||||||
- call convention: return long -> return it in R0+R1.... because AY is only 16 bits...
|
- call convention: return long -> return it in R0+R1.... because AY is only 16 bits...
|
||||||
- call convention: long param -> passed as regular variable NOT via R0:R1 asmsubs don't have syntax for this so use explicit separate msw() and lsw() arguments...
|
- call convention: long param -> passed as regular variable NOT via R0:R1? asmsubs don't have syntax for this so use explicit separate msw() and lsw() arguments... Or introduce new syntax for R0+R1 combo's?
|
||||||
- implement << >> expressions on longs
|
|
||||||
- implement the bitwise & | ^ operations as expressions on longs (all types args)
|
- implement the bitwise & | ^ operations as expressions on longs (all types args)
|
||||||
- make sure == and != work with longs against byte and words as well signed and unsigned
|
- make sure == and != work with longs against byte and words as well signed and unsigned
|
||||||
- how hard is it to also implement the other comparison operators on longs?
|
- how hard is it to also implement the other comparison operators on longs?
|
||||||
|
|||||||
@@ -15,7 +15,16 @@ main {
|
|||||||
txt.print_ulhex(lv1, false)
|
txt.print_ulhex(lv1, false)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
txt.print_l(lv1<<3) ; TODO fix compiler error
|
lv1 = 999999
|
||||||
|
txt.print_l(lv1<<3)
|
||||||
|
txt.nl()
|
||||||
|
cx16.r4sL = -55
|
||||||
|
lv1 = 999999
|
||||||
|
txt.print_l(lv1+cx16.r4sL)
|
||||||
|
txt.nl()
|
||||||
|
cx16.r4s = -5555
|
||||||
|
lv1 = 999999
|
||||||
|
txt.print_l(lv1+cx16.r4s)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
lv2 <<= cx16.r0L
|
lv2 <<= cx16.r0L
|
||||||
@@ -51,6 +60,7 @@ main {
|
|||||||
b2 = lv2 != cx16.r0s
|
b2 = lv2 != cx16.r0s
|
||||||
b1 = lv1 != lv2
|
b1 = lv1 != lv2
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sub start2() {
|
sub start2() {
|
||||||
@@ -174,4 +184,4 @@ main {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
;}
|
||||||
|
|||||||
Reference in New Issue
Block a user