mirror of
https://github.com/irmen/prog8.git
synced 2025-10-25 05:18:38 +00:00
Compare commits
4 Commits
v12.0-beta
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c0affd1bf | ||
|
|
c7158fd968 | ||
|
|
de2f3f0d0d | ||
|
|
c0286e3349 |
@@ -866,7 +866,7 @@ class AsmGen6502Internal (
|
||||
}
|
||||
target.datatype.isLong -> {
|
||||
if(value is PtNumber) {
|
||||
val hex = value.asConstInteger()!!.toString(16).padStart(8, '0')
|
||||
val hex = value.asConstInteger()!!.toLongHex()
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
out("""
|
||||
@@ -1426,7 +1426,10 @@ $repeatLabel""")
|
||||
sta $asmvar+3""")
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
out(" lda #0 | sta $asmvar+2 | sta $asmvar+3")
|
||||
if(isTargetCpu(CpuType.CPU65C02))
|
||||
out(" stz $asmvar+2 | stz $asmvar+3")
|
||||
else
|
||||
out(" lda #0 | sta $asmvar+2 | sta $asmvar+3")
|
||||
}
|
||||
BaseDataType.WORD -> {
|
||||
out("""
|
||||
@@ -2109,6 +2112,22 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun loadIndirectLongIntoR14R15(zpPtrVar: String, offset: UByte) {
|
||||
out("""
|
||||
ldy #$offset
|
||||
lda ($zpPtrVar),y
|
||||
sta cx16.r14
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sta cx16.r14+1
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sta cx16.r14+2
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sta cx16.r14+3""")
|
||||
}
|
||||
|
||||
internal fun storeIndirectByte(byte: Int, zpPtrVar: String, offset: UByte) {
|
||||
if (offset > 0u) {
|
||||
out(" lda #$byte | ldy #$offset | sta ($zpPtrVar),y")
|
||||
@@ -2497,4 +2516,8 @@ internal class SubroutineExtraAsmInfo {
|
||||
var usedFloatEvalResultVar2 = false
|
||||
|
||||
val extraVars = mutableListOf<Triple<BaseDataType, String, UInt?>>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun Double.toLongHex(): String = this.toUInt().toString(16).padStart(8, '0')
|
||||
internal fun Int.toLongHex(): String = this.toUInt().toString(16).padStart(8, '0')
|
||||
|
||||
@@ -416,7 +416,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
if(arg2.type.isLong) {
|
||||
if(arg1 is PtIdentifier && arg2 is PtNumber) {
|
||||
val var1 = asmgen.asmVariableName(arg1)
|
||||
val hex = arg2.number.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = arg2.number.toLongHex()
|
||||
asmgen.out("""
|
||||
sec
|
||||
lda $var1
|
||||
@@ -538,7 +538,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" lda $variable | lsr a | bcc + | ora #$80 |+ | sta $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
@@ -557,7 +557,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" lsr $variable+1 | ror $variable | bcc + | lda $variable+1 | ora #$80 | sta $variable+1 |+ ")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.LONG -> {
|
||||
@@ -577,7 +577,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
sta $variable+3
|
||||
+""")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
@@ -620,7 +620,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" ror $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
@@ -641,7 +641,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" ror $variable+1 | ror $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.LONG -> {
|
||||
@@ -652,7 +652,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" ror $variable+3 | ror $variable+2 | ror $variable+1 | ror $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
@@ -684,7 +684,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" lda $variable | cmp #$80 | rol a | sta $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
@@ -703,7 +703,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" asl $variable | rol $variable+1 | bcc + | inc $variable |+ ")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.LONG -> {
|
||||
@@ -721,7 +721,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
inc $variable
|
||||
+""")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
@@ -763,7 +763,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" rol $variable")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
@@ -784,7 +784,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" rol $variable | rol $variable+1")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
BaseDataType.LONG -> {
|
||||
@@ -795,7 +795,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
val variable = asmgen.asmVariableName(what)
|
||||
asmgen.out(" rol $variable | rol $variable+1 | rol $variable+2 | rol $variable+3")
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
else -> throw AssemblyError("weird node")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
|
||||
@@ -1406,7 +1406,7 @@ _jump jmp (${target.asmLabel})
|
||||
if(left is PtIdentifier) {
|
||||
val leftvar = asmgen.asmVariableName(left)
|
||||
if(constRight!=null) {
|
||||
val hex = constRight.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = constRight.toLongHex()
|
||||
asmgen.out("""
|
||||
lda $leftvar
|
||||
cmp #$${hex.substring(6,8)}
|
||||
@@ -1437,7 +1437,7 @@ _jump jmp (${target.asmLabel})
|
||||
// TODO cannot easily preserve R14:R15 on stack because we need the status flags of the comparison in between...
|
||||
asmgen.assignExpressionToRegister(left, RegisterOrPair.R14R15_32, left.type.isSigned)
|
||||
if(constRight!=null) {
|
||||
val hex = constRight.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = constRight.toLongHex()
|
||||
asmgen.out("""
|
||||
lda cx16.r14
|
||||
cmp #$${hex.substring(6,8)}
|
||||
@@ -2113,4 +2113,5 @@ _jump jmp (${target.asmLabel})
|
||||
else -> throw AssemblyError("expected comparison operator")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -368,7 +368,7 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat
|
||||
private fun translateLongExprEqualsNumber(expr: PtExpression, number: Int, falseLabel: String) {
|
||||
// if L==number
|
||||
// TODO reuse code from ifElse?
|
||||
val hex = number.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = number.toLongHex()
|
||||
if(expr is PtIdentifier) {
|
||||
val varname = asmgen.asmVariableName(expr)
|
||||
asmgen.out("""
|
||||
|
||||
@@ -1044,7 +1044,7 @@ internal class ProgramAndVarsGen(
|
||||
}
|
||||
dt.isLongArray -> array.map {
|
||||
val number = it.number!!.toInt()
|
||||
val hexnum = number.absoluteValue.toString(16).padStart(8, '0')
|
||||
val hexnum = number.absoluteValue.toLongHex()
|
||||
if(number>=0)
|
||||
"$$hexnum"
|
||||
else
|
||||
|
||||
@@ -5,6 +5,7 @@ import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
import prog8.codegen.cpu6502.VariableAllocator
|
||||
import prog8.codegen.cpu6502.toLongHex
|
||||
import kotlin.math.log2
|
||||
|
||||
|
||||
@@ -787,8 +788,12 @@ internal class AssignmentAsmGen(
|
||||
|
||||
return if(translatedOk)
|
||||
true
|
||||
else
|
||||
else {
|
||||
if(expr.type.isLong && expr.operator in "*/%")
|
||||
TODO("long multiplication or division ${expr.position}")
|
||||
|
||||
anyExprGen.assignAnyExpressionUsingStack(expr, assign)
|
||||
}
|
||||
}
|
||||
|
||||
private fun optimizedComparison(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
@@ -1783,7 +1788,7 @@ internal class AssignmentAsmGen(
|
||||
}
|
||||
is PtNumber -> {
|
||||
asmgen.assignExpressionTo(left, target)
|
||||
val hex = right.number.toInt().toString(16).padStart(8, '0')
|
||||
val hex = right.number.toLongHex()
|
||||
if (target.kind == TargetStorageKind.VARIABLE) {
|
||||
if (expr.operator == "+") {
|
||||
asmgen.out("""
|
||||
@@ -2617,7 +2622,7 @@ $endLabel""")
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
} else if(valueDt.isUnsignedWord) {
|
||||
} else if(valueDt.isWord) {
|
||||
when(target.register) {
|
||||
RegisterOrPair.A,
|
||||
RegisterOrPair.X,
|
||||
@@ -2636,7 +2641,38 @@ $endLabel""")
|
||||
// 'cast' uword into a 16 bits register, just assign it
|
||||
return assignExpressionToRegister(value, target.register!!, targetDt.isSigned)
|
||||
}
|
||||
in combinedLongRegisters -> TODO("assign wprd to long reg ${value.position}")
|
||||
RegisterOrPair.R0R1_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R0, false)
|
||||
asmgen.signExtendLongVariable("cx16.r0", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R2R3_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R2, false)
|
||||
asmgen.signExtendLongVariable("cx16.r2", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R4R5_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R4, false)
|
||||
asmgen.signExtendLongVariable("cx16.r4", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R6R7_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R6, false)
|
||||
asmgen.signExtendLongVariable("cx16.r6", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R8R9_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R8, false)
|
||||
asmgen.signExtendLongVariable("cx16.r8", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R10R11_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R10, false)
|
||||
asmgen.signExtendLongVariable("cx16.r10", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R12R13_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R12, false)
|
||||
asmgen.signExtendLongVariable("cx16.r12", valueDt.base)
|
||||
}
|
||||
RegisterOrPair.R14R15_32 -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.R14, false)
|
||||
asmgen.signExtendLongVariable("cx16.r14", valueDt.base)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -2812,7 +2848,8 @@ $endLabel""")
|
||||
BaseDataType.BYTE -> asmgen.out(" jsr floats.cast_FAC1_as_w_into_ay | sta $targetAsmVarName")
|
||||
BaseDataType.UWORD -> asmgen.out(" jsr floats.cast_FAC1_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1")
|
||||
BaseDataType.WORD -> asmgen.out(" jsr floats.cast_FAC1_as_w_into_ay | sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||
else -> throw AssemblyError("weird type")
|
||||
BaseDataType.LONG -> TODO("cast float to long")
|
||||
else -> throw AssemblyError("weird type $targetDt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2842,6 +2879,7 @@ $endLabel""")
|
||||
else
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out("""
|
||||
lda $sourceAsmVarName
|
||||
@@ -2878,6 +2916,7 @@ $endLabel""")
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
|
||||
asmgen.signExtendVariableLsb(targetAsmVarName, BaseDataType.BYTE)
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName")
|
||||
asmgen.signExtendVariableLsb(targetAsmVarName, BaseDataType.BYTE)
|
||||
@@ -2911,6 +2950,7 @@ $endLabel""")
|
||||
BaseDataType.WORD -> {
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out("""
|
||||
lda $sourceAsmVarName
|
||||
@@ -2950,6 +2990,7 @@ $endLabel""")
|
||||
BaseDataType.UWORD, BaseDataType.POINTER -> {
|
||||
asmgen.out(" lda $sourceAsmVarName | sta $targetAsmVarName | lda $sourceAsmVarName+1 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out("""
|
||||
lda $sourceAsmVarName
|
||||
@@ -2979,6 +3020,7 @@ $endLabel""")
|
||||
BaseDataType.BYTE -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName")
|
||||
BaseDataType.UWORD -> asmgen.out(" jsr floats.cast_as_uw_into_ya | sty $targetAsmVarName | sta $targetAsmVarName+1")
|
||||
BaseDataType.WORD -> asmgen.out(" jsr floats.cast_as_w_into_ay | sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||
BaseDataType.LONG -> TODO("cast float to long")
|
||||
else -> throw AssemblyError("weird type")
|
||||
}
|
||||
}
|
||||
@@ -3026,6 +3068,7 @@ $endLabel""")
|
||||
else
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out("""
|
||||
st${regs.toString().lowercase()} $targetAsmVarName
|
||||
@@ -3073,6 +3116,7 @@ $endLabel""")
|
||||
asmgen.signExtendAYlsb(sourceDt)
|
||||
asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName")
|
||||
asmgen.signExtendLongVariable(targetAsmVarName, sourceDt)
|
||||
@@ -3108,6 +3152,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("non-word regs")
|
||||
}
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
when(regs) {
|
||||
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
|
||||
@@ -3146,6 +3191,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("non-word regs")
|
||||
}
|
||||
}
|
||||
BaseDataType.POINTER -> TODO("cast to pointer")
|
||||
BaseDataType.LONG -> {
|
||||
when(regs) {
|
||||
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
|
||||
@@ -3479,7 +3525,7 @@ $endLabel""")
|
||||
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 -> TODO("assign long to pointer ${target.position}")
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
@@ -4004,7 +4050,7 @@ $endLabel""")
|
||||
sta cx16.$targetStartReg+3""")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
TargetStorageKind.POINTER -> TODO("assign long to pointer ${target.position}")
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
@@ -4499,7 +4545,7 @@ $endLabel""")
|
||||
stz $startreg+2
|
||||
stz $startreg+3""")
|
||||
}
|
||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
TargetStorageKind.POINTER -> TODO("assign long to pointer ${target.position}")
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
return
|
||||
@@ -4514,7 +4560,7 @@ $endLabel""")
|
||||
asmgen.out(" lda #$$hexbyte | sta ${target.asmVarname}+$offset")
|
||||
}
|
||||
}
|
||||
val hex = long.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = long.toLongHex()
|
||||
store(hex.substring(6,8), 0)
|
||||
store(hex.substring(4,6), 1)
|
||||
store(hex.substring(2,4), 2)
|
||||
@@ -4527,7 +4573,7 @@ $endLabel""")
|
||||
return
|
||||
}
|
||||
asmgen.loadScaledArrayIndexIntoRegister(target.array, CpuRegister.Y)
|
||||
val hex = long.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = long.toLongHex()
|
||||
asmgen.out("""
|
||||
lda #$${hex.substring(6,8)}
|
||||
sta ${target.asmVarname},y
|
||||
@@ -4542,7 +4588,7 @@ $endLabel""")
|
||||
TargetStorageKind.REGISTER -> {
|
||||
require(target.register in combinedLongRegisters)
|
||||
val regstart = target.register!!.startregname()
|
||||
val hex = long.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = long.toLongHex()
|
||||
asmgen.out("""
|
||||
lda #$${hex.substring(6,8)}
|
||||
sta cx16.$regstart
|
||||
@@ -4553,7 +4599,7 @@ $endLabel""")
|
||||
lda #$${hex.take(2)}
|
||||
sta cx16.$regstart+3""")
|
||||
}
|
||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
TargetStorageKind.POINTER -> pointergen.assignLong(target.pointer!!, long)
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
@@ -5309,7 +5355,7 @@ $endLabel""")
|
||||
TargetStorageKind.ARRAY -> TODO(" - long array ${target.position}")
|
||||
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
||||
TargetStorageKind.REGISTER -> TODO("32 bits register negate ${target.position}")
|
||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
TargetStorageKind.POINTER -> TODO("long negate via pointer ${target.position}")
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
import prog8.codegen.cpu6502.VariableAllocator
|
||||
import prog8.codegen.cpu6502.toLongHex
|
||||
|
||||
|
||||
internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
@@ -859,7 +860,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
inc $variable+3
|
||||
+""")
|
||||
} else {
|
||||
val hex = value.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = value.toLongHex()
|
||||
asmgen.out("""
|
||||
clc
|
||||
lda $variable
|
||||
@@ -921,7 +922,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
dec $variable+3
|
||||
+""")
|
||||
} else {
|
||||
val hex = value.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = value.toLongHex()
|
||||
asmgen.out("""
|
||||
sec
|
||||
lda $variable
|
||||
@@ -943,7 +944,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
"<<" -> if (value > 0) inplaceLongShiftLeft()
|
||||
">>" -> if (value > 0) inplaceLongShiftRight()
|
||||
"|" -> {
|
||||
val hex = value.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = value.toLongHex()
|
||||
asmgen.out("""
|
||||
lda $variable
|
||||
ora #$${hex.substring(6,8)}
|
||||
@@ -959,7 +960,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
sta $variable+3""")
|
||||
}
|
||||
"&" -> {
|
||||
val hex = value.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = value.toLongHex()
|
||||
asmgen.out("""
|
||||
lda $variable
|
||||
and #$${hex.substring(6,8)}
|
||||
@@ -975,7 +976,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
|
||||
sta $variable+3""")
|
||||
}
|
||||
"^" -> {
|
||||
val hex = value.toUInt().toString(16).padStart(8, '0')
|
||||
val hex = value.toLongHex()
|
||||
asmgen.out("""
|
||||
lda $variable
|
||||
eor #$${hex.substring(6,8)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
import prog8.codegen.cpu6502.VariableAllocator
|
||||
import prog8.codegen.cpu6502.toLongHex
|
||||
import kotlin.math.log2
|
||||
|
||||
|
||||
@@ -248,8 +249,10 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
asmgen.loadIndirectFloat(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, target)
|
||||
}
|
||||
else if(value.type.isLong)
|
||||
TODO("load long ${value.position}")
|
||||
else if(value.type.isLong) {
|
||||
asmgen.loadIndirectLongIntoR14R15(zpPtrVar, offset)
|
||||
asmgen.assignRegister(RegisterOrPair.R14R15_32, target)
|
||||
}
|
||||
else
|
||||
throw AssemblyError("weird dt ${value.type} in pointer deref assignment ${target.position}")
|
||||
}
|
||||
@@ -298,29 +301,34 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
"<<" -> {
|
||||
if(target.dt.isByte) inplaceByteShiftLeft(target, value)
|
||||
else if(target.dt.isWord) inplaceWordShiftLeft(target, value)
|
||||
else if(target.dt.isLong) TODO("inplace long << ${target.position}")
|
||||
else throw AssemblyError("weird dt ${target.position}")
|
||||
}
|
||||
">>" -> {
|
||||
if(target.dt.isByte) inplaceByteShiftRight(target, value)
|
||||
else if(target.dt.isWord) inplaceWordShiftRight(target, value)
|
||||
else if(target.dt.isLong) TODO("inplace long >> ${target.position}")
|
||||
else throw AssemblyError("weird dt ${target.position}")
|
||||
}
|
||||
"&", "and" -> {
|
||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
||||
if(target.dt.isByteOrBool) inplaceByteAnd(target, value)
|
||||
else if(target.dt.isWord) inplaceWordAnd(target, value)
|
||||
else if(target.dt.isLong) TODO("inplace long and ${target.position}")
|
||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||
}
|
||||
"|", "or" -> {
|
||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
||||
if(target.dt.isByteOrBool) inplaceByteOr(target, value)
|
||||
else if(target.dt.isWord) inplaceWordOr(target, value)
|
||||
else if(target.dt.isLong) TODO("inplace long or ${target.position}")
|
||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
// byte targets are handled as direct memory access, not a pointer operation anymore however boolean targets are still to be handled here
|
||||
if(target.dt.isByteOrBool) inplaceByteXor(target, value)
|
||||
else if(target.dt.isWord) inplaceWordXor(target, value)
|
||||
else if(target.dt.isLong) TODO("inplace long xor ${target.position}")
|
||||
else throw AssemblyError("weird dt ${target.dt} ${target.position}")
|
||||
}
|
||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||
@@ -454,6 +462,25 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
TODO("array ptr assign long var ${target.position}")
|
||||
}
|
||||
|
||||
fun assignLong(pointer: PtPointerDeref, long: Int) {
|
||||
val (ptrVar, offset) = deref(pointer)
|
||||
val hex = long.toLongHex()
|
||||
asmgen.out("""
|
||||
ldy #$offset
|
||||
lda #$${hex.substring(6,8)}
|
||||
sta ($ptrVar),y
|
||||
iny
|
||||
lda #$${hex.substring(4, 6)}
|
||||
sta ($ptrVar),y
|
||||
iny
|
||||
lda #$${hex.substring(2, 4)}
|
||||
sta ($ptrVar),y
|
||||
iny
|
||||
lda #$${hex.take(2)}
|
||||
sta ($ptrVar),y""")
|
||||
}
|
||||
|
||||
|
||||
internal fun operatorDereference(binExpr: PtBinaryExpression): Triple<String, UByte, DataType> {
|
||||
// the only case we support here is: a.b.c[i] . value
|
||||
// returns the ZP var to use as a pointer, and a Y register offset (which can be zero), and finally the datatype of the field
|
||||
@@ -948,18 +975,64 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
}
|
||||
|
||||
private fun inplaceLongAdd(target: PtrTarget, value: AsmAssignSource) {
|
||||
val (zpPtrVar, offset) = deref(target.pointer)
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALNUMBER -> TODO("inplace long add with ${value.number} ${target.position}")
|
||||
SourceStorageKind.VARIABLE -> TODO("inplace long add with ${value.asmVarname} ${target.position}")
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
val hex = value.number!!.number.toLongHex()
|
||||
asmgen.out("""
|
||||
ldy #$offset
|
||||
clc
|
||||
lda ($zpPtrVar),y
|
||||
adc #$${hex.substring(6, 8)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
adc #$${hex.substring(4, 6)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
adc #$${hex.substring(2, 4)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
adc #$${hex.take(2)}
|
||||
sta ($zpPtrVar),y""")
|
||||
}
|
||||
SourceStorageKind.VARIABLE -> {
|
||||
TODO("inplace long add with ${value.asmVarname} ${target.position}")
|
||||
}
|
||||
SourceStorageKind.EXPRESSION -> TODO("inplace long add with ${value.expression} ${target.position}")
|
||||
else -> TODO("inplace long add with ${value.kind} ${target.position}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceLongSub(target: PtrTarget, value: AsmAssignSource) {
|
||||
val (zpPtrVar, offset) = deref(target.pointer)
|
||||
when(value.kind) {
|
||||
SourceStorageKind.LITERALNUMBER -> TODO("inplace long sub with ${value.number} ${target.position}")
|
||||
SourceStorageKind.VARIABLE -> TODO("inplace long sub with ${value.asmVarname} ${target.position}")
|
||||
SourceStorageKind.LITERALNUMBER -> {
|
||||
val hex = value.number!!.number.toLongHex()
|
||||
asmgen.out("""
|
||||
ldy #$offset
|
||||
sec
|
||||
lda ($zpPtrVar),y
|
||||
sbc #$${hex.substring(6, 8)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sbc #$${hex.substring(4, 6)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sbc #$${hex.substring(2, 4)}
|
||||
sta ($zpPtrVar),y
|
||||
iny
|
||||
lda ($zpPtrVar),y
|
||||
sbc #$${hex.take(2)}
|
||||
sta ($zpPtrVar),y""")
|
||||
}
|
||||
SourceStorageKind.VARIABLE -> {
|
||||
TODO("inplace long sub with ${value.asmVarname} ${target.position}")
|
||||
}
|
||||
SourceStorageKind.EXPRESSION -> TODO("inplace long sub with ${value.expression} ${target.position}")
|
||||
else -> TODO("inplace long sub with ${value.kind} ${target.position}")
|
||||
}
|
||||
|
||||
@@ -406,6 +406,7 @@ asmsub width() clobbers(X,Y) -> ubyte @A {
|
||||
; -- returns the text screen width (number of columns)
|
||||
%asm {{
|
||||
jsr cbm.SCREEN
|
||||
inx
|
||||
txa
|
||||
rts
|
||||
}}
|
||||
@@ -415,11 +416,22 @@ asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
; -- returns the text screen height (number of rows)
|
||||
%asm {{
|
||||
jsr cbm.SCREEN
|
||||
iny
|
||||
tya
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
jsr cbm.SCREEN
|
||||
inx
|
||||
iny
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
- jsr cbm.GETIN
|
||||
|
||||
@@ -424,6 +424,14 @@ asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
jmp cbm.SCREEN
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
- jsr cbm.GETIN
|
||||
|
||||
@@ -818,8 +818,13 @@ io_error:
|
||||
|
||||
; For use directly after a load or load_raw call (don't mess with the ram bank yet):
|
||||
; Calculates the number of bytes loaded (files > 64Kb are truncated to 16 bits)
|
||||
sub load_size(ubyte startbank, uword startaddress, uword endaddress) -> uword {
|
||||
return $2000 * (cx16.getrambank() - startbank) + endaddress - startaddress
|
||||
sub load_size(ubyte startbank, uword startaddress, uword endaddress) -> long {
|
||||
&long banksize = &cx16.r12
|
||||
banksize = cx16.getrambank() - startbank
|
||||
banksize <<= 13 ; * 8192
|
||||
banksize += endaddress
|
||||
banksize -= startaddress
|
||||
return banksize
|
||||
}
|
||||
|
||||
asmsub vload(str name @R0, ubyte bank @A, uword startaddress @R1) clobbers(X, Y) -> bool @A {
|
||||
|
||||
@@ -615,6 +615,13 @@ asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
jmp cbm.SCREEN
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
- jsr cbm.GETIN
|
||||
|
||||
@@ -236,6 +236,17 @@ asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
jsr width
|
||||
tax
|
||||
jsr height
|
||||
tay
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
- jsr cbm.GETIN
|
||||
|
||||
@@ -21,6 +21,11 @@ sub height() -> ubyte {
|
||||
}}
|
||||
}
|
||||
|
||||
sub size() -> ubyte, ubyte {
|
||||
; -- returns the text screen width and height (number of columns and rows)
|
||||
return width(), height()
|
||||
}
|
||||
|
||||
sub clear_screen() {
|
||||
str @shared sequence = "\x1b[2J\x1B[H"
|
||||
%ir {{
|
||||
|
||||
@@ -825,6 +825,7 @@ txt {
|
||||
setcc (ubyte col, ubyte row, ubyte character, ubyte charcolor)
|
||||
setchr (ubyte col @X, ubyte row @Y, ubyte character @A) clobbers (A,Y)
|
||||
setclr (ubyte col @X, ubyte row @Y, ubyte color @A) clobbers (A,Y)
|
||||
size () clobbers (A) -> ubyte @X, ubyte @Y
|
||||
spc ()
|
||||
uppercase ()
|
||||
waitkey () -> ubyte @A
|
||||
|
||||
@@ -938,6 +938,7 @@ txt {
|
||||
setcc (ubyte col, ubyte row, ubyte character, ubyte charcolor)
|
||||
setchr (ubyte col @X, ubyte row @Y, ubyte character @A) clobbers (A,Y)
|
||||
setclr (ubyte col @X, ubyte row @Y, ubyte color @A) clobbers (A,Y)
|
||||
size () clobbers (A) -> ubyte @X, ubyte @Y
|
||||
spc ()
|
||||
uppercase ()
|
||||
waitkey () -> ubyte @A
|
||||
|
||||
@@ -240,7 +240,7 @@ diskio {
|
||||
list_filenames (str pattern_ptr, uword filenames_buffer, uword filenames_buf_size) -> ubyte
|
||||
load (str filenameptr, uword address_override) -> uword
|
||||
load_raw (str filenameptr, uword startaddress) -> uword
|
||||
load_size (ubyte startbank, uword startaddress, uword endaddress) -> uword
|
||||
load_size (ubyte startbank, uword startaddress, uword endaddress) -> long
|
||||
loadlib (str libnameptr, uword libaddress) -> uword
|
||||
mkdir (str name)
|
||||
read4hex () -> uword
|
||||
@@ -1422,6 +1422,7 @@ txt {
|
||||
setcc2 (ubyte col, ubyte row, ubyte character, ubyte colors)
|
||||
setchr (ubyte col @X, ubyte row @Y, ubyte character @A) clobbers (A)
|
||||
setclr (ubyte col @X, ubyte row @Y, ubyte color @A) clobbers (A)
|
||||
size () clobbers (A) -> ubyte @X, ubyte @Y
|
||||
spc ()
|
||||
t256c (bool enable)
|
||||
uppercase ()
|
||||
|
||||
@@ -540,6 +540,7 @@ txt {
|
||||
setcc (ubyte col, ubyte row, ubyte character, ubyte charcolor_ignored)
|
||||
setchr (ubyte col @X, ubyte row @Y, ubyte character @A) clobbers (A,Y)
|
||||
setclr (ubyte col, ubyte row, ubyte color)
|
||||
size () clobbers (A) -> ubyte @X, ubyte @Y
|
||||
spc ()
|
||||
uppercase ()
|
||||
waitkey () -> ubyte @A
|
||||
|
||||
@@ -559,6 +559,7 @@ txt {
|
||||
rvs_off ()
|
||||
rvs_on ()
|
||||
setchr (ubyte col, ubyte row, ubyte char)
|
||||
size () -> ubyte, ubyte
|
||||
spc ()
|
||||
uppercase ()
|
||||
width () -> ubyte
|
||||
|
||||
@@ -16,11 +16,12 @@ Then you can choose a few ways to get a compiler:
|
||||
#. download a recent "fat-jar" (called something like "prog8c-all.jar") from `the releases on Github <https://github.com/irmen/prog8/releases>`_
|
||||
#. run the compiler with "java -jar prog8c.jar" to see how you can use it (use the correct name and version of the jar file you've downloaded).
|
||||
|
||||
**Or, install via a Package Manager:**
|
||||
**Or, install via a Package Manager (takes care of dependencies for you):**
|
||||
|
||||
Arch Linux:
|
||||
Currently, it's available on `AUR <https://wiki.archlinux.org/title/Arch_User_Repository>`_ for Arch Linux and compatible systems.
|
||||
The package is called `"prog8" <https://aur.archlinux.org/packages/prog8>`_.
|
||||
Currently, it's available on `AUR <https://wiki.archlinux.org/title/Arch_User_Repository>`_ for Arch Linux and derivative systems.
|
||||
The package is called `"prog8" <https://aur.archlinux.org/packages/prog8>`_. There should be no need to install aything else as
|
||||
it can automatically pull in the required dependencies.
|
||||
|
||||
This package, alongside the compiler itself, also globally installs syntax highlighting for ``vim`` and ``nano``.
|
||||
In order to run compiler, you can type ``prog8c``. The usage of those commands is exactly the same as with the ``java -jar`` method.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- fix github issues. Probably those include the folloing already:
|
||||
- implement the TODO in assignPointerDerefExpression()
|
||||
- implement inplaceLongAdd/Sub in PointerAssignmentGen to make this compile::
|
||||
|
||||
@@ -10,24 +11,22 @@ TODO
|
||||
^^Node np = 20000
|
||||
np.x += cx16.r0
|
||||
|
||||
- redo the benchmark-c tests with final 12.0 release version.
|
||||
|
||||
STRUCTS and TYPED POINTERS
|
||||
--------------------------
|
||||
|
||||
- implement the remaining TODO's in PointerAssignmentsGen.
|
||||
- optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
||||
- optimize the float copying in assignIndexedPointer() (also word and long?)
|
||||
- optimize augmented assignments to indexed pointer targets like sprptr[2]^^.y++ (these are now not performend in-place but as a regular assignment)
|
||||
- implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
|
||||
- support @nosplit pointer arrays?
|
||||
- support pointer to pointer?
|
||||
- support for typed function pointers? (&routine could be typed by default as well then)
|
||||
- really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
|
||||
- (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
|
||||
|
||||
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- struct/ptr: implement the remaining TODO's in PointerAssignmentsGen.
|
||||
- struct/ptr: optimize deref in PointerAssignmentsGen: optimize 'forceTemporary' to only use a temporary when the offset is >0
|
||||
- struct/ptr: optimize the float copying in assignIndexedPointer() (also word and long?)
|
||||
- struct/ptr: optimize augmented assignments to indexed pointer targets like sprptr[2]^^.y++ (these are now not performend in-place but as a regular assignment)
|
||||
- struct/ptr: implement even more struct instance assignments (via memcopy) in CodeDesugarer (see the TODO) (add to documentation as well, paragraph 'Structs')
|
||||
- struct/ptr: support @nosplit pointer arrays?
|
||||
- struct/ptr: support pointer to pointer?
|
||||
- struct/ptr: support for typed function pointers? (&routine could be typed by default as well then)
|
||||
- struct/ptr: really fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
|
||||
- struct/ptr: (later, nasty parser problem:) support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
|
||||
- make $8000000 a valid long integer (-2147483648) this is more involved than you think. To make this work: long \|= $80000000
|
||||
- make memory mapped variables support more constant expressions such as: &uword MyHigh = &mylong1+2
|
||||
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1, should both always be 1-based (is this the reason some source lines end up missing in the IR file?)
|
||||
|
||||
@@ -412,20 +412,28 @@ asmsub waitkey() -> ubyte @A {
|
||||
|
||||
asmsub width() clobbers(X,Y) -> ubyte @A {
|
||||
; -- returns the text screen width (number of columns)
|
||||
; TODO
|
||||
%asm {{
|
||||
lda #0
|
||||
lda #DEFAULT_WIDTH
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
; -- returns the text screen height (number of rows)
|
||||
; TODO
|
||||
%asm {{
|
||||
lda #0
|
||||
lda #DEFAULT_HEIGHT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
ldx #DEFAULT_WIDTH
|
||||
ldy #DEFAULT_HEIGHT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ asmsub plot (ubyte col @ Y, ubyte row @ X) {
|
||||
asmsub width() clobbers(X,Y) -> ubyte @A {
|
||||
; -- returns the text screen width (number of columns)
|
||||
%asm {{
|
||||
lda DEFAULT_WIDTH
|
||||
lda #DEFAULT_WIDTH
|
||||
rts
|
||||
}}
|
||||
}
|
||||
@@ -425,11 +425,21 @@ asmsub width() clobbers(X,Y) -> ubyte @A {
|
||||
asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
; -- returns the text screen height (number of rows)
|
||||
%asm {{
|
||||
lda DEFAULT_HEIGHT
|
||||
lda #DEFAULT_HEIGHT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub size() clobbers(A) -> ubyte @X, ubyte @Y {
|
||||
; -- returns the text screen width in X and height in Y (number of columns and rows)
|
||||
%asm {{
|
||||
ldx #DEFAULT_HEIGHT
|
||||
ldy #DEFAULT_HEIGHT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
; TODO: jmp to cbm.CHRIN?
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
|
||||
@@ -12,26 +12,26 @@ main{
|
||||
}
|
||||
|
||||
^^Country[] countries = [
|
||||
^^Country:["Indonesia", 285.72, 1904],
|
||||
^^Country:["Congo", 112.83, 2344],
|
||||
^^Country:["Vietnam", 101.60, 331],
|
||||
^^Country:["United States", 347.28, 9372],
|
||||
^^Country:["Iran", 92.42, 1648],
|
||||
^^Country:["Turkey", 87.69, 783],
|
||||
^^Country:["Brazil", 212.81, 8515],
|
||||
^^Country:["Bangladesh", 175.69, 147],
|
||||
^^Country:["Germany", 84.08, 357],
|
||||
^^Country:["Japan", 123.10, 377],
|
||||
^^Country:["India", 1463.87, 3287],
|
||||
^^Country:["China", 1416.10, 9596],
|
||||
^^Country:["Philippines", 116.79, 300],
|
||||
^^Country:["Russia", 143.99, 17098],
|
||||
^^Country:["Pakistan", 255.22, 881],
|
||||
^^Country:["Nigeria", 237.53, 923],
|
||||
^^Country:["Ethiopia", 135.47, 1104],
|
||||
^^Country:["Mexico", 131.95, 1964],
|
||||
^^Country:["Thailand", 71.62, 513],
|
||||
^^Country:["Egypt", 118.37, 1002],
|
||||
["Indonesia", 285.72, 1904],
|
||||
["Congo", 112.83, 2344],
|
||||
["Vietnam", 101.60, 331],
|
||||
["United States", 347.28, 9372],
|
||||
["Iran", 92.42, 1648],
|
||||
["Turkey", 87.69, 783],
|
||||
["Brazil", 212.81, 8515],
|
||||
["Bangladesh", 175.69, 147],
|
||||
["Germany", 84.08, 357],
|
||||
["Japan", 123.10, 377],
|
||||
["India", 1463.87, 3287],
|
||||
["China", 1416.10, 9596],
|
||||
["Philippines", 116.79, 300],
|
||||
["Russia", 143.99, 17098],
|
||||
["Pakistan", 255.22, 881],
|
||||
["Nigeria", 237.53, 923],
|
||||
["Ethiopia", 135.47, 1104],
|
||||
["Mexico", 131.95, 1964],
|
||||
["Thailand", 71.62, 513],
|
||||
["Egypt", 118.37, 1002],
|
||||
]
|
||||
|
||||
sub start() {
|
||||
|
||||
@@ -1,41 +1,34 @@
|
||||
%import textio
|
||||
%import math
|
||||
%import diskio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
struct element {
|
||||
ubyte type
|
||||
long x
|
||||
long y
|
||||
}
|
||||
|
||||
sub start() {
|
||||
long @shared lv, lv2
|
||||
; cx16.r5L = 10
|
||||
; txt.print_l(cx16.r5L as long * $2000)
|
||||
; txt.spc()
|
||||
; txt.print_l(($2000 as long) * cx16.r5L) ; TODO fix long result? or wait till the long consts have landed?
|
||||
; txt.nl()
|
||||
|
||||
lv = $11111111
|
||||
lv2 = $55555555
|
||||
|
||||
lv = lv | lv2 ^ 999999
|
||||
|
||||
txt.print_ulhex(lv, true) ; $555b177b
|
||||
cx16.rambank(15)
|
||||
txt.print_l(diskio.load_size(10, $1000, $6000))
|
||||
txt.nl()
|
||||
cx16.rambank(25)
|
||||
txt.print_l(diskio.load_size(10, $1000, $f000))
|
||||
|
||||
|
||||
; long @shared lv1 = $12345678
|
||||
; ^^element myElement = $6000
|
||||
; myElement.y = $44444444
|
||||
; long @shared lv
|
||||
;
|
||||
; txt.print_ubhex(msb(lv1), true)
|
||||
; txt.spc()
|
||||
; txt.print_ubhex(lsb(lv1), true)
|
||||
; txt.spc()
|
||||
; txt.print_ubhex(lv1 as ubyte, true)
|
||||
; txt.nl()
|
||||
; txt.print_uwhex(msw(lv1), true)
|
||||
; txt.spc()
|
||||
; txt.print_uwhex(lsw(lv1), true)
|
||||
; txt.nl()
|
||||
|
||||
; ; TODO support long+1 / -1 expressions....
|
||||
; cx16.r4 = msw(lv1-1)
|
||||
; cx16.r5 = lsw(lv1-1)
|
||||
; txt.print_uwhex(cx16.r4, true)
|
||||
; txt.print_uwhex(cx16.r5, true)
|
||||
; txt.nl()
|
||||
; myElement.y -= lv
|
||||
;
|
||||
; txt.print_ubhex((lv1-1) as ubyte, true)
|
||||
; txt.nl()
|
||||
; txt.print_ulhex(myElement.y, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ org.gradle.parallel=true
|
||||
org.gradle.daemon=true
|
||||
org.gradle.configuration-cache=false
|
||||
kotlin.code.style=official
|
||||
version=12.0-BETA5
|
||||
version=12.0-SNAPSHOT
|
||||
@@ -583,7 +583,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
|
||||
val value = memory.getSL(pointer.toInt())
|
||||
registers.setSL(i.reg1!!, value)
|
||||
statusbitsNZ(value.toInt(), i.type!!)
|
||||
statusbitsNZ(value, i.type!!)
|
||||
}
|
||||
IRDataType.FLOAT -> {
|
||||
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!)
|
||||
@@ -2526,7 +2526,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
newStatusCarry = (orig and 0x80000000u) != 0u
|
||||
val rotated: UInt = (if (useCarry) {
|
||||
val carry = if (statusCarry) 1u else 0u
|
||||
(orig.toUInt().rotateLeft(1) or carry)
|
||||
(orig.rotateLeft(1) or carry)
|
||||
} else
|
||||
orig.rotateLeft(1))
|
||||
registers.setSL(i.reg1!!, rotated.toInt())
|
||||
@@ -2648,7 +2648,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
val lsb = registers.getUB(i.reg3!!)
|
||||
val value = ((msb.toInt() shl 8) or lsb.toInt())
|
||||
registers.setUW(i.reg1!!, value.toUShort())
|
||||
statusbitsNZ(value.toInt(), i.type!!)
|
||||
statusbitsNZ(value, i.type!!)
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val msw = registers.getUW(i.reg2!!)
|
||||
@@ -2959,15 +2959,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
}
|
||||
|
||||
private fun multiplyAnyLongSigned(reg1: Int, reg2: Int) {
|
||||
TODO("multiplyAnyLongSigned - multiplication and division of long numbers not yet supported, use floats or words")
|
||||
val result = registers.getSL(reg1) * registers.getSL(reg2)
|
||||
registers.setSL(reg1, result)
|
||||
}
|
||||
|
||||
private fun multiplyConstLongSigned(reg1: Int, value: Int) {
|
||||
TODO("multiplyConstLongSigned - multiplication and division of long numbers not yet supported, use floats or words")
|
||||
val result = registers.getSL(reg1) * value
|
||||
registers.setSL(reg1, result)
|
||||
}
|
||||
|
||||
private fun multiplyAnyLongSignedInplace(reg1: Int, address: Int) {
|
||||
TODO("multiplyAnyLongSignedInplace - multiplication and division of long numbers not yet supported, use floats or words")
|
||||
val result = memory.getSL(address) * registers.getSL(reg1)
|
||||
memory.setSL(address, result)
|
||||
}
|
||||
|
||||
private fun divModLongSigned(operator: String, reg1: Int, reg2: Int) {
|
||||
|
||||
Reference in New Issue
Block a user