made versions of various builtin funcs returning value in registers

This commit is contained in:
Irmen de Jong 2020-10-28 23:13:53 +01:00
parent 3e28ed4fe4
commit 3efa8da8e0
15 changed files with 423 additions and 129 deletions

View File

@ -573,6 +573,18 @@ func_ceil .proc
+ jmp push_fac1_as_result
.pend
func_any_f_into_A .proc
jsr func_any_f
_popA inx
lda P8ESTACK_LO,x
rts
.pend
func_all_f_into_A .proc
jsr func_all_f
jmp func_any_f_into_A._popA
.pend
func_any_f .proc
inx
lda P8ESTACK_LO,x ; array size

View File

@ -702,6 +702,10 @@ func_read_flags .proc
rts
.pend
func_sqrt16_into_A .proc
jsr func_sqrt16
jmp func_any_b_into_A._popA
.pend
func_sqrt16 .proc
; TODO is this one faster? http://6502org.wikidot.com/software-math-sqrt
@ -754,6 +758,78 @@ _stab .byte $01,$02,$04,$08,$10,$20,$40,$80
.pend
func_sin8_into_A .proc
inx
ldy P8ESTACK_LO,x
lda func_sin8._sinecos8,y
rts
.pend
func_sin8u_into_A .proc
inx
ldy P8ESTACK_LO,x
lda func_sin8u._sinecos8u,y
rts
.pend
func_sin16_into_AY .proc
inx
ldy P8ESTACK_LO,x
lda func_sin16._sinecos8lo,y
pha
lda func_sin16._sinecos8hi,y
tay
pla
rts
.pend
func_sin16u_into_AY .proc
inx
ldy P8ESTACK_LO,x
lda func_sin16u._sinecos8ulo,y
pha
lda func_sin16u._sinecos8uhi,y
tay
pla
rts
.pend
func_cos8_into_A .proc
inx
ldy P8ESTACK_LO,x
lda func_sin8._sinecos8+64,y
rts
.pend
func_cos8u_into_A .proc
inx
ldy P8ESTACK_LO,x
lda func_sin8u._sinecos8u+64,y
rts
.pend
func_cos16_into_AY .proc
inx
ldy P8ESTACK_LO,x
lda func_sin16._sinecos8lo+64,y
pha
lda func_sin16._sinecos8hi+64,y
tay
pla
rts
.pend
func_cos16u_into_AY .proc
inx
ldy P8ESTACK_LO,x
lda func_sin16u._sinecos8ulo+64,y
pha
lda func_sin16u._sinecos8uhi+64,y
tay
pla
rts
.pend
func_sin8 .proc
ldy P8ESTACK_LO+1,x
lda _sinecos8,y
@ -838,6 +914,29 @@ peek_address .proc
rts
.pend
func_any_b_into_A .proc
jsr func_any_b
_popA inx
lda P8ESTACK_LO,x
rts
.pend
func_all_b_into_A .proc
jsr func_all_b
jmp func_any_b_into_A._popA
.pend
func_any_w_into_A .proc
jsr func_any_w
jmp func_any_b_into_A._popA
.pend
func_all_w_into_A .proc
jsr func_all_w
jmp func_any_b_into_A._popA
.pend
func_any_b .proc
inx
lda P8ESTACK_LO,x ; array size
@ -1103,6 +1202,72 @@ pop_array_and_lengthmin1Y .proc
rts
.pend
func_min_ub_into_A .proc
jsr func_min_ub
_popA inx
lda P8ESTACK_LO,x
rts
.pend
func_min_b_into_A .proc
jsr func_min_b
jmp func_min_ub_into_A._popA
.pend
func_max_ub_into_A .proc
jsr func_max_ub
jmp func_min_ub_into_A._popA
.pend
func_max_b_into_A .proc
jsr func_max_b
jmp func_min_ub_into_A._popA
.pend
func_sum_ub_into_AY .proc
jsr func_sum_ub
_popAY inx
lda P8ESTACK_LO,x
ldy P8ESTACK_HI,x
rts
.pend
func_sum_b_into_AY .proc
jsr func_sum_b
jmp func_sum_ub_into_AY._popAY
.pend
func_min_uw_into_AY .proc
jsr func_min_uw
jmp func_sum_ub_into_AY._popAY
.pend
func_min_w_into_AY .proc
jsr func_min_w
jmp func_sum_ub_into_AY._popAY
.pend
func_max_uw_into_AY .proc
jsr func_max_uw
jmp func_sum_ub_into_AY._popAY
.pend
func_max_w_into_AY .proc
jsr func_max_w
jmp func_sum_ub_into_AY._popAY
.pend
func_sum_uw_into_AY .proc
jsr func_sum_uw
jmp func_sum_ub_into_AY._popAY
.pend
func_sum_w_into_AY .proc
jsr func_sum_w
jmp func_sum_ub_into_AY._popAY
.pend
func_min_ub .proc
jsr pop_array_and_lengthmin1Y
lda #255
@ -2165,5 +2330,6 @@ func_strcmp .proc
lda P8ESTACK_LO+1,x
jsr strcmp_mem
sta P8ESTACK_LO+1,x
; make sure A contains the result value as well
rts
.pend

