mirror of
https://github.com/irmen/prog8.git
synced 2024-07-08 10:29:09 +00:00
asm fix
This commit is contained in:
parent
c83a61c460
commit
ef7744dbda
@ -52,6 +52,7 @@ multiply_words .proc
|
||||
; -- multiply two 16-bit words into a 32-bit result (signed and unsigned)
|
||||
; input: A/Y = first 16-bit number, c64.SCRATCH_ZPWORD1 in ZP = second 16-bit number
|
||||
; output: multiply_words.result 4-bytes/32-bits product, LSB order (low-to-high)
|
||||
; clobbers: A
|
||||
|
||||
sta c64.SCRATCH_ZPWORD2
|
||||
sty c64.SCRATCH_ZPWORD2+1
|
||||
|
@ -55,7 +55,7 @@ write_byte_to_address_on_stack .proc
|
||||
ldy c64.ESTACK_HI+1,x
|
||||
sty c64.SCRATCH_ZPWORD2+1
|
||||
ldy #0
|
||||
lda (c64.SCRATCH_ZPWORD2),y
|
||||
sta (c64.SCRATCH_ZPWORD2),y
|
||||
rts
|
||||
.pend
|
||||
|
||||
@ -343,9 +343,7 @@ mul_word .proc
|
||||
sta c64.SCRATCH_ZPWORD1+1
|
||||
lda c64.ESTACK_LO+1,x
|
||||
ldy c64.ESTACK_HI+1,x
|
||||
stx c64.SCRATCH_ZPREGX
|
||||
jsr math.multiply_words
|
||||
ldx c64.SCRATCH_ZPREGX
|
||||
lda math.multiply_words.result
|
||||
sta c64.ESTACK_LO+1,x
|
||||
lda math.multiply_words.result+1
|
||||
|
@ -371,7 +371,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val addressExpr = memoryAddress.addressExpression
|
||||
val addressLv = addressExpr as? NumericLiteralValue
|
||||
when {
|
||||
addressLv != null -> asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
|
||||
addressLv != null -> {
|
||||
asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
|
||||
}
|
||||
addressExpr is IdentifierReference -> {
|
||||
val pointerVarName = asmgen.asmIdentifierName(addressExpr)
|
||||
asmgen.out("""
|
||||
@ -404,7 +406,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val addressLv = addressExpr as? NumericLiteralValue
|
||||
val registerName = register.name.toLowerCase()
|
||||
when {
|
||||
addressLv != null -> asmgen.out(" st$registerName ${addressLv.number.toHex()}")
|
||||
addressLv != null -> {
|
||||
asmgen.out(" st$registerName ${addressLv.number.toHex()}")
|
||||
}
|
||||
addressExpr is IdentifierReference -> {
|
||||
val targetName = asmgen.asmIdentifierName(addressExpr)
|
||||
when (register) {
|
||||
|
@ -23,7 +23,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
val px = assign.value as PrefixExpression
|
||||
val type = px.inferType(program).typeOrElse(DataType.STRUCT)
|
||||
when (px.operator) {
|
||||
"+" -> {}
|
||||
"+" -> {
|
||||
}
|
||||
"-" -> inplaceNegate(assign.target, type)
|
||||
"~" -> inplaceInvert(assign.target, type)
|
||||
"not" -> inplaceBooleanNot(assign.target, type)
|
||||
@ -43,8 +44,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
return inplaceModification(target, binExpr.operator, binExpr.right, assign)
|
||||
}
|
||||
|
||||
if (binExpr.operator in associativeOperators)
|
||||
{
|
||||
if (binExpr.operator in associativeOperators) {
|
||||
val leftBinExpr = binExpr.left as? BinaryExpression
|
||||
if (leftBinExpr != null && binExpr.right isSameAs target) {
|
||||
// A = 5 <operator> A
|
||||
@ -116,10 +116,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
when (dt) {
|
||||
in ByteDatatypes -> {
|
||||
when {
|
||||
valueLv!=null -> inplaceModification_byte_litval_to_variable(name, operator, valueLv)
|
||||
ident!=null -> inplaceModification_byte_variable_to_variable(name, operator, ident)
|
||||
valueLv != null -> inplaceModification_byte_litval_to_variable(name, dt, operator, valueLv)
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(name, dt, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
else -> inplaceModification_byte_value_to_variable(name, operator, value)
|
||||
else -> inplaceModification_byte_value_to_variable(name, dt, operator, value)
|
||||
}
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
@ -150,10 +150,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
val addr = (memory.addressExpression as NumericLiteralValue).number.toInt()
|
||||
// re-use code to assign a variable, instead this time, use a direct memory address
|
||||
when {
|
||||
valueLv!=null -> inplaceModification_byte_litval_to_variable(addr.toHex(), operator, valueLv)
|
||||
ident!=null -> inplaceModification_byte_variable_to_variable(addr.toHex(), operator, ident)
|
||||
valueLv != null -> inplaceModification_byte_litval_to_variable(addr.toHex(), DataType.UBYTE, operator, valueLv)
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(addr.toHex(), DataType.UBYTE, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
else -> inplaceModification_byte_value_to_variable(addr.toHex(), operator, value)
|
||||
else -> inplaceModification_byte_value_to_variable(addr.toHex(), DataType.UBYTE, operator, value)
|
||||
}
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
@ -170,10 +170,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta ${C64Zeropage.SCRATCH_B1}")
|
||||
// the original memory byte's value is now in the scratch B1 location.
|
||||
when {
|
||||
valueLv!=null -> inplaceModification_byte_litval_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, valueLv)
|
||||
ident!=null -> inplaceModification_byte_variable_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, ident)
|
||||
valueLv != null -> inplaceModification_byte_litval_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv)
|
||||
ident != null -> inplaceModification_byte_variable_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident)
|
||||
// TODO more specialized code for types such as memory read etc.
|
||||
else -> inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, value)
|
||||
else -> inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, value)
|
||||
}
|
||||
asmgen.out(" lda ${C64Zeropage.SCRATCH_B1} | jsr prog8_lib.write_byte_to_address_on_stack | inx")
|
||||
}
|
||||
@ -207,7 +207,18 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
""")
|
||||
}
|
||||
"-" -> {
|
||||
TODO("-")
|
||||
asmgen.out("""
|
||||
jsr c64flt.pop_float_fac1
|
||||
stx ${C64Zeropage.SCRATCH_REG_X}
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.CONUPK
|
||||
jsr c64flt.FSUBT
|
||||
ldx #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.MOVMF
|
||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||
""")
|
||||
}
|
||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> {
|
||||
@ -254,7 +265,20 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"-" -> {
|
||||
if (value == 0.0)
|
||||
return
|
||||
TODO("-")
|
||||
asmgen.out("""
|
||||
stx ${C64Zeropage.SCRATCH_REG_X}
|
||||
lda #<$constValueName
|
||||
ldy #>$constValueName
|
||||
jsr c64flt.MOVFM
|
||||
lda #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.CONUPK
|
||||
jsr c64flt.FSUBT
|
||||
ldx #<$name
|
||||
ldy #>$name
|
||||
jsr c64flt.MOVMF
|
||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||
""")
|
||||
}
|
||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> {
|
||||
@ -275,7 +299,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
|
||||
private fun inplaceModification_byte_value_to_memory(pointername: String, operator: String, value: Expression, origAssign: Assignment) {
|
||||
assignmentAsmGen.translateOtherAssignment(origAssign) // TODO get rid of this fallback
|
||||
TODO("Not yet implemented")
|
||||
TODO("inplaceModification_byte_value_to_memory")
|
||||
}
|
||||
|
||||
private fun inplaceModification_byte_variable_to_memory(pointername: String, operator: String, ident: IdentifierReference) {
|
||||
@ -388,10 +412,24 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
// note: ** (power) operator requires floats.
|
||||
"+" -> asmgen.out(" lda $name | clc | adc #<$value | sta $name | lda $name+1 | adc #>$value | sta $name+1")
|
||||
"-" -> asmgen.out(" lda $name | sec | sbc #<$value | sta $name | lda $name+1 | sbc #>$value | sta $name+1")
|
||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"*" -> {
|
||||
// TODO what about the optimized routines?
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
sta c64.SCRATCH_ZPWORD1
|
||||
lda $name+1
|
||||
sta c64.SCRATCH_ZPWORD1+1
|
||||
lda #<$value
|
||||
ldy #>$value
|
||||
jsr math.multiply_words
|
||||
lda math.multiply_words.result
|
||||
sta $name
|
||||
lda math.multiply_words.result+1
|
||||
sta $name+1,x""")
|
||||
}
|
||||
"/" -> TODO("word $name /= $value")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"%" -> {
|
||||
TODO("word remainder")
|
||||
TODO("word remainder $value")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
@ -466,7 +504,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" inx")
|
||||
}
|
||||
|
||||
private fun inplaceModification_byte_value_to_variable(name: String, operator: String, value: Expression) {
|
||||
private fun inplaceModification_byte_value_to_variable(name: String, dt: DataType, operator: String, value: Expression) {
|
||||
// this should be the last resort for code generation for this,
|
||||
// because the value is evaluated onto the eval stack (=slow).
|
||||
asmgen.translateExpression(value)
|
||||
@ -492,7 +530,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" inx")
|
||||
}
|
||||
|
||||
private fun inplaceModification_byte_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
||||
private fun inplaceModification_byte_variable_to_variable(name: String, dt: DataType, operator: String, ident: IdentifierReference) {
|
||||
val otherName = asmgen.asmIdentifierName(ident)
|
||||
when (operator) {
|
||||
// note: ** (power) operator requires floats.
|
||||
@ -515,15 +553,32 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
private fun inplaceModification_byte_litval_to_variable(name: String, operator: String, value: Double) {
|
||||
private fun inplaceModification_byte_litval_to_variable(name: String, dt: DataType, operator: String, value: Double) {
|
||||
when (operator) {
|
||||
// note: ** (power) operator requires floats.
|
||||
"+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name")
|
||||
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
|
||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"*" -> {
|
||||
// TODO what about the optimized routines?
|
||||
TODO("$dt mul $name *= $value")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
}
|
||||
"/" -> {
|
||||
if (dt == DataType.UBYTE) {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
ldy #$value
|
||||
jsr math.divmod_ub
|
||||
sty $name
|
||||
""")
|
||||
} else {
|
||||
// BYTE
|
||||
// requires to use unsigned division and fix sign afterwards, see idiv_b in prog8lib
|
||||
TODO("BYTE div $name /= $value")
|
||||
}
|
||||
}
|
||||
"%" -> {
|
||||
TODO("byte remainder")
|
||||
TODO("$dt remainder")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
@ -557,7 +612,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
if (innerCastDt == null) {
|
||||
// simple typecast where the value is the target
|
||||
when (targetDt) {
|
||||
DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */ }
|
||||
DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */
|
||||
}
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
when (outerCastDt) {
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
@ -567,7 +623,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
} else
|
||||
throw AssemblyError("weird value")
|
||||
}
|
||||
DataType.UWORD, DataType.WORD, in IterableDatatypes -> {}
|
||||
DataType.UWORD, DataType.WORD, in IterableDatatypes -> {
|
||||
}
|
||||
DataType.FLOAT -> throw AssemblyError("incompatible cast type")
|
||||
else -> throw AssemblyError("weird cast type")
|
||||
}
|
||||
@ -631,7 +688,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||
}
|
||||
else -> {
|
||||
TODO("$memory")
|
||||
asmgen.translateExpression(memory.addressExpression)
|
||||
asmgen.out("""
|
||||
jsr prog8_lib.read_byte_from_address_on_stack
|
||||
beq +
|
||||
lda #1
|
||||
+ eor #1
|
||||
jsr prog8_lib.write_byte_to_address_on_stack
|
||||
inx""")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -699,7 +763,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sta (${C64Zeropage.SCRATCH_W1}),y""")
|
||||
}
|
||||
else -> {
|
||||
TODO("$memory")
|
||||
asmgen.translateExpression(memory.addressExpression)
|
||||
asmgen.out("""
|
||||
jsr prog8_lib.read_byte_from_address_on_stack
|
||||
eor #255
|
||||
jsr prog8_lib.write_byte_to_address_on_stack
|
||||
inx""")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,79 +7,14 @@ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
;ubyte @(addr)=0
|
||||
uword addr = $02
|
||||
uword addr2 = $03
|
||||
ubyte B = 22
|
||||
; all optimized:
|
||||
@(addr) = B
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr2-1) = @(addr2-1) +33
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
uword addr = $c002
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
@(addr-2) = $f8
|
||||
@(addr-2) = not @(addr-2)
|
||||
c64scr.print_ubhex(@($c000), true)
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = 33 + @(addr)
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = (@(addr) + 33) + B
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = (33 + @(addr)) + B
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = (@(addr) + B) + 33
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = (B + @(addr)) + 33
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = B+ (@(addr) + 33)
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = B+(33 + @(addr))
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = 33+(@(addr) + B)
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
|
||||
@(addr) = 11
|
||||
c64scr.print_ub(@(addr))
|
||||
c64.CHROUT('\n')
|
||||
@(addr) = 33+(B + @(addr))
|
||||
c64scr.print_ub(@(addr))
|
||||
@(addr-2) = not @(addr-2)
|
||||
c64scr.print_ubhex(@($c000), true)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user