mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
made versions of various builtin funcs returning value in registers
This commit is contained in:
parent
3e28ed4fe4
commit
3efa8da8e0
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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?,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
|
@ -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()) {
|
||||
|
@ -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 -> {
|
||||
|
@ -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("""
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user