mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +00:00
adding long arrays
This commit is contained in:
@@ -145,7 +145,7 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
return if(splitwordarray && actualElementDt.isWord)
|
||||
DataType(BaseDataType.ARRAY_SPLITW, actualElementDt, null)
|
||||
else {
|
||||
if(actualElementDt.isNumericOrBool && actualElementDt != BaseDataType.LONG)
|
||||
if(actualElementDt.isNumericOrBool)
|
||||
DataType(BaseDataType.ARRAY, actualElementDt, null)
|
||||
else
|
||||
throw NoSuchElementException("invalid basic element dt $elementDt")
|
||||
@@ -224,6 +224,7 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
BaseDataType.WORD -> "word[]"
|
||||
BaseDataType.UBYTE -> "ubyte[]"
|
||||
BaseDataType.UWORD -> "uword[]"
|
||||
BaseDataType.LONG -> "long[]"
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
}
|
||||
@@ -286,6 +287,7 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
BaseDataType.BOOL -> "bool["
|
||||
BaseDataType.BYTE -> "byte["
|
||||
BaseDataType.WORD -> "@nosplit word["
|
||||
BaseDataType.LONG -> "long["
|
||||
BaseDataType.FLOAT -> "float["
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
}
|
||||
@@ -365,6 +367,7 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
||||
val isWordArray = base.isArray && !base.isPointerArray && (sub == BaseDataType.UWORD || sub == BaseDataType.WORD)
|
||||
val isUnsignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.UWORD
|
||||
val isSignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.WORD
|
||||
val isLongArray = base.isArray && sub == BaseDataType.LONG
|
||||
val isFloatArray = base.isArray && !base.isPointerArray && sub == BaseDataType.FLOAT
|
||||
val isString = base == BaseDataType.STR
|
||||
val isBool = base == BaseDataType.BOOL
|
||||
|
||||
@@ -27,8 +27,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val sscope = fcall.definingISub()
|
||||
|
||||
when (fcall.name) {
|
||||
"lsw" -> throw AssemblyError("lsw() should have been removed or replaced by a const value")
|
||||
"msw" -> throw AssemblyError("msw() should have been removed or replaced by a const value")
|
||||
"msw" -> funcMsw(fcall, resultRegister)
|
||||
"lsw" -> funcLsw(fcall, resultRegister)
|
||||
"msb" -> funcMsb(fcall, resultRegister)
|
||||
"lsb" -> funcLsb(fcall, resultRegister)
|
||||
"mkword" -> funcMkword(fcall, resultRegister)
|
||||
@@ -1185,7 +1185,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
private fun funcMsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
val arg = fcall.args.single()
|
||||
if (!arg.type.isWord)
|
||||
throw AssemblyError("msb required word argument")
|
||||
throw AssemblyError("msb requires word argument")
|
||||
if (arg is PtNumber)
|
||||
throw AssemblyError("msb(const) should have been const-folded away")
|
||||
if (arg is PtIdentifier) {
|
||||
@@ -1371,6 +1371,53 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcMsw(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
val arg = fcall.args.single()
|
||||
if (!arg.type.isLong)
|
||||
throw AssemblyError("msw requires long argument")
|
||||
if (arg is PtNumber)
|
||||
throw AssemblyError("msw(const) should have been const-folded away")
|
||||
if (arg is PtIdentifier) {
|
||||
val sourceName = asmgen.asmVariableName(arg)
|
||||
when(resultRegister) {
|
||||
RegisterOrPair.AX -> asmgen.out(" lda $sourceName+2 | ldx $sourceName+3")
|
||||
null, RegisterOrPair.AY -> asmgen.out(" lda $sourceName+2 | ldy $sourceName+3")
|
||||
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName+2 | ldy $sourceName+3")
|
||||
in Cx16VirtualRegisters -> {
|
||||
val regname = resultRegister.name.lowercase()
|
||||
asmgen.out(" lda $sourceName+2 | sta cx16.$regname | lda $sourceName+3 | sta cx16.$regname+1")
|
||||
}
|
||||
else -> throw AssemblyError("invalid reg")
|
||||
}
|
||||
} else {
|
||||
TODO("msw(expression) ${fcall.position} - use a temporary variable for now")
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcLsw(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
val arg = fcall.args.single()
|
||||
if (!arg.type.isLong)
|
||||
throw AssemblyError("lsw requires long argument")
|
||||
if (arg is PtNumber)
|
||||
throw AssemblyError("lsw(const) should have been const-folded away")
|
||||
if (arg is PtIdentifier) {
|
||||
val sourceName = asmgen.asmVariableName(arg)
|
||||
when(resultRegister) {
|
||||
RegisterOrPair.AX -> asmgen.out(" lda $sourceName | ldx $sourceName+1")
|
||||
null, RegisterOrPair.AY -> asmgen.out(" lda $sourceName | ldy $sourceName+1")
|
||||
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName | ldy $sourceName+1")
|
||||
in Cx16VirtualRegisters -> {
|
||||
val regname = resultRegister.name.lowercase()
|
||||
asmgen.out(" lda $sourceName | sta cx16.$regname | lda $sourceName+1 | sta cx16.$regname+1")
|
||||
}
|
||||
else -> throw AssemblyError("invalid reg")
|
||||
}
|
||||
} else {
|
||||
TODO("lsw(expression) ${fcall.position} - use a temporary variable for now")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun translateArguments(call: PtBuiltinFunctionCall, scope: IPtSubroutine?) {
|
||||
val signature = BuiltinFunctions.getValue(call.name)
|
||||
val callConv = signature.callConvention(call.args.map {
|
||||
|
||||
@@ -505,137 +505,158 @@ $endLabel""")
|
||||
is StMemVar -> symbol.length!!
|
||||
else -> 0u
|
||||
}
|
||||
when {
|
||||
iterableDt.isString -> {
|
||||
if(asmgen.options.romable) {
|
||||
val indexVar = asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
asmgen.out("""
|
||||
|
||||
fun iterateStrings() {
|
||||
if(asmgen.options.romable) {
|
||||
val indexVar = asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
sty $indexVar
|
||||
$loopLabel lda $iterableName,y
|
||||
beq $endLabel
|
||||
sta ${asmgen.asmVariableName(stmt.variable)}""")
|
||||
asmgen.translate(stmt.statements)
|
||||
asmgen.out("""
|
||||
asmgen.translate(stmt.statements)
|
||||
asmgen.out("""
|
||||
inc $indexVar
|
||||
ldy $indexVar
|
||||
bne $loopLabel
|
||||
$endLabel""")
|
||||
} else {
|
||||
val indexVar = asmgen.makeLabel("for_index")
|
||||
asmgen.out("""
|
||||
} else {
|
||||
val indexVar = asmgen.makeLabel("for_index")
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
sty $indexVar
|
||||
$loopLabel lda $iterableName,y
|
||||
beq $endLabel
|
||||
sta ${asmgen.asmVariableName(stmt.variable)}""")
|
||||
asmgen.translate(stmt.statements)
|
||||
asmgen.out("""
|
||||
asmgen.translate(stmt.statements)
|
||||
asmgen.out("""
|
||||
inc $indexVar
|
||||
ldy $indexVar
|
||||
bne $loopLabel
|
||||
$indexVar .byte 0
|
||||
$endLabel""")
|
||||
}
|
||||
}
|
||||
iterableDt.isByteArray || iterableDt.isBoolArray -> {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(iterableDt.elementType().base, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
asmgen.out("""
|
||||
}
|
||||
|
||||
fun iterateBytes() {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(iterableDt.elementType().base, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
$loopLabel sty $indexVar
|
||||
lda $iterableName,y
|
||||
sta ${asmgen.asmVariableName(stmt.variable)}""")
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=255u) {
|
||||
asmgen.out("""
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=255u) {
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
cpy #$numElements
|
||||
beq $endLabel
|
||||
bne $loopLabel""")
|
||||
} else {
|
||||
// length is 256
|
||||
asmgen.out("""
|
||||
} else {
|
||||
// length is 256
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
bne $loopLabel
|
||||
beq $endLabel""")
|
||||
}
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
iterableDt.isSplitWordArray -> {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
val loopvarName = asmgen.asmVariableName(stmt.variable)
|
||||
asmgen.out("""
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
|
||||
fun iterateSplitWords() {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
val loopvarName = asmgen.asmVariableName(stmt.variable)
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
$loopLabel sty $indexVar
|
||||
lda ${iterableName}_lsb,y
|
||||
sta $loopvarName
|
||||
lda ${iterableName}_msb,y
|
||||
sta $loopvarName+1""")
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=255u) {
|
||||
asmgen.out("""
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=255u) {
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
cpy #$numElements
|
||||
beq $endLabel
|
||||
bne $loopLabel""")
|
||||
} else {
|
||||
// length is 256
|
||||
asmgen.out("""
|
||||
} else {
|
||||
// length is 256
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
bne $loopLabel
|
||||
beq $endLabel""")
|
||||
}
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
iterableDt.isWordArray -> {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
val loopvarName = asmgen.asmVariableName(stmt.variable)
|
||||
asmgen.out("""
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
|
||||
fun iterateWords(actuallyLongs: Boolean = false) {
|
||||
val indexVar = if(asmgen.options.romable)
|
||||
asmgen.createTempVarReused(BaseDataType.UBYTE, false, stmt)
|
||||
else
|
||||
asmgen.makeLabel("for_index")
|
||||
val loopvarName = asmgen.asmVariableName(stmt.variable)
|
||||
asmgen.out("""
|
||||
ldy #0
|
||||
$loopLabel sty $indexVar
|
||||
lda $iterableName,y
|
||||
sta $loopvarName
|
||||
lda $iterableName+1,y
|
||||
sta $loopvarName+1""")
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=127u) {
|
||||
if(actuallyLongs) {
|
||||
asmgen.out("""
|
||||
lda $iterableName+2,y
|
||||
sta $loopvarName+2
|
||||
lda $iterableName+3,y
|
||||
sta $loopvarName+3""")
|
||||
}
|
||||
asmgen.translate(stmt.statements)
|
||||
if(numElements<=127u) {
|
||||
if(actuallyLongs) {
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
iny
|
||||
iny
|
||||
iny
|
||||
cpy #${numElements*4u}
|
||||
beq $endLabel
|
||||
bne $loopLabel""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
@@ -643,6 +664,19 @@ $loopLabel sty $indexVar
|
||||
cpy #${numElements*2u}
|
||||
beq $endLabel
|
||||
bne $loopLabel""")
|
||||
}
|
||||
} else {
|
||||
if(actuallyLongs) {
|
||||
// array size is 64 longs, 256 bytes
|
||||
asmgen.out("""
|
||||
ldy $indexVar
|
||||
iny
|
||||
iny
|
||||
iny
|
||||
iny
|
||||
bne $loopLabel
|
||||
beq $endLabel""")
|
||||
|
||||
} else {
|
||||
// array size is 128 words, 256 bytes
|
||||
asmgen.out("""
|
||||
@@ -652,23 +686,29 @@ $loopLabel sty $indexVar
|
||||
bne $loopLabel
|
||||
beq $endLabel""")
|
||||
}
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
}
|
||||
if(!asmgen.options.romable) {
|
||||
if(numElements>=16u) {
|
||||
// allocate index var on ZP if possible, otherwise inline
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = { (address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""") },
|
||||
failure = { asmgen.out("$indexVar .byte 0") }
|
||||
)
|
||||
} else {
|
||||
asmgen.out("$indexVar .byte 0")
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
iterableDt.isFloatArray -> {
|
||||
throw AssemblyError("for loop with floating point variables is not supported")
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
|
||||
when {
|
||||
iterableDt.isString -> iterateStrings()
|
||||
iterableDt.isByteArray || iterableDt.isBoolArray -> iterateBytes()
|
||||
iterableDt.isSplitWordArray -> iterateSplitWords()
|
||||
iterableDt.isWordArray -> iterateWords()
|
||||
iterableDt.isLongArray -> iterateWords(true)
|
||||
iterableDt.isFloatArray -> throw AssemblyError("for loop with floating point variables is not supported")
|
||||
else -> throw AssemblyError("can't iterate over $iterableDt")
|
||||
}
|
||||
asmgen.loopEndLabels.removeLast()
|
||||
|
||||
@@ -901,6 +901,16 @@ internal class ProgramAndVarsGen(
|
||||
asmgen.out(" .sint " + chunk.joinToString())
|
||||
}
|
||||
}
|
||||
dt.isLongArray -> {
|
||||
val data = makeArrayFillDataSigned(dt, value, orNumberOfZeros)
|
||||
if (data.size <= 16)
|
||||
asmgen.out("$varname\t.dint ${data.joinToString()}")
|
||||
else {
|
||||
asmgen.out(varname)
|
||||
for (chunk in data.chunked(16))
|
||||
asmgen.out(" .dint " + chunk.joinToString())
|
||||
}
|
||||
}
|
||||
dt.isFloatArray -> {
|
||||
val array = value ?: zeroFilledArray(orNumberOfZeros!!)
|
||||
val floatFills = array.map {
|
||||
@@ -1023,7 +1033,7 @@ internal class ProgramAndVarsGen(
|
||||
val number = it.number!!.toInt()
|
||||
"$" + number.toString(16).padStart(4, '0')
|
||||
}
|
||||
dt.isArray && dt.elementType().isSignedWord -> array.map {
|
||||
dt.isSignedWordArray -> array.map {
|
||||
val number = it.number!!.toInt()
|
||||
val hexnum = number.absoluteValue.toString(16).padStart(4, '0')
|
||||
if(number>=0)
|
||||
@@ -1031,6 +1041,14 @@ internal class ProgramAndVarsGen(
|
||||
else
|
||||
"-$$hexnum"
|
||||
}
|
||||
dt.isLongArray -> array.map {
|
||||
val number = it.number!!.toInt()
|
||||
val hexnum = number.absoluteValue.toString(16).padStart(8, '0')
|
||||
if(number>=0)
|
||||
"$$hexnum"
|
||||
else
|
||||
"-$$hexnum"
|
||||
}
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3964,7 +3964,20 @@ $endLabel""")
|
||||
stz ${target.asmVarname}+2
|
||||
stz ${target.asmVarname}+3""")
|
||||
}
|
||||
TargetStorageKind.ARRAY -> TODO("assign long zero to array ${target.position}")
|
||||
TargetStorageKind.ARRAY -> {
|
||||
val deref = target.array!!.pointerderef
|
||||
if(deref!=null) {
|
||||
pointergen.assignLong(IndexedPtrTarget(target), 0)
|
||||
return
|
||||
}
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
||||
asmgen.out("""
|
||||
lda #0
|
||||
sta ${target.asmVarname},y
|
||||
sta ${target.asmVarname}+1,y
|
||||
sta ${target.asmVarname}+2,y
|
||||
sta ${target.asmVarname}+3,y""")
|
||||
}
|
||||
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.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
@@ -3988,7 +4001,24 @@ $endLabel""")
|
||||
store(hex.substring(2,4), 2)
|
||||
store(hex.substring(0,2), 3)
|
||||
}
|
||||
TargetStorageKind.ARRAY -> TODO("assign long $long to array ${target.position}")
|
||||
TargetStorageKind.ARRAY -> {
|
||||
val deref = target.array!!.pointerderef
|
||||
if(deref!=null) {
|
||||
pointergen.assignWord(IndexedPtrTarget(target), long)
|
||||
return
|
||||
}
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
||||
val hex = long.toUInt().toString(16).padStart(8, '0')
|
||||
asmgen.out("""
|
||||
lda #$${hex.substring(6,8)}
|
||||
sta ${target.asmVarname},y
|
||||
lda #$${hex.substring(4, 6)}
|
||||
sta ${target.asmVarname}+1,y
|
||||
lda #$${hex.substring(2, 4)}
|
||||
sta ${target.asmVarname}+2,y
|
||||
lda #$${hex.take(2)}
|
||||
sta ${target.asmVarname}+3,y""")
|
||||
}
|
||||
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.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
@@ -4009,7 +4039,7 @@ $endLabel""")
|
||||
TargetStorageKind.ARRAY -> {
|
||||
val deref = target.array!!.pointerderef
|
||||
if(deref!=null) {
|
||||
pointergen.assignWord(IndexedPtrTarget(target), word)
|
||||
pointergen.assignWord(IndexedPtrTarget(target), 0)
|
||||
return
|
||||
}
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
||||
|
||||
@@ -302,6 +302,25 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
target.datatype.isLong -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationLongWithLiteralval(targetVarName, operator, value.boolean!!.asInt())
|
||||
SourceStorageKind.LITERALNUMBER -> inplacemodificationLongWithLiteralval(targetVarName, operator, value.number!!.number.toInt())
|
||||
SourceStorageKind.VARIABLE -> inplacemodificationLongWithVariable(targetVarName, operator, value.asmVarname)
|
||||
SourceStorageKind.REGISTER -> inplacemodificationLongWithVariable(targetVarName, operator, regName(value))
|
||||
SourceStorageKind.MEMORY -> TODO("inplace long modifiication ${target.position}")
|
||||
SourceStorageKind.ARRAY -> TODO("inplace long modifiication ${target.position}")
|
||||
SourceStorageKind.EXPRESSION -> {
|
||||
if(value.expression is PtTypeCast) {
|
||||
if (tryInplaceModifyWithRemovedRedundantCast(value.expression, target, operator)) return
|
||||
TODO("inplace long modifiication ${target.position}")
|
||||
} else {
|
||||
TODO("inplace long modifiication ${target.position}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.datatype.isFloat -> {
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALBOOLEAN -> inplacemodificationFloatWithLiteralval(targetVarName, operator, value.boolean!!.asInt().toDouble())
|
||||
|
||||
@@ -406,6 +406,10 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
TODO("array ptr assign const word ${target.position}")
|
||||
}
|
||||
|
||||
internal fun assignLong(target: IndexedPtrTarget, long: Int) {
|
||||
TODO("array ptr assign const long ${target.position}")
|
||||
}
|
||||
|
||||
internal fun assignFloat(target: IndexedPtrTarget, float: Double) {
|
||||
TODO("array ptr assign const float ${target.position}")
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
"callfar" -> funcCallfar(call)
|
||||
"callfar2" -> funcCallfar2(call)
|
||||
"call" -> funcCall(call)
|
||||
"lsw" -> throw AssemblyError("lsw() should have been removed or replaced by a const value")
|
||||
"msw" -> throw AssemblyError("msw() should have been removed or replaced by a const value")
|
||||
"msw" -> funcMsw(call)
|
||||
"lsw" -> funcLsw(call)
|
||||
"msb" -> funcMsb(call)
|
||||
"lsb" -> funcLsb(call)
|
||||
"memory" -> funcMemory(call)
|
||||
@@ -525,6 +525,15 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcLsw(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val tr = exprGen.translateExpression(call.args.single())
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
||||
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcMsb(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val tr = exprGen.translateExpression(call.args.single())
|
||||
@@ -535,6 +544,15 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcMsw(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val tr = exprGen.translateExpression(call.args.single())
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val resultReg = codeGen.registers.next(IRDataType.WORD)
|
||||
addInstr(result, IRInstruction(Opcode.MSIG, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcRolRor(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val arg = call.args[0]
|
||||
|
||||
@@ -240,6 +240,11 @@ internal class AstChecker(private val program: Program,
|
||||
errors.err("word loop variable can only loop over bytes or words", forLoop.position)
|
||||
}
|
||||
|
||||
BaseDataType.LONG -> {
|
||||
if(!iterableDt.elementType().isInteger)
|
||||
errors.err("long loop variable can only loop over integers", forLoop.position)
|
||||
}
|
||||
|
||||
BaseDataType.FLOAT -> {
|
||||
// Looping over float variables is very inefficient because the loopvar is going to
|
||||
// get copied over with new values all the time. We don't support this for now.
|
||||
@@ -941,6 +946,9 @@ internal class AstChecker(private val program: Program,
|
||||
dt.isWordArray ->
|
||||
if(arraySize > 128)
|
||||
err("regular word array length must be 1-128, use split array to get to 256")
|
||||
dt.isLongArray ->
|
||||
if(arraySize > 64)
|
||||
err("long array length must be 1-64")
|
||||
dt.isFloatArray ->
|
||||
if(arraySize > 51)
|
||||
err("float array length must be 1-51")
|
||||
@@ -1044,6 +1052,10 @@ internal class AstChecker(private val program: Program,
|
||||
if (length == 0 || length > 128)
|
||||
err("regular word array length must be 1-128, use split array to get to 256")
|
||||
}
|
||||
decl.datatype.isLongArray -> {
|
||||
if (length == 0 || length > 64)
|
||||
err("long array length must be 1-64")
|
||||
}
|
||||
decl.datatype.isFloatArray -> {
|
||||
if (length == 0 || length > 51)
|
||||
err("float array length must be 1-51")
|
||||
@@ -2478,7 +2490,6 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
override fun visit(onGoto: OnGoto) {
|
||||
val t = onGoto.index.inferType(program)
|
||||
if(!onGoto.index.inferType(program).getOrUndef().isUnsignedByte) {
|
||||
errors.err("on..goto index must be an unsigned byte", onGoto.index.position)
|
||||
}
|
||||
|
||||
@@ -386,9 +386,6 @@ class TestMemory: FunSpec({
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
target.memorySize(BaseDataType.UNDEFINED)
|
||||
}
|
||||
shouldThrow<NoSuchElementException> {
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.LONG), 10)
|
||||
}
|
||||
target.memorySize(BaseDataType.BOOL) shouldBe 1
|
||||
target.memorySize(BaseDataType.BYTE) shouldBe 1
|
||||
target.memorySize(BaseDataType.WORD) shouldBe 2
|
||||
@@ -397,6 +394,7 @@ class TestMemory: FunSpec({
|
||||
|
||||
target.memorySize(DataType.BOOL, null) shouldBe 1
|
||||
target.memorySize(DataType.WORD, null) shouldBe 2
|
||||
target.memorySize(DataType.LONG, null) shouldBe 4
|
||||
target.memorySize(DataType.FLOAT, null) shouldBe target.FLOAT_MEM_SIZE
|
||||
|
||||
target.memorySize(DataType.STR, null) shouldBe 2
|
||||
@@ -409,6 +407,7 @@ class TestMemory: FunSpec({
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.BYTE), 10) shouldBe 10
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.WORD), 10) shouldBe 20
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.UWORD), 10) shouldBe 20
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.LONG), 10) shouldBe 40
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.FLOAT), 10) shouldBe 10*target.FLOAT_MEM_SIZE
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.WORD, true), 10) shouldBe 20
|
||||
target.memorySize(DataType.arrayFor(BaseDataType.UWORD, true), 10) shouldBe 20
|
||||
|
||||
@@ -871,6 +871,7 @@ main {
|
||||
DataType.forDt(BaseDataType.FLOAT).isFloat shouldBe true
|
||||
|
||||
DataType.arrayFor(BaseDataType.UBYTE, true).isUnsignedByteArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.LONG).isLongArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.FLOAT).isFloatArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isUnsignedWordArray shouldBe true
|
||||
DataType.arrayFor(BaseDataType.UWORD).isArray shouldBe true
|
||||
@@ -886,9 +887,6 @@ main {
|
||||
shouldThrow<NoSuchElementException> {
|
||||
DataType.arrayFor(BaseDataType.ARRAY)
|
||||
}
|
||||
shouldThrow<NoSuchElementException> {
|
||||
DataType.arrayFor(BaseDataType.LONG)
|
||||
}
|
||||
shouldThrow<NoSuchElementException> {
|
||||
DataType.arrayFor(BaseDataType.UNDEFINED)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,21 @@ main {
|
||||
; }
|
||||
|
||||
sub start() {
|
||||
long[] array = [-1999888777, -999, 42, 0, 77, 123456, 999999999]
|
||||
long xx
|
||||
for xx in array {
|
||||
txt.print_uw(msw(xx))
|
||||
txt.spc()
|
||||
txt.print_uw(lsw(xx))
|
||||
txt.nl()
|
||||
}
|
||||
txt.nl()
|
||||
array[2] = 0
|
||||
array[3] = 222222222
|
||||
array[4] = bignum
|
||||
array[5]++
|
||||
array[6]--
|
||||
|
||||
txt.print_l(-1999888777)
|
||||
txt.spc()
|
||||
txt.print_l(-999)
|
||||
|
||||
@@ -32,6 +32,7 @@ fun DataType.irTypeString(length: UInt?): String {
|
||||
BaseDataType.UWORD -> "uword[$lengthStr]"
|
||||
BaseDataType.BYTE -> "byte[$lengthStr]"
|
||||
BaseDataType.WORD -> "word[$lengthStr]"
|
||||
BaseDataType.LONG -> "long[$lengthStr]"
|
||||
BaseDataType.BOOL -> "bool[$lengthStr]"
|
||||
BaseDataType.FLOAT -> "float[$lengthStr]"
|
||||
else -> throw IllegalArgumentException("invalid sub type")
|
||||
|
||||
@@ -386,6 +386,17 @@ class VmProgramLoader {
|
||||
}
|
||||
}
|
||||
|
||||
variable.dt.isLongArray -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
value.fold(
|
||||
{ memory.setSL(address, it.toInt()) },
|
||||
{ throw IRParseException("didn't expect bool") }
|
||||
)
|
||||
address += 4
|
||||
}
|
||||
}
|
||||
|
||||
variable.dt.isFloatArray -> {
|
||||
for (elt in iElts) {
|
||||
val value = getInitializerValue(variable.dt, elt, symbolAddresses)
|
||||
|
||||
Reference in New Issue
Block a user