mirror of
https://github.com/irmen/prog8.git
synced 2025-01-14 01:29:55 +00:00
byte/word typecasts optimized even further to just use cpu registers (and fixed sign extending AY)
This commit is contained in:
parent
53a600d87b
commit
238d8197f5
@ -1081,7 +1081,6 @@ sign_extend_stack_byte .proc
|
|||||||
sign_extend_AY_byte .proc
|
sign_extend_AY_byte .proc
|
||||||
; -- sign extend the (signed) byte in AY to full 16 bits
|
; -- sign extend the (signed) byte in AY to full 16 bits
|
||||||
pha
|
pha
|
||||||
tya
|
|
||||||
and #$80
|
and #$80
|
||||||
beq +
|
beq +
|
||||||
ldy #$ff
|
ldy #$ff
|
||||||
|
@ -122,7 +122,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
assignMemoryByte(assign.target, null, value.addressExpression as IdentifierReference)
|
assignMemoryByte(assign.target, null, value.addressExpression as IdentifierReference)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
asmgen.assignExpressionToVariable(value.addressExpression, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, assign.target.scope)
|
assignExpressionToVariable(value.addressExpression, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, assign.target.scope)
|
||||||
asmgen.out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
|
asmgen.out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
|
||||||
assignRegisterByte(assign.target, CpuRegister.A)
|
assignRegisterByte(assign.target, CpuRegister.A)
|
||||||
}
|
}
|
||||||
@ -272,18 +272,26 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
return assignTypeCastedIdentifier(target.asmVarname, targetDt, asmgen.asmVariableName(value), valueDt)
|
return assignTypeCastedIdentifier(target.asmVarname, targetDt, asmgen.asmVariableName(value), valueDt)
|
||||||
|
|
||||||
when (valueDt) {
|
when (valueDt) {
|
||||||
in ByteDatatypes, in WordDatatypes -> {
|
in ByteDatatypes -> {
|
||||||
// TODO optimize byte/word typecasts even more by only using registers
|
assignExpressionToRegister(value, RegisterOrPair.A)
|
||||||
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", valueDt, null)
|
return assignTypeCastedRegisters(target.asmVarname, targetDt, RegisterOrPair.A, valueDt)
|
||||||
return assignTypeCastedIdentifier(target.asmVarname, targetDt, "P8ZP_SCRATCH_W1", valueDt)
|
}
|
||||||
|
in WordDatatypes -> {
|
||||||
|
assignExpressionToRegister(value, RegisterOrPair.AY)
|
||||||
|
return assignTypeCastedRegisters(target.asmVarname, targetDt, RegisterOrPair.AY, valueDt)
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
// float value cast, fall through and do it via stack for now
|
// float value cast, fall through and do it via stack for now
|
||||||
// TODO optimize float casts to not use stack
|
// because doing it with an intermediate variable uses up quite a few extra instructions at this point..
|
||||||
|
// TODO re-enable float cast via var once expression code generation is more efficent? Or do it via FAC1 directly?
|
||||||
|
// val scope = value.definingSubroutine()!!
|
||||||
|
// scope.asmGenInfo.usedFloatEvalResultVar = true
|
||||||
|
// assignExpressionToVariable(value, subroutineFloatEvalResultVar, valueDt, scope)
|
||||||
|
// return assignTypeCastedIdentifier(target.asmVarname, targetDt, subroutineFloatEvalResultVar, valueDt)
|
||||||
}
|
}
|
||||||
in PassByReferenceDatatypes -> {
|
in PassByReferenceDatatypes -> {
|
||||||
// str/array value cast (most likely to UWORD, take address-of)
|
// str/array value cast (most likely to UWORD, take address-of)
|
||||||
return asmgen.assignExpressionToVariable(value, target.asmVarname, targetDt, null) // TODO test this cast
|
return assignExpressionToVariable(value, target.asmVarname, targetDt, null) // TODO test this cast
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("strange dt in typecast assign to var: $valueDt --> $targetDt")
|
else -> throw AssemblyError("strange dt in typecast assign to var: $valueDt --> $targetDt")
|
||||||
}
|
}
|
||||||
@ -398,6 +406,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
|
// TODO loading targetasmname in SCRATCH_W2 no longer needed???????
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda #<$targetAsmVarName
|
lda #<$targetAsmVarName
|
||||||
ldy #>$targetAsmVarName
|
ldy #>$targetAsmVarName
|
||||||
@ -423,6 +432,145 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun assignTypeCastedRegisters(targetAsmVarName: String, targetDt: DataType,
|
||||||
|
regs: RegisterOrPair, sourceDt: DataType) {
|
||||||
|
if(sourceDt == targetDt)
|
||||||
|
throw AssemblyError("typecast to identical value")
|
||||||
|
|
||||||
|
// also see: ExpressionAsmGen, fun translateExpression(typecast: TypecastExpression)
|
||||||
|
when(sourceDt) {
|
||||||
|
DataType.UBYTE -> {
|
||||||
|
when(targetDt) {
|
||||||
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName")
|
||||||
|
}
|
||||||
|
DataType.UWORD, DataType.WORD -> {
|
||||||
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||||
|
else
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.A -> asmgen.out(" tay")
|
||||||
|
RegisterOrPair.X -> asmgen.out(" txa | tay")
|
||||||
|
RegisterOrPair.Y -> {}
|
||||||
|
else -> throw AssemblyError("non-byte regs")
|
||||||
|
}
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda #>$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
jsr floats.cast_from_ub""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.BYTE -> {
|
||||||
|
when(targetDt) {
|
||||||
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName")
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||||
|
else
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||||
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.A -> {}
|
||||||
|
RegisterOrPair.X -> asmgen.out(" txa")
|
||||||
|
RegisterOrPair.Y -> asmgen.out(" tya")
|
||||||
|
else -> throw AssemblyError("non-byte regs")
|
||||||
|
}
|
||||||
|
asmgen.signExtendAYlsb(sourceDt)
|
||||||
|
asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.A -> {}
|
||||||
|
RegisterOrPair.X -> asmgen.out(" txa")
|
||||||
|
RegisterOrPair.Y -> asmgen.out(" tya")
|
||||||
|
else -> throw AssemblyError("non-byte regs")
|
||||||
|
}
|
||||||
|
asmgen.out("""
|
||||||
|
ldy #<$targetAsmVarName
|
||||||
|
sty P8ZP_SCRATCH_W2
|
||||||
|
ldy #>$targetAsmVarName
|
||||||
|
sty P8ZP_SCRATCH_W2+1
|
||||||
|
jsr floats.cast_from_b""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
when(targetDt) {
|
||||||
|
DataType.BYTE, DataType.UBYTE -> {
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase().first()} $targetAsmVarName")
|
||||||
|
}
|
||||||
|
DataType.WORD, DataType.UWORD -> {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" stx $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
else -> throw AssemblyError("non-word regs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
if(regs!=RegisterOrPair.AY)
|
||||||
|
throw AssemblyError("only supports AY here")
|
||||||
|
asmgen.out("""
|
||||||
|
pha
|
||||||
|
lda #<$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda #>$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
pla
|
||||||
|
jsr floats.cast_from_uw""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
when(targetDt) {
|
||||||
|
DataType.BYTE, DataType.UBYTE -> {
|
||||||
|
asmgen.out(" st${regs.toString().toLowerCase().first()} $targetAsmVarName")
|
||||||
|
}
|
||||||
|
DataType.WORD, DataType.UWORD -> {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" stx $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
else -> throw AssemblyError("non-word regs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
if(regs!=RegisterOrPair.AY)
|
||||||
|
throw AssemblyError("only supports AY here")
|
||||||
|
asmgen.out("""
|
||||||
|
pha
|
||||||
|
lda #<$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2
|
||||||
|
lda #>$targetAsmVarName
|
||||||
|
sta P8ZP_SCRATCH_W2+1
|
||||||
|
pla
|
||||||
|
jsr floats.cast_from_w""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.STR -> {
|
||||||
|
if (targetDt != DataType.UWORD && targetDt == DataType.STR)
|
||||||
|
throw AssemblyError("cannot typecast a string into another incompatitble type")
|
||||||
|
TODO("assign typecasted string into target var")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun assignStackValue(target: AsmAssignTarget) {
|
private fun assignStackValue(target: AsmAssignTarget) {
|
||||||
when(target.kind) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
@ -1469,7 +1617,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
asmgen.storeByteIntoPointer(addressExpr, ldaInstructionArg)
|
asmgen.storeByteIntoPointer(addressExpr, ldaInstructionArg)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
asmgen.assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||||
asmgen.out(" ldy #0 | lda $ldaInstructionArg | sta (P8ZP_SCRATCH_W2),y")
|
asmgen.out(" ldy #0 | lda $ldaInstructionArg | sta (P8ZP_SCRATCH_W2),y")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1494,7 +1642,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
asmgen.saveRegister(register, false, memoryAddress.definingSubroutine()!!)
|
asmgen.saveRegister(register, false, memoryAddress.definingSubroutine()!!)
|
||||||
asmgen.assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||||
asmgen.restoreRegister(CpuRegister.A, false)
|
asmgen.restoreRegister(CpuRegister.A, false)
|
||||||
asmgen.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
|
asmgen.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
|
||||||
}
|
}
|
||||||
|
112
examples/test.p8
112
examples/test.p8
@ -7,105 +7,29 @@ main {
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
uword uw = $c000
|
float fl
|
||||||
ubyte ub = 1
|
word ww
|
||||||
ubyte ub2 = 1
|
uword uw
|
||||||
uword uv1 = 1
|
byte bb
|
||||||
uword uv2 = 1
|
ubyte ub
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw += ub+ub2
|
fl = 9997.999
|
||||||
|
ww = (fl+1.1) as word
|
||||||
|
uw = (fl+1.1) as uword
|
||||||
|
fl = 97.999
|
||||||
|
bb = (fl+1.1) as byte
|
||||||
|
ub = (fl+1.1) as ubyte
|
||||||
|
|
||||||
|
txt.print_w(ww)
|
||||||
|
txt.chrout('\n')
|
||||||
txt.print_uw(uw)
|
txt.print_uw(uw)
|
||||||
txt.chrout('\n')
|
txt.chrout('\n')
|
||||||
|
txt.print_b(bb)
|
||||||
uw = 1000
|
txt.chrout('\n')
|
||||||
uw -= ub+ub2
|
txt.print_ub(ub)
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
txt.chrout('\n')
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw *= ub+ub2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw /= ub+ub2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw %= 5*ub+ub2+ub2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw <<= ub+ub2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw >>= ub+ub2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw &= (ub+ub2) | 15
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw |= (ub+ub2) | 15
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw ^= (ub+ub2) | 15
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw += uv1+uv2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw -= uv1+uv2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw *= uv1+uv2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw /= uv1+uv2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = 1000
|
|
||||||
uw %= 5*uv1+uv2+uv2
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw &= (uv1+uv2) | 1023
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw |= (uv1+uv2) | 32768
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
uw = $1111
|
|
||||||
uw ^= (uv1+uv2) | 32768
|
|
||||||
txt.print_uwhex(uw, 1)
|
|
||||||
txt.chrout('\n')
|
|
||||||
|
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user