View File

@ -263,7 +263,6 @@ private class AsmSubroutineParameter(name: String,
type: DataType,
val registerOrPair: RegisterOrPair?,
val statusflag: Statusflag?,
// TODO implement: val stack: Boolean,
position: Position) : SubroutineParameter(name, type, position)
private class AsmSubroutineReturn(val type: DataType,

View File

@ -44,7 +44,7 @@ class BuiltinFunctionStatementPlaceholder(val name: String, override val positio
}
}
data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?, val stack: Boolean)
data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?, val stack: Boolean) // TODO get rid of stack?
class Block(override val name: String,
val address: Int?,

View File

@ -550,23 +550,20 @@ internal class AsmGen(private val program: Program,
private fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
internal fun saveRegister(register: CpuRegister, dontUseStack: Boolean, scope: Subroutine?) {
internal fun saveRegister(register: CpuRegister, dontUseStack: Boolean, scope: Subroutine) {
if(dontUseStack) {
when (register) {
CpuRegister.A -> {
out(" sta _prog8_regsaveA")
if (scope != null)
scope.asmGenInfo.usedRegsaveA = true
scope.asmGenInfo.usedRegsaveA = true
}
CpuRegister.X -> {
out(" stx _prog8_regsaveX")
if (scope != null)
scope.asmGenInfo.usedRegsaveX = true
scope.asmGenInfo.usedRegsaveX = true
}
CpuRegister.Y -> {
out(" sty _prog8_regsaveY")
if (scope != null)
scope.asmGenInfo.usedRegsaveY = true
scope.asmGenInfo.usedRegsaveY = true
}
}
@ -577,16 +574,14 @@ internal class AsmGen(private val program: Program,
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
else {
out(" stx _prog8_regsaveX")
if (scope != null)
scope.asmGenInfo.usedRegsaveX = true
scope.asmGenInfo.usedRegsaveX = true
}
}
CpuRegister.Y -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
else {
out(" sty _prog8_regsaveY")
if (scope != null)
scope.asmGenInfo.usedRegsaveY = true
scope.asmGenInfo.usedRegsaveY = true
}
}
}

View File

@ -36,18 +36,21 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
when (functionName) {
"msb" -> funcMsb(fcall, resultToStack)
"lsb" -> funcLsb(fcall, resultToStack)
// TODO THE OTHERS
// "mkword" -> funcMkword(fcall, func) // TODO resultToStack
"mkword" -> funcMkword(fcall, resultToStack)
"abs" -> funcAbs(fcall, func, resultToStack)
"swap" -> funcSwap(fcall)
// "strlen" -> funcStrlen(fcall) // TODO resultToStack
// "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) // TODO resultToStack
// "any", "all" -> funcAnyAll(fcall, functionName) // TODO resultToStack
"min", "max" -> funcMinMax(fcall, functionName, resultToStack)
"sum" -> funcSum(fcall, resultToStack)
"any", "all" -> funcAnyAll(fcall, functionName, resultToStack)
"sin8", "sin8u", "sin16", "sin16u",
"cos8", "cos8u", "cos16", "cos16u" -> funcSinCosInt(fcall, func, functionName, resultToStack)
"sgn" -> funcSgn(fcall, func, resultToStack)
"sin", "cos", "tan", "atan",
"ln", "log2", "sqrt", "rad",
"deg", "round", "floor", "ceil",
// "rdnf" -> funcVariousFloatFuncs(fcall, func, functionName) // TODO resultToStack
"rdnf" -> funcVariousFloatFuncs(fcall, func, functionName, resultToStack)
"rnd", "rndw" -> funcRnd(functionName, resultToStack)
"sqrt16" -> funcSqrt16(fcall, func, resultToStack)
"rol" -> funcRol(fcall)
"rol2" -> funcRol2(fcall)
"ror" -> funcRor(fcall)
@ -63,22 +66,55 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
// restore all registers and cpu status flag
asmgen.out(" pla | tay | pla | tax | pla | plp")
}
"read_flags" -> {
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_read_flags")
else
asmgen.out(" php | pla")
}
"clear_carry" -> asmgen.out(" clc")
"set_carry" -> asmgen.out(" sec")
"clear_irqd" -> asmgen.out(" cli")
"set_irqd" -> asmgen.out(" sei")
else -> {
"strlen" -> funcStrlen(fcall, resultToStack)
"strcmp" -> funcStrcmp(fcall, func, resultToStack)
"substr", "leftstr", "rightstr",
"memcopy", "memset", "memsetw" -> {
translateArguments(fcall.args, func)
if(resultToStack) {
asmgen.out(" jsr prog8_lib.func_$functionName")
} else {
TODO("builtin function $fcall")
// TODO call function that puts result in registers, not on stack
}
asmgen.out(" jsr prog8_lib.func_$functionName")
}
"exit" -> asmgen.out(" jmp prog8_lib.func_exit")
else -> TODO("missing asmgen for builtin func $functionName")
}
}
private fun funcStrcmp(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) {
translateArguments(fcall.args, func)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_strcmp")
else
asmgen.out(" jsr prog8_lib.func_strcmp | inx") // result is also in register A
}
private fun funcSqrt16(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) {
translateArguments(fcall.args, func)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_sqrt16")
else
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
}
private fun funcSinCosInt(fcall: IFunctionCall, func: FSignature, functionName: String, resultToStack: Boolean) {
translateArguments(fcall.args, func)
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_$functionName")
else
when(functionName) {
"sin8", "sin8u", "cos8", "cos8u" -> asmgen.out(" jsr prog8_lib.func_${functionName}_into_A")
"sin16", "sin16u", "cos16", "cos16u" -> asmgen.out(" jsr prog8_lib.func_${functionName}_into_AY")
}
}
private fun funcReverse(fcall: IFunctionCall) {
val variable = fcall.args.single()
if (variable is IdentifierReference) {
@ -351,9 +387,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, functionName: String) {
private fun funcVariousFloatFuncs(fcall: IFunctionCall, func: FSignature, functionName: String, resultToStack: Boolean) {
translateArguments(fcall.args, func)
asmgen.out(" jsr floats.func_$functionName")
if(resultToStack) {
asmgen.out(" jsr floats.func_$functionName")
} else {
TODO("float func result via registers $functionName")
}
}
private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) {
@ -380,46 +420,88 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcAnyAll(fcall: IFunctionCall, functionName: String) {
private fun funcAnyAll(fcall: IFunctionCall, functionName: String, resultToStack: Boolean) {
outputPushAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().inferType(program)
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_b")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt")
if(resultToStack) {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_b")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt")
}
} else {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_b_into_A")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w_into_A")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f_into_A")
else -> throw AssemblyError("weird type $dt")
}
}
}
private fun funcMinMaxSum(fcall: IFunctionCall, functionName: String) {
private fun funcMinMax(fcall: IFunctionCall, functionName: String, resultToStack: Boolean) {
outputPushAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().inferType(program)
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_ub")
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${functionName}_b")
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${functionName}_uw")
DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt")
if(resultToStack) {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_ub")
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${functionName}_b")
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${functionName}_uw")
DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt")
}
} else {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_ub_into_A")
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${functionName}_b_into_A")
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${functionName}_uw_into_AY")
DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w_into_AY")
DataType.ARRAY_F -> TODO("min/max of floats result in float via registers")
else -> throw AssemblyError("weird type $dt")
}
}
}
private fun funcStrlen(fcall: IFunctionCall) {
private fun funcSum(fcall: IFunctionCall, resultToStack: Boolean) {
outputPushAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().inferType(program)
if(resultToStack) {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_sum_ub")
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_sum_b")
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_sum_uw")
DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_sum_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_sum_f")
else -> throw AssemblyError("weird type $dt")
}
} else {
when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_sum_ub_into_AY")
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_sum_b_into_AY")
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_sum_uw_into_AY")
DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_sum_w_into_AY")
DataType.ARRAY_F -> TODO("sum of floats result in float via registers")
else -> throw AssemblyError("weird type $dt")
}
}
}
private fun funcStrlen(fcall: IFunctionCall, resultToStack: Boolean) {
val name = asmgen.asmVariableName(fcall.args[0] as IdentifierReference)
val type = fcall.args[0].inferType(program)
when {
type.istype(DataType.STR) -> asmgen.out("""
lda #<$name
ldy #>$name
jsr prog8_lib.strlen
sta P8ESTACK_LO,x
dex""")
type.istype(DataType.UWORD) -> asmgen.out("""
lda $name
ldy $name+1
jsr prog8_lib.strlen
sta P8ESTACK_LO,x
dex""")
type.istype(DataType.STR) -> {
asmgen.out(" lda #<$name | ldy #>$name | jsr prog8_lib.strlen")
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
}
type.istype(DataType.UWORD) -> {
asmgen.out(" lda $name | ldy $name+1 | jsr prog8_lib.strlen")
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
}
else -> throw AssemblyError("strlen requires str or uword arg")
}
}
@ -795,11 +877,37 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
}
private fun funcMkword(fcall: IFunctionCall, func: FSignature) {
// trick: push the args in reverse order (msb first, lsb second) this saves some instructions
asmgen.translateExpression(fcall.args[1])
asmgen.translateExpression(fcall.args[0])
asmgen.out(" inx | lda P8ESTACK_LO,x | sta P8ESTACK_HI+1,x")
private fun funcRnd(functionName: String, resultToStack: Boolean) {
when(functionName) {
"rnd" -> {
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_rnd")
else
asmgen.out(" jsr math.randbyte")
}
"rndw" -> {
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_rndw")
else
asmgen.out(" jsr math.randword")
}
else -> throw AssemblyError("wrong func")
}
}
private fun funcMkword(fcall: IFunctionCall, resultToStack: Boolean) {
if(resultToStack) {
// trick: push the args in reverse order (lsb first, msb second) this saves some instructions
asmgen.translateExpression(fcall.args[1])
asmgen.translateExpression(fcall.args[0])
asmgen.out(" inx | lda P8ESTACK_LO,x | sta P8ESTACK_HI+1,x")
} else {
// TODO some args without stack usage...
// trick: push the args in reverse order (lsb first, msb second) this saves some instructions
asmgen.translateExpression(fcall.args[1])
asmgen.translateExpression(fcall.args[0])
asmgen.out(" inx | ldy P8ESTACK_LO,x | inx | lda P8ESTACK_LO,x")
}
}
private fun funcMsb(fcall: IFunctionCall, resultToStack: Boolean) {
@ -814,9 +922,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
TODO("msb from non-identifier expression $arg")
// asmgen.translateExpression(arg)
// asmgen.out(" lda P8ESTACK_HI+1,x | sta P8ESTACK_LO+1,x")
asmgen.translateExpression(arg) // TODO this evalutes onto stack, use registers instead
if(resultToStack)
asmgen.out(" lda P8ESTACK_HI+1,x | sta P8ESTACK_LO+1,x")
else
asmgen.out(" inx | lda P8ESTACK_HI,x")
}
}
@ -832,9 +942,13 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
TODO("lsb from non-identifier expression $arg")
// asmgen.translateExpression(arg)
// just ignore any high-byte
// TODO this evalutes onto stack, use registers instead
asmgen.translateExpression(arg)
if(resultToStack) {
// simply ignore the high-byte of what's on the stack now
} else {
asmgen.out(" inx | lda P8ESTACK_LO,x")
}
}
}

