byte/word typecasts optimized even further to just use cpu registers (and fixed sign extending AY)

This commit is contained in:
Irmen de Jong 2020-11-26 01:11:31 +01:00
parent 53a600d87b
commit 238d8197f5
3 changed files with 175 additions and 104 deletions

View File

@ -1081,7 +1081,6 @@ sign_extend_stack_byte .proc
sign_extend_AY_byte .proc
; -- sign extend the (signed) byte in AY to full 16 bits
pha
tya
and #$80
beq +
ldy #$ff

View File

@ -122,7 +122,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
assignMemoryByte(assign.target, null, value.addressExpression as IdentifierReference)
}
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")
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)
when (valueDt) {
in ByteDatatypes, in WordDatatypes -> {
// TODO optimize byte/word typecasts even more by only using registers
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_W1", valueDt, null)
return assignTypeCastedIdentifier(target.asmVarname, targetDt, "P8ZP_SCRATCH_W1", valueDt)
in ByteDatatypes -> {
assignExpressionToRegister(value, RegisterOrPair.A)
return assignTypeCastedRegisters(target.asmVarname, targetDt, RegisterOrPair.A, valueDt)
}
in WordDatatypes -> {
assignExpressionToRegister(value, RegisterOrPair.AY)
return assignTypeCastedRegisters(target.asmVarname, targetDt, RegisterOrPair.AY, valueDt)
}
DataType.FLOAT -> {
// 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 -> {
// 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")
}
@ -398,6 +406,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
}
DataType.FLOAT -> {
// TODO loading targetasmname in SCRATCH_W2 no longer needed???????
asmgen.out("""
lda #<$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) {
when(target.kind) {
TargetStorageKind.VARIABLE -> {
@ -1469,7 +1617,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.storeByteIntoPointer(addressExpr, ldaInstructionArg)
}
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")
}
}
@ -1494,7 +1642,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
else -> {
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.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
}

View File

@ -7,105 +7,29 @@ main {
sub start() {
uword uw = $c000
ubyte ub = 1
ubyte ub2 = 1
uword uv1 = 1
uword uv2 = 1
float fl
word ww
uword uw
byte bb
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.chrout('\n')
uw = 1000
uw -= ub+ub2
txt.print_uw(uw)
txt.print_b(bb)
txt.chrout('\n')
txt.print_ub(ub)
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()