mirror of
https://github.com/irmen/prog8.git
synced 2024-09-08 10:55:08 +00:00
fix X register clobbering in asmfunc call, fixed graphics.plot()
This commit is contained in:
parent
2f951bd54d
commit
81f7419f70
@ -1,11 +1,11 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
// id "org.jetbrains.kotlin.jvm" version "1.4.0"
|
// id "org.jetbrains.kotlin.jvm" version "1.4.10"
|
||||||
id 'application'
|
id 'application'
|
||||||
id 'org.jetbrains.dokka' version "0.9.18"
|
id 'org.jetbrains.dokka' version "0.9.18"
|
||||||
id 'com.github.johnrengelman.shadow' version '5.2.0'
|
id 'com.github.johnrengelman.shadow' version '5.2.0'
|
||||||
|
@ -181,9 +181,7 @@ graphics {
|
|||||||
; @(addr) |= ormask[lsb(px) & 7]
|
; @(addr) |= ormask[lsb(px) & 7]
|
||||||
; }
|
; }
|
||||||
|
|
||||||
; TODO fix the use of X (or XY) as parameter so we can actually use this plot() routine
|
asmsub plot(uword plotx @XY, ubyte ploty @A) clobbers (A, X, Y) {
|
||||||
; calling it with a byte results in a compiler crash, calling it with word results in clobbering X register I think
|
|
||||||
asmsub plotXXX(uword plotx @XY, ubyte ploty @A) {
|
|
||||||
%asm {{
|
%asm {{
|
||||||
stx internal_plotx
|
stx internal_plotx
|
||||||
sty internal_plotx+1
|
sty internal_plotx+1
|
||||||
@ -191,12 +189,14 @@ graphics {
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; for efficiency of internal algorithms here is the internal plot routine
|
||||||
|
; that takes the plotx coordinate in a separate variable instead of the XY register pair:
|
||||||
|
|
||||||
uword internal_plotx ; 0..319 ; separate 'parameter' for internal_plot()
|
uword internal_plotx ; 0..319 ; separate 'parameter' for internal_plot()
|
||||||
|
|
||||||
asmsub internal_plot(ubyte ploty @A) { ; internal_plotx is 16 bits 0 to 319... doesn't fit in a register
|
asmsub internal_plot(ubyte ploty @A) clobbers (A, X, Y) { ; internal_plotx is 16 bits 0 to 319... doesn't fit in a register
|
||||||
%asm {{
|
%asm {{
|
||||||
tay
|
tay
|
||||||
stx P8ZP_SCRATCH_REG_X
|
|
||||||
lda internal_plotx+1
|
lda internal_plotx+1
|
||||||
sta P8ZP_SCRATCH_W2+1
|
sta P8ZP_SCRATCH_W2+1
|
||||||
lsr a ; 0
|
lsr a ; 0
|
||||||
@ -220,8 +220,6 @@ graphics {
|
|||||||
lda (P8ZP_SCRATCH_W2),y
|
lda (P8ZP_SCRATCH_W2),y
|
||||||
ora _ormask,x
|
ora _ormask,x
|
||||||
sta (P8ZP_SCRATCH_W2),y
|
sta (P8ZP_SCRATCH_W2),y
|
||||||
|
|
||||||
ldx P8ZP_SCRATCH_REG_X
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
||||||
|
@ -552,31 +552,60 @@ internal class AsmGen(private val program: Program,
|
|||||||
|
|
||||||
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
|
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
|
||||||
|
|
||||||
internal fun saveRegister(register: CpuRegister) {
|
internal fun saveRegister(register: CpuRegister, forFuncCall: Boolean = false, dontClobberA: Boolean = false) {
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" pha")
|
CpuRegister.A -> out(" pha")
|
||||||
CpuRegister.X -> {
|
CpuRegister.X -> {
|
||||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
// TODO get rid of REG_X altogheter! replace with sta _save | txa | pha | lda _save
|
||||||
out(" phx")
|
when {
|
||||||
|
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" phx")
|
||||||
|
forFuncCall -> {
|
||||||
|
if(dontClobberA)
|
||||||
|
out(" sta P8ZP_SCRATCH_REG | txa | pha | lda P8ZP_SCRATCH_REG")
|
||||||
else
|
else
|
||||||
out(" stx P8ZP_SCRATCH_REG_X")
|
out(" txa | pha")
|
||||||
|
}
|
||||||
|
else -> out(" stx P8ZP_SCRATCH_REG_X")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CpuRegister.Y -> {
|
||||||
|
when {
|
||||||
|
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" phy")
|
||||||
|
dontClobberA -> out(" sta P8ZP_SCRATCH_REG | tya | pha | lda P8ZP_SCRATCH_REG")
|
||||||
|
else -> out(" tya | pha")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> out(" tya | pha")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun restoreRegister(register: CpuRegister) {
|
internal fun restoreRegister(register: CpuRegister, forFuncCall: Boolean = false, dontClobberA: Boolean=false) {
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> out(" pla")
|
CpuRegister.A -> {
|
||||||
|
require(!dontClobberA)
|
||||||
|
out(" pla")
|
||||||
|
}
|
||||||
CpuRegister.X -> {
|
CpuRegister.X -> {
|
||||||
if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
when {
|
||||||
out(" plx")
|
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" plx")
|
||||||
|
forFuncCall -> {
|
||||||
|
if(dontClobberA)
|
||||||
|
out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
|
||||||
else
|
else
|
||||||
out(" ldx P8ZP_SCRATCH_REG_X")
|
out(" pla | tax")
|
||||||
}
|
}
|
||||||
CpuRegister.Y -> out(" pla | tay")
|
else -> out(" ldx P8ZP_SCRATCH_REG_X")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CpuRegister.Y -> {
|
||||||
|
when {
|
||||||
|
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" ply")
|
||||||
|
dontClobberA -> out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
|
||||||
|
else -> out(" pla | tay")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun translate(stmt: Statement) {
|
internal fun translate(stmt: Statement) {
|
||||||
outputSourceLine(stmt)
|
outputSourceLine(stmt)
|
||||||
@ -796,6 +825,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: IfStatement) {
|
private fun translate(stmt: IfStatement) {
|
||||||
|
// TODO don't generate needless jumps/labels when the if or else block is empty
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT))
|
||||||
val elseLabel = makeLabel("if_else")
|
val elseLabel = makeLabel("if_else")
|
||||||
|
@ -19,7 +19,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) // we only save X for now (required! is the eval stack pointer), screw A and Y...
|
asmgen.saveRegister(CpuRegister.X, forFuncCall = true, dontClobberA = false) // we only save X for now (required! is the eval stack pointer), screw A and Y...
|
||||||
|
|
||||||
val subName = asmgen.asmSymbolName(stmt.target)
|
val subName = asmgen.asmSymbolName(stmt.target)
|
||||||
if(stmt.args.isNotEmpty()) {
|
if(stmt.args.isNotEmpty()) {
|
||||||
@ -58,7 +58,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
asmgen.out(" jsr $subName")
|
asmgen.out(" jsr $subName")
|
||||||
|
|
||||||
if(saveX)
|
if(saveX)
|
||||||
asmgen.restoreRegister(CpuRegister.X)
|
asmgen.restoreRegister(CpuRegister.X, forFuncCall = true, dontClobberA = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
||||||
@ -120,6 +120,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(argForXregister!=null) {
|
if(argForXregister!=null) {
|
||||||
|
|
||||||
if(argForAregister!=null)
|
if(argForAregister!=null)
|
||||||
asmgen.out(" pha")
|
asmgen.out(" pha")
|
||||||
when(argForXregister.value.second.registerOrPair) {
|
when(argForXregister.value.second.registerOrPair) {
|
||||||
|
@ -38,9 +38,7 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if iter & 1
|
if iter & 1
|
||||||
; TODO fix plot() so we don't have to use separate internal variable
|
graphics.plot(pixelx, pixely) ; TODO get rid of typecast in pixelx arg
|
||||||
graphics.internal_plotx = pixelx
|
|
||||||
graphics.internal_plot(pixely)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user