View File

@ -1687,7 +1687,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
}
private fun translateCompareStrings(operator: String) {
asmgen.out(" jsr prog8_lib.func_strcmp | lda P8ESTACK_LO+1,x") // result of compare in A
asmgen.out(" jsr prog8_lib.func_strcmp") // result of compare is on stack but also in A
when(operator) {
"==" -> asmgen.out(" and #1 | eor #1 | sta P8ESTACK_LO+1,x")
"!=" -> asmgen.out(" and #1 | sta P8ESTACK_LO+1,x")

View File

@ -37,7 +37,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
if(saveX)
asmgen.saveRegister(CpuRegister.X, preserveStatusRegisterAfterCall, (stmt as Node).definingSubroutine())
asmgen.saveRegister(CpuRegister.X, preserveStatusRegisterAfterCall, (stmt as Node).definingSubroutine()!!)
val subName = asmgen.asmSymbolName(stmt.target)
if(stmt.args.isNotEmpty()) {

View File

@ -97,7 +97,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
else
{
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, elementDt, CpuRegister.A)
asmgen.saveRegister(CpuRegister.X, false, scope)
asmgen.saveRegister(CpuRegister.X, false, scope!!)
asmgen.out(" tax")
when(elementDt) {
in ByteDatatypes -> {

View File

@ -130,14 +130,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
is Subroutine -> {
val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null }
asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall)
when ((sub.asmReturnvaluesRegisters.single { it.registerOrPair != null }).registerOrPair) {
RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A)
RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X)
RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y)
RegisterOrPair.AX -> assignRegisterpairWord(assign.target, RegisterOrPair.AX)
RegisterOrPair.AY -> assignRegisterpairWord(assign.target, RegisterOrPair.AY)
RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY)
else -> throw AssemblyError("should be just one register byte result value")
if(sub.returntypes.single()==DataType.STR) {
TODO("assignment of string => copy string ${assign.position}")
} else {
when ((sub.asmReturnvaluesRegisters.single { it.registerOrPair != null }).registerOrPair) {
RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A)
RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X)
RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y)
RegisterOrPair.AX -> assignRegisterpairWord(assign.target, RegisterOrPair.AX)
RegisterOrPair.AY -> assignRegisterpairWord(assign.target, RegisterOrPair.AY)
RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY)
else -> throw AssemblyError("should be just one register byte result value")
}
}
if (preserveStatusRegisterAfterCall)
asmgen.out(" plp\t; restore status flags from call")
@ -151,6 +155,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
when(returntype.typeOrElse(DataType.STRUCT)) {
in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A
in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY
DataType.STR -> TODO("assign string => copy string")
DataType.FLOAT -> TODO("assign float result from ${sub.name}")
else -> throw AssemblyError("weird result type")
}
@ -775,10 +780,12 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
private fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
require(target.datatype in NumericDatatypes)
require(target.datatype in NumericDatatypes) {
"zzz"
}
if(target.datatype==DataType.FLOAT) {
if (regs == RegisterOrPair.AY) {
asmgen.out(" brk ; TODO FLOAT RETURN VALUE") // TODO
asmgen.out(" brk ; TODO FLOAT RETURN VALUE") // TODO float value via registers
return
}
else throw AssemblyError("float reaturn value should be via AY return pointer")
@ -793,7 +800,20 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
}
TargetStorageKind.ARRAY -> {
TODO("store register pair $regs into word-array ${target.array}")
// TODO can be a bit more optimized if the array indexer is a number
when(regs) {
RegisterOrPair.AX -> asmgen.out(" pha | txa | pha")
RegisterOrPair.AY -> asmgen.out(" pha | tya | pha")
RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha")
else -> throw AssemblyError("expected reg pair")
}
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true)
asmgen.out("""
pla
sta ${target.asmVarname},y
dey
pla
sta ${target.asmVarname},y""")
}
TargetStorageKind.REGISTER -> {
when(regs) {
@ -1190,7 +1210,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.storeByteIntoPointer(addressExpr, null)
}
else -> {
asmgen.saveRegister(register, false, memoryAddress.definingSubroutine())
asmgen.saveRegister(register, false, memoryAddress.definingSubroutine()!!)
asmgen.translateExpression(addressExpr)
asmgen.restoreRegister(CpuRegister.A, false)
asmgen.out("""

View File

@ -136,13 +136,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
}
DataType.FLOAT -> {
when {
valueLv != null -> inplaceModification_float_litval_to_variable(target.asmVarname, operator, valueLv.toDouble(), target.scope)
ident != null -> inplaceModification_float_variable_to_variable(target.asmVarname, operator, ident, target.scope)
valueLv != null -> inplaceModification_float_litval_to_variable(target.asmVarname, operator, valueLv.toDouble(), target.scope!!)
ident != null -> inplaceModification_float_variable_to_variable(target.asmVarname, operator, ident, target.scope!!)
value is TypecastExpression -> {
if (tryRemoveRedundantCast(value, target, operator)) return
inplaceModification_float_value_to_variable(target.asmVarname, operator, value, target.scope)
inplaceModification_float_value_to_variable(target.asmVarname, operator, value, target.scope!!)
}
else -> inplaceModification_float_value_to_variable(target.asmVarname, operator, value, target.scope)
else -> inplaceModification_float_value_to_variable(target.asmVarname, operator, value, target.scope!!)
}
}
else -> throw AssemblyError("weird type to do in-place modification on ${target.datatype}")
@ -1295,7 +1295,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.out(" inx")
}
private fun inplaceModification_float_value_to_variable(name: String, operator: String, value: Expression, scope: Subroutine?) {
private fun inplaceModification_float_value_to_variable(name: String, operator: String, value: Expression, scope: Subroutine) {
// this should be the last resort for code generation for this,
// because the value is evaluated onto the eval stack (=slow).
if(asmgen.options.slowCodegenWarnings)
@ -1350,7 +1350,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.restoreRegister(CpuRegister.X, false)
}
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference, scope: Subroutine?) {
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference, scope: Subroutine) {
val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
if(valueDt != DataType.FLOAT)
throw AssemblyError("float variable expected")
@ -1419,7 +1419,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.restoreRegister(CpuRegister.X, false)
}
private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double, scope: Subroutine?) {
private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double, scope: Subroutine) {
val constValueName = asmgen.getFloatAsmConst(value)
asmgen.saveRegister(CpuRegister.X, false, scope)
when (operator) {

View File

@ -617,8 +617,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
if (amount >= 16) {
return NumericLiteralValue(targetDt, 0, expr.position)
} else if (amount >= 8) {
// TODO is this correct???
val lsb = TypecastExpression(expr.left, DataType.UBYTE, true, expr.position)
val lsb = FunctionCall(IdentifierReference(listOf("lsb"), expr.position), mutableListOf(expr.left), expr.position)
if (amount == 8) {
return FunctionCall(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(lsb, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position)
}

View File

@ -6,7 +6,7 @@ TODO
- make memset(w) and memcopy able to work with >256 bytes
- make memset and memcopy use the ROM routines on the CX16
- calling convention for builtin functions no longer via stack but via statically allocated vars inside the subroutine proc (just as normal subroutines)
- get rid of @stack in asmsub altogether (because all subroutines are no longer using this calling convention anymore)
- get rid of @stack in asmsub (syntax, ast) altogether (because all subroutines are no longer using this calling convention anymore)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
- see if we can group some errors together for instance the (now single) errors about unidentified symbols

View File

@ -9,6 +9,8 @@
; Converted to prog8 by Irmen de Jong.
; TODO why is the output of this larger with the register-eval stuff than before with the stack eval stuff?
main {
const uword SCREEN1 = $E000
const uword SCREEN2 = $E400

View File

@ -11,50 +11,37 @@
main {
sub start() {
byte bb
word ww
bb = 0
bb = sgn(bb)
txt.print_b(bb)
txt.chrout('\n')
bb = 127
bb = sgn(bb)
txt.print_b(bb)
txt.chrout('\n')
bb = -1
bb = sgn(bb)
txt.print_b(bb)
txt.chrout('\n')
bb = -127
bb = sgn(bb)
txt.print_b(bb)
txt.chrout('\n')
bb = -128
bb = sgn(bb)
txt.print_b(bb)
txt.chrout('\n')
uword ss
ss = %1000000110101010
ss <<= 8
txt.print_uwbin(ss, 1)
txt.chrout('\n')
ww = 0
ww = sgn(ww)
txt.print_w(ww)
ss = %1000000110101111
ss <<= 9
txt.print_uwbin(ss, 1)
txt.chrout('\n')
ww = 32767
ww = sgn(ww)
txt.print_w(ww)
ss = %1000000110101111
ss <<= 14
txt.print_uwbin(ss, 1)
txt.chrout('\n')
ww = -1
ww = sgn(ww)
txt.print_w(ww)
ss = %1000000110101111
ss <<= 15
txt.print_uwbin(ss, 1)
txt.chrout('\n')
ww = -32767
ww = sgn(ww)
txt.print_w(ww)
ss = %1000000110101111
ss <<= 16
txt.print_uwbin(ss, 1)
txt.chrout('\n')
ww = -32768
ww = sgn(ww)
txt.print_w(ww)
ss = %1000000110101010
ss <<= 17
txt.print_uwbin(ss, 1)
txt.chrout('\n')
main22.testX()
@ -87,7 +74,7 @@ main22 {
txt.chrout('\n')
void getstr()
ssss = getstr()
; TODO string assign ssss = getstr()
txt.print_uwhex(ssss, true)
txt.chrout('\n')