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 + jmp push_fac1_as_result
.pend .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 func_any_f .proc
inx inx
lda P8ESTACK_LO,x ; array size lda P8ESTACK_LO,x ; array size

View File

@ -702,6 +702,10 @@ func_read_flags .proc
rts rts
.pend .pend
func_sqrt16_into_A .proc
jsr func_sqrt16
jmp func_any_b_into_A._popA
.pend
func_sqrt16 .proc func_sqrt16 .proc
; TODO is this one faster? http://6502org.wikidot.com/software-math-sqrt ; 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 .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 func_sin8 .proc
ldy P8ESTACK_LO+1,x ldy P8ESTACK_LO+1,x
lda _sinecos8,y lda _sinecos8,y
@ -838,6 +914,29 @@ peek_address .proc
rts rts
.pend .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 func_any_b .proc
inx inx
lda P8ESTACK_LO,x ; array size lda P8ESTACK_LO,x ; array size
@ -1103,6 +1202,72 @@ pop_array_and_lengthmin1Y .proc
rts rts
.pend .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 func_min_ub .proc
jsr pop_array_and_lengthmin1Y jsr pop_array_and_lengthmin1Y
lda #255 lda #255
@ -2165,5 +2330,6 @@ func_strcmp .proc
lda P8ESTACK_LO+1,x lda P8ESTACK_LO+1,x
jsr strcmp_mem jsr strcmp_mem
sta P8ESTACK_LO+1,x sta P8ESTACK_LO+1,x
; make sure A contains the result value as well
rts rts
.pend .pend

View File

