diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index b3b8b341f..7559edb09 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -483,7 +483,7 @@ class AsmGen6502Internal ( when(reg) { RegisterOrPair.A, RegisterOrPair.X, - RegisterOrPair.Y -> assignmentAsmGen.assignRegisterByte(target, reg.asCpuRegister()) + RegisterOrPair.Y -> assignmentAsmGen.assignRegisterByte(target, reg.asCpuRegister(), false) RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY, diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 7cd611e0d..70abf2110 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -91,8 +91,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, val var3name = asmgen.asmVariableName(fcall.args[3] as PtIdentifier) val divisionTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UBYTE, fcall.definingISub(), fcall.args[2].position, var2name) val remainderTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, asmgen, DataType.UBYTE, fcall.definingISub(), fcall.args[3].position, var3name) - assignAsmGen.assignRegisterByte(remainderTarget, CpuRegister.A) - assignAsmGen.assignRegisterByte(divisionTarget, CpuRegister.Y) + assignAsmGen.assignRegisterByte(remainderTarget, CpuRegister.A, false) + assignAsmGen.assignRegisterByte(divisionTarget, CpuRegister.Y, false) } private fun funcDivmodW(fcall: PtBuiltinFunctionCall) { @@ -304,7 +304,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, asmgen.out(" jsr prog8_lib.func_sqrt16_stack") else { asmgen.out(" jsr prog8_lib.func_sqrt16_into_A") - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A) + assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false) } } @@ -647,7 +647,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.FLOAT -> asmgen.out(" jsr floats.func_sign_f_into_A") else -> throw AssemblyError("weird type $dt") } - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A) + assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true) } } @@ -668,7 +668,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${fcall.name}_f_into_A | ldy #0") else -> throw AssemblyError("weird type $dt") } - assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A) + assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes) } } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 404dcbdf5..c9cc9f0d0 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -75,7 +75,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" lda $arrayVarName | sta P8ZP_SCRATCH_W1 | lda $arrayVarName+1 | sta P8ZP_SCRATCH_W1+1") asmgen.out(" lda (P8ZP_SCRATCH_W1),y") } - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, elementDt in SignedDatatypes) return } @@ -86,7 +86,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, when (elementDt) { in ByteDatatypes -> { asmgen.out(" lda $arrayVarName+$indexValue") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, elementDt in SignedDatatypes) } in WordDatatypes -> { asmgen.out(" lda $arrayVarName+$indexValue | ldy $arrayVarName+$indexValue+1") @@ -104,7 +104,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, in ByteDatatypes -> { asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y) asmgen.out(" lda $arrayVarName,y") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, elementDt in SignedDatatypes) } in WordDatatypes -> { asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y) @@ -131,7 +131,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, fun assignViaExprEval(expression: PtExpression) { assignExpressionToVariable(expression, "P8ZP_SCRATCH_W2", DataType.UWORD) asmgen.loadAFromZpPointerVar("P8ZP_SCRATCH_W2") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) } val value = assign.source.memory!! @@ -147,7 +147,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, require(!asmgen.options.useNewExprCode) val addrExpr = value.address as PtBinaryExpression if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) { - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) } else { assignViaExprEval(value.address) } @@ -207,9 +207,9 @@ internal class AssignmentAsmGen(private val program: PtProgram, else -> { // do NOT restore X register before assigning the result values first when (returnValue.first.registerOrPair) { - RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A) - RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X) - RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y) + RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A, returnValue.second in SignedDatatypes) + RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X, returnValue.second in SignedDatatypes) + RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y, returnValue.second in SignedDatatypes) RegisterOrPair.AX -> assignVirtualRegister(assign.target, RegisterOrPair.AX) RegisterOrPair.AY -> assignVirtualRegister(assign.target, RegisterOrPair.AY) RegisterOrPair.XY -> assignVirtualRegister(assign.target, RegisterOrPair.XY) @@ -247,7 +247,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, if(assign.target.register==null) { // still need to assign the result to the target variable/etc. when(returnDt) { - in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A + in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A, returnDt in SignedDatatypes) // function's byte result is in A in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY DataType.STR -> { when (assign.target.datatype) { @@ -296,7 +296,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } is PtContainmentCheck -> { containmentCheckIntoA(value) - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) } is PtBinaryExpression -> { require(!asmgen.options.useNewExprCode) @@ -337,7 +337,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, when(target.datatype) { in ByteDatatypes -> { asmgen.out(" lda cx16.${register.toString().lowercase()}L") - assignRegisterByte(target, CpuRegister.A) + assignRegisterByte(target, CpuRegister.A, false) } in WordDatatypes -> assignRegisterpairWord(target, register) else -> throw AssemblyError("expected byte or word") @@ -398,7 +398,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, "^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1") else -> throw AssemblyError("invalid operator") } - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) } } @@ -464,7 +464,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, + lda #0 +""") } - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes && expr.left.isSimple() && expr.right.isSimple()) { @@ -495,7 +495,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, + lda #1 +""") } - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } return false @@ -513,7 +513,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" clc | adc $symname") else asmgen.out(" sec | sbc $symname") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, dt in SignedDatatypes) return true } is PtNumber -> { @@ -522,7 +522,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" clc | adc #${right.number.toHex()}") else asmgen.out(" sec | sbc #${right.number.toHex()}") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, dt in SignedDatatypes) return true } else -> return false @@ -650,7 +650,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } } - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, signed) return true } else if(dt in WordDatatypes && shifts in 0..7) { val signed = dt == DataType.WORD @@ -698,7 +698,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, "^", "xor" -> asmgen.out(" eor $operand") else -> throw AssemblyError("invalid operator") } - assignRegisterByte(target, CpuRegister.A) + assignRegisterByte(target, CpuRegister.A, false) } private fun assignLogicalWithSimpleRightOperandWord(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) { @@ -740,7 +740,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, beq ++ + lda #1 +""") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } in WordDatatypes -> { @@ -753,13 +753,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, beq ++ + lda #1 +""") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } DataType.FLOAT -> { assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true) asmgen.out(" jsr floats.SIGN | and #1 | eor #1") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } else->{ @@ -773,7 +773,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, assignExpressionToRegister(expr.left, RegisterOrPair.A, dt==DataType.BYTE) asmgen.out(" beq + | lda #1") asmgen.out("+") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } in WordDatatypes -> { @@ -781,13 +781,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, asmgen.out(" sty P8ZP_SCRATCH_B1 | ora P8ZP_SCRATCH_B1") asmgen.out(" beq + | lda #1") asmgen.out("+") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, false) return true } DataType.FLOAT -> { assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true) asmgen.out(" jsr floats.SIGN") - assignRegisterByte(assign.target, CpuRegister.A) + assignRegisterByte(assign.target, CpuRegister.A, true) return true } else->{ @@ -868,7 +868,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } else -> throw AssemblyError("can't use Z or N flags as return 'values'") } - assignRegisterByte(target, CpuRegister.A) + assignRegisterByte(target, CpuRegister.A, false) } private fun assignTypeCastedValue(target: AsmAssignTarget, targetDt: DataType, value: PtExpression, origTypeCastExpression: PtTypeCast) { @@ -2057,7 +2057,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } - internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister) { + internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister, signed: Boolean) { // we make an exception in the type check for assigning something to a register pair AX, AY or XY // these will be correctly typecasted from a byte to a word value here if(target.register !in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) @@ -2099,9 +2099,40 @@ internal class AssignmentAsmGen(private val program: PtProgram, RegisterOrPair.A -> {} RegisterOrPair.X -> { asmgen.out(" tax") } RegisterOrPair.Y -> { asmgen.out(" tay") } - RegisterOrPair.AY -> { asmgen.out(" ldy #0") } - RegisterOrPair.AX -> { asmgen.out(" ldx #0") } - RegisterOrPair.XY -> { asmgen.out(" tax | ldy #0") } + RegisterOrPair.AY -> { + if(signed) + asmgen.out(""" + ldy #0 + cmp #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" ldy #0") + } + RegisterOrPair.AX -> { + if(signed) + asmgen.out(""" + ldx #0 + cmp #${'$'}80 + bcc + + dex ++""") + else + asmgen.out(" ldx #0") + } + RegisterOrPair.XY -> { + if(signed) + asmgen.out(""" + tax + ldy #0 + cpx #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" tax | ldy #0") + } RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") in Cx16VirtualRegisters -> { // only assign a single byte to the virtual register's Lsb @@ -2113,9 +2144,41 @@ internal class AssignmentAsmGen(private val program: PtProgram, RegisterOrPair.A -> { asmgen.out(" txa") } RegisterOrPair.X -> { } RegisterOrPair.Y -> { asmgen.out(" txy") } - RegisterOrPair.AY -> { asmgen.out(" txa | ldy #0") } - RegisterOrPair.AX -> { asmgen.out(" txa | ldx #0") } - RegisterOrPair.XY -> { asmgen.out(" ldy #0") } + RegisterOrPair.AY -> { + if(signed) + asmgen.out(""" + txa + ldy #0 + cmp #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" txa | ldy #0") + } + RegisterOrPair.AX -> { + if(signed) + asmgen.out(""" + txa + ldx #0 + cmp #${'$'}80 + bcc + + dex ++""") + else + asmgen.out(" txa | ldx #0") + } + RegisterOrPair.XY -> { + if(signed) + asmgen.out(""" + ldy #0 + cpx #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" ldy #0") + } RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") in Cx16VirtualRegisters -> { // only assign a single byte to the virtual register's Lsb @@ -2127,9 +2190,43 @@ internal class AssignmentAsmGen(private val program: PtProgram, RegisterOrPair.A -> { asmgen.out(" tya") } RegisterOrPair.X -> { asmgen.out(" tyx") } RegisterOrPair.Y -> { } - RegisterOrPair.AY -> { asmgen.out(" tya | ldy #0") } - RegisterOrPair.AX -> { asmgen.out(" tya | ldx #0") } - RegisterOrPair.XY -> { asmgen.out(" tya | tax | ldy #0") } + RegisterOrPair.AY -> { + if(signed) + asmgen.out(""" + tya + ldy #0 + cmp #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" tya | ldy #0") + } + RegisterOrPair.AX -> { + if(signed) + asmgen.out(""" + tya + ldx #0 + cmp #${'$'}80 + bcc + + dex ++""") + else + asmgen.out(" tya | ldx #0") + } + RegisterOrPair.XY -> { + if(signed) + asmgen.out(""" + tya + tax + ldy #0 + cpx #${'$'}80 + bcc + + dey ++""") + else + asmgen.out(" tya | tax | ldy #0") + } RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected type cast to float") in Cx16VirtualRegisters -> { // only assign a single byte to the virtual register's Lsb @@ -2666,7 +2763,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } TargetStorageKind.ARRAY -> { asmgen.out(" lda ${address.toHex()}") - assignRegisterByte(target, CpuRegister.A) + assignRegisterByte(target, CpuRegister.A, false) } TargetStorageKind.REGISTER -> when(target.register!!) { RegisterOrPair.A -> asmgen.out(" lda ${address.toHex()}") @@ -2706,7 +2803,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, } TargetStorageKind.ARRAY -> { asmgen.loadByteFromPointerIntoA(identifier) - assignRegisterByte(target, CpuRegister.A) + assignRegisterByte(target, CpuRegister.A, false) } TargetStorageKind.REGISTER -> { asmgen.loadByteFromPointerIntoA(identifier) diff --git a/examples/test.p8 b/examples/test.p8 index f5eea808c..0cfb983ed 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,9 +1,28 @@ %import textio +%option no_sysinit +%zeropage basicsafe main { sub start() { - sys.set_leds_brightness(255, 255) - sys.wait(120) - sys.reset_system() + byte v1s = 22 + byte v2s = -99 + word ww + + txt.print_w(minsb()) ; TODO WRONG RESULT! + txt.spc() + ww = minsb() + txt.print_w(ww) + txt.spc() + txt.print_b(minsb()) + txt.spc() + v2s = minsb() + txt.print_w(v2s) + + sub minsb() -> byte { + cx16.r0++ + return v2s + } } + } +