@ -263,7 +263,6 @@ private class AsmSubroutineParameter(name: String,
type: DataType, type: DataType,
val registerOrPair: RegisterOrPair?, val registerOrPair: RegisterOrPair?,
val statusflag: Statusflag?, val statusflag: Statusflag?,
// TODO implement: val stack: Boolean,
position: Position) : SubroutineParameter(name, type, position) position: Position) : SubroutineParameter(name, type, position)
private class AsmSubroutineReturn(val type: DataType, 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, class Block(override val name: String,
val address: Int?, val address: Int?,

View File

@ -550,22 +550,19 @@ 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 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) { if(dontUseStack) {
when (register) { when (register) {
CpuRegister.A -> { CpuRegister.A -> {
out(" sta _prog8_regsaveA") out(" sta _prog8_regsaveA")
if (scope != null)
scope.asmGenInfo.usedRegsaveA = true scope.asmGenInfo.usedRegsaveA = true
} }
CpuRegister.X -> { CpuRegister.X -> {
out(" stx _prog8_regsaveX") out(" stx _prog8_regsaveX")
if (scope != null)
scope.asmGenInfo.usedRegsaveX = true scope.asmGenInfo.usedRegsaveX = true
} }
CpuRegister.Y -> { CpuRegister.Y -> {
out(" sty _prog8_regsaveY") out(" sty _prog8_regsaveY")
if (scope != null)
scope.asmGenInfo.usedRegsaveY = true scope.asmGenInfo.usedRegsaveY = true
} }
} }
@ -577,7 +574,6 @@ internal class AsmGen(private val program: Program,
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx") if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
else { else {
out(" stx _prog8_regsaveX") out(" stx _prog8_regsaveX")
if (scope != null)
scope.asmGenInfo.usedRegsaveX = true scope.asmGenInfo.usedRegsaveX = true
} }
} }
@ -585,7 +581,6 @@ internal class AsmGen(private val program: Program,
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy") if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
else { else {
out(" sty _prog8_regsaveY") 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) { when (functionName) {
"msb" -> funcMsb(fcall, resultToStack) "msb" -> funcMsb(fcall, resultToStack)
"lsb" -> funcLsb(fcall, resultToStack) "lsb" -> funcLsb(fcall, resultToStack)
// TODO THE OTHERS "mkword" -> funcMkword(fcall, resultToStack)
// "mkword" -> funcMkword(fcall, func) // TODO resultToStack
"abs" -> funcAbs(fcall, func, resultToStack) "abs" -> funcAbs(fcall, func, resultToStack)
"swap" -> funcSwap(fcall) "swap" -> funcSwap(fcall)
// "strlen" -> funcStrlen(fcall) // TODO resultToStack "min", "max" -> funcMinMax(fcall, functionName, resultToStack)
// "min", "max", "sum" -> funcMinMaxSum(fcall, functionName) // TODO resultToStack "sum" -> funcSum(fcall, resultToStack)
// "any", "all" -> funcAnyAll(fcall, functionName) // TODO 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) "sgn" -> funcSgn(fcall, func, resultToStack)
"sin", "cos", "tan", "atan", "sin", "cos", "tan", "atan",
"ln", "log2", "sqrt", "rad", "ln", "log2", "sqrt", "rad",
"deg", "round", "floor", "ceil", "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) "rol" -> funcRol(fcall)
"rol2" -> funcRol2(fcall) "rol2" -> funcRol2(fcall)
"ror" -> funcRor(fcall) "ror" -> funcRor(fcall)
@ -63,19 +66,52 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
// restore all registers and cpu status flag // restore all registers and cpu status flag
asmgen.out(" pla | tay | pla | tax | pla | plp") 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") "clear_carry" -> asmgen.out(" clc")
"set_carry" -> asmgen.out(" sec") "set_carry" -> asmgen.out(" sec")
"clear_irqd" -> asmgen.out(" cli") "clear_irqd" -> asmgen.out(" cli")
"set_irqd" -> asmgen.out(" sei") "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) translateArguments(fcall.args, func)
if(resultToStack) {
asmgen.out(" jsr prog8_lib.func_$functionName") asmgen.out(" jsr prog8_lib.func_$functionName")
} else { }
TODO("builtin function $fcall") "exit" -> asmgen.out(" jmp prog8_lib.func_exit")
// TODO call function that puts result in registers, not on stack 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")
} }
} }
@ -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) translateArguments(fcall.args, func)
if(resultToStack) {
asmgen.out(" jsr floats.func_$functionName") asmgen.out(" jsr floats.func_$functionName")
} else {
TODO("float func result via registers $functionName")
}
} }
private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) { private fun funcSgn(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean) {
@ -380,20 +420,30 @@ 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]) outputPushAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().inferType(program) val dt = fcall.args.single().inferType(program)
if(resultToStack) {
when (dt.typeOrElse(DataType.STRUCT)) { when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_b") 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_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${functionName}_w")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f") DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt") 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]) outputPushAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().inferType(program) val dt = fcall.args.single().inferType(program)
if(resultToStack) {
when (dt.typeOrElse(DataType.STRUCT)) { when (dt.typeOrElse(DataType.STRUCT)) {
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${functionName}_ub") 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_B -> asmgen.out(" jsr prog8_lib.func_${functionName}_b")
@ -402,24 +452,56 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f") DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${functionName}_f")
else -> throw AssemblyError("weird type $dt") 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 name = asmgen.asmVariableName(fcall.args[0] as IdentifierReference)
val type = fcall.args[0].inferType(program) val type = fcall.args[0].inferType(program)
when { when {
type.istype(DataType.STR) -> asmgen.out(""" type.istype(DataType.STR) -> {
lda #<$name asmgen.out(" lda #<$name | ldy #>$name | jsr prog8_lib.strlen")
ldy #>$name if(resultToStack)
jsr prog8_lib.strlen asmgen.out(" sta P8ESTACK_LO,x | dex")
sta P8ESTACK_LO,x }
dex""") type.istype(DataType.UWORD) -> {
type.istype(DataType.UWORD) -> asmgen.out(""" asmgen.out(" lda $name | ldy $name+1 | jsr prog8_lib.strlen")
lda $name if(resultToStack)
ldy $name+1 asmgen.out(" sta P8ESTACK_LO,x | dex")
jsr prog8_lib.strlen }
sta P8ESTACK_LO,x
dex""")
else -> throw AssemblyError("strlen requires str or uword arg") 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) { private fun funcRnd(functionName: String, resultToStack: Boolean) {
// trick: push the args in reverse order (msb first, lsb second) this saves some instructions 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[1])
asmgen.translateExpression(fcall.args[0]) asmgen.translateExpression(fcall.args[0])
asmgen.out(" inx | lda P8ESTACK_LO,x | sta P8ESTACK_HI+1,x") 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) { private fun funcMsb(fcall: IFunctionCall, resultToStack: Boolean) {
@ -814,9 +922,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
if(resultToStack) if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex") asmgen.out(" sta P8ESTACK_LO,x | dex")
} else { } else {
TODO("msb from non-identifier expression $arg") asmgen.translateExpression(arg) // TODO this evalutes onto stack, use registers instead
// asmgen.translateExpression(arg) if(resultToStack)
// asmgen.out(" lda P8ESTACK_HI+1,x | sta P8ESTACK_LO+1,x") 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) if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex") asmgen.out(" sta P8ESTACK_LO,x | dex")
} else { } else {
TODO("lsb from non-identifier expression $arg") // TODO this evalutes onto stack, use registers instead
// asmgen.translateExpression(arg) asmgen.translateExpression(arg)
// just ignore any high-byte 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) { 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) { when(operator) {
"==" -> asmgen.out(" and #1 | eor #1 | sta P8ESTACK_LO+1,x") "==" -> asmgen.out(" and #1 | eor #1 | sta P8ESTACK_LO+1,x")
"!=" -> asmgen.out(" and #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 sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam() val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
if(saveX) 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) val subName = asmgen.asmSymbolName(stmt.target)
if(stmt.args.isNotEmpty()) { if(stmt.args.isNotEmpty()) {

View File

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

View File

@ -130,6 +130,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
is Subroutine -> { is Subroutine -> {
val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null } val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null }
asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall) asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall)
if(sub.returntypes.single()==DataType.STR) {
TODO("assignment of string => copy string ${assign.position}")
} else {
when ((sub.asmReturnvaluesRegisters.single { it.registerOrPair != null }).registerOrPair) { when ((sub.asmReturnvaluesRegisters.single { it.registerOrPair != null }).registerOrPair) {
RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A) RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A)
RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X) RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X)
@ -139,6 +142,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY) RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY)
else -> throw AssemblyError("should be just one register byte result value") else -> throw AssemblyError("should be just one register byte result value")
} }
}
if (preserveStatusRegisterAfterCall) if (preserveStatusRegisterAfterCall)
asmgen.out(" plp\t; restore status flags from call") 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)) { when(returntype.typeOrElse(DataType.STRUCT)) {
in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A 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 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}") DataType.FLOAT -> TODO("assign float result from ${sub.name}")
else -> throw AssemblyError("weird result type") 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) { private fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
require(target.datatype in NumericDatatypes) require(target.datatype in NumericDatatypes) {
"zzz"
}
if(target.datatype==DataType.FLOAT) { if(target.datatype==DataType.FLOAT) {
if (regs == RegisterOrPair.AY) { 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 return
} }
else throw AssemblyError("float reaturn value should be via AY return pointer") 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 -> { 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 -> { TargetStorageKind.REGISTER -> {
when(regs) { when(regs) {
@ -1190,7 +1210,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.storeByteIntoPointer(addressExpr, null) asmgen.storeByteIntoPointer(addressExpr, null)
} }
else -> { else -> {
asmgen.saveRegister(register, false, memoryAddress.definingSubroutine()) asmgen.saveRegister(register, false, memoryAddress.definingSubroutine()!!)
asmgen.translateExpression(addressExpr) asmgen.translateExpression(addressExpr)
asmgen.restoreRegister(CpuRegister.A, false) asmgen.restoreRegister(CpuRegister.A, false)
asmgen.out(""" asmgen.out("""

View File

@ -136,13 +136,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
DataType.FLOAT -> { DataType.FLOAT -> {
when { when {
valueLv != null -> inplaceModification_float_litval_to_variable(target.asmVarname, operator, valueLv.toDouble(), 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) ident != null -> inplaceModification_float_variable_to_variable(target.asmVarname, operator, ident, target.scope!!)
value is TypecastExpression -> { value is TypecastExpression -> {
if (tryRemoveRedundantCast(value, target, operator)) return 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}") 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") 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, // this should be the last resort for code generation for this,
// because the value is evaluated onto the eval stack (=slow). // because the value is evaluated onto the eval stack (=slow).
if(asmgen.options.slowCodegenWarnings) if(asmgen.options.slowCodegenWarnings)
@ -1350,7 +1350,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.restoreRegister(CpuRegister.X, false) 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 val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
if(valueDt != DataType.FLOAT) if(valueDt != DataType.FLOAT)
throw AssemblyError("float variable expected") throw AssemblyError("float variable expected")
@ -1419,7 +1419,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
asmgen.restoreRegister(CpuRegister.X, false) 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) val constValueName = asmgen.getFloatAsmConst(value)
asmgen.saveRegister(CpuRegister.X, false, scope) asmgen.saveRegister(CpuRegister.X, false, scope)
when (operator) { when (operator) {

View File

@ -617,8 +617,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
if (amount >= 16) { if (amount >= 16) {
return NumericLiteralValue(targetDt, 0, expr.position) return NumericLiteralValue(targetDt, 0, expr.position)
} else if (amount >= 8) { } else if (amount >= 8) {
// TODO is this correct??? val lsb = FunctionCall(IdentifierReference(listOf("lsb"), expr.position), mutableListOf(expr.left), expr.position)
val lsb = TypecastExpression(expr.left, DataType.UBYTE, true, expr.position)
if (amount == 8) { if (amount == 8) {
return FunctionCall(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(lsb, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position) 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(w) and memcopy able to work with >256 bytes
- make memset and memcopy use the ROM routines on the CX16 - 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) - 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 '_' - 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) - 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 - 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. ; 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 { main {
const uword SCREEN1 = $E000 const uword SCREEN1 = $E000
const uword SCREEN2 = $E400 const uword SCREEN2 = $E400

View File

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