mirror of
https://github.com/irmen/prog8.git
synced 2024-09-08 10:55:08 +00:00
restored certain memoryread asm gen
This commit is contained in:
parent
0b717f9e76
commit
335599ed22
@ -89,7 +89,14 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E
|
|||||||
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(sourceDt in PassByReferenceDatatypes) {
|
|
||||||
|
|
||||||
|
// Note: for various reasons (most importantly, code simplicity), the code generator assumes/requires
|
||||||
|
// that the types of assignment values and their target are the same,
|
||||||
|
// and that the types of both operands of a binaryexpression node are the same.
|
||||||
|
// So, it is not easily possible to remove the typecasts that are there to make these conditions true.
|
||||||
|
|
||||||
|
if(sourceDt in PassByReferenceDatatypes) {
|
||||||
if(typecast.type==DataType.UWORD) {
|
if(typecast.type==DataType.UWORD) {
|
||||||
return listOf(IAstModification.ReplaceNode(
|
return listOf(IAstModification.ReplaceNode(
|
||||||
typecast,
|
typecast,
|
||||||
|
@ -72,10 +72,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
TODO("assign from memread $assign") // see inplaceModification() ?
|
asmgen.translateExpression(read.addressExpression)
|
||||||
// asmgen.translateExpression(read.addressExpression)
|
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
||||||
// asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
assignFromRegister(assign.target, CpuRegister.A)
|
||||||
// assignFromRegister(assign.target, CpuRegister.A)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
val arrayIdx = target.arrayindexed
|
val arrayIdx = target.arrayindexed
|
||||||
val identifier = target.identifier
|
val identifier = target.identifier
|
||||||
val memory = target.memoryAddress
|
val memory = target.memoryAddress
|
||||||
|
val targetDt = target.inferType(program, origAssign).typeOrElse(DataType.STRUCT)
|
||||||
val valueLv = (value as? NumericLiteralValue)?.number
|
val valueLv = (value as? NumericLiteralValue)?.number
|
||||||
val ident = value as? IdentifierReference
|
val ident = value as? IdentifierReference
|
||||||
|
|
||||||
@ -124,9 +125,34 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
when {
|
when {
|
||||||
valueLv != null -> inplaceModification_word_litval_to_variable(name, operator, valueLv.toInt(), origAssign)
|
valueLv != null -> inplaceModification_word_litval_to_variable(name, operator, valueLv.toInt())
|
||||||
ident != null -> inplaceModification_word_variable_to_variable(name, operator, ident)
|
ident != null -> inplaceModification_word_variable_to_variable(name, operator, ident)
|
||||||
// TODO more specialized code for types such as memory read etc.
|
// TODO more specialized code for types such as memory read etc.
|
||||||
|
// value is DirectMemoryRead -> {
|
||||||
|
// asmgen.errors.warn("slow stack evaluation used (8): $name $operator= ${value::class.simpleName}", value.position) // TODO
|
||||||
|
// // assignmentAsmGen.translateOtherAssignment(origAssign)
|
||||||
|
// asmgen.translateExpression(value.addressExpression)
|
||||||
|
// asmgen.out("""
|
||||||
|
// jsr prog8_lib.read_byte_from_address_on_stack
|
||||||
|
// sta ...
|
||||||
|
// inx
|
||||||
|
// """)
|
||||||
|
// inplaceModification_word_value_to_variable(name, operator, )
|
||||||
|
// // TODO
|
||||||
|
// }
|
||||||
|
value is TypecastExpression -> {
|
||||||
|
if(targetDt == value.type) {
|
||||||
|
// this typecast is redundant here.
|
||||||
|
// the rest of the code knows how to deal with
|
||||||
|
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
|
if(value.type == childDt || value.type.largerThan(childDt)) {
|
||||||
|
println("***(test) removing redundant typecast ${value.position} $childDt") // TODO
|
||||||
|
inplaceModification(target, operator, value.expression, origAssign)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inplaceModification_word_value_to_variable(name, operator, value)
|
||||||
|
}
|
||||||
else -> inplaceModification_word_value_to_variable(name, operator, value)
|
else -> inplaceModification_word_value_to_variable(name, operator, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,6 +261,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
||||||
|
val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
|
||||||
|
// TODO check valueDt
|
||||||
val otherName = asmgen.asmIdentifierName(ident)
|
val otherName = asmgen.asmIdentifierName(ident)
|
||||||
TODO("Not yet implemented $name $operator= $otherName")
|
TODO("Not yet implemented $name $operator= $otherName")
|
||||||
}
|
}
|
||||||
@ -450,7 +478,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplaceModification_word_litval_to_variable(name: String, operator: String, value: Int, origAssign: Assignment) {
|
private fun inplaceModification_word_litval_to_variable(name: String, operator: String, value: Int) {
|
||||||
when (operator) {
|
when (operator) {
|
||||||
// note: ** (power) operator requires floats.
|
// note: ** (power) operator requires floats.
|
||||||
// TODO use the + and - optimizations in the expression asm code as well.
|
// TODO use the + and - optimizations in the expression asm code as well.
|
||||||
@ -539,22 +567,25 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"&" -> {
|
"&" -> {
|
||||||
if (value and 255 == 0)
|
when {
|
||||||
TODO("only high byte")
|
value and 255 == 0 -> TODO("only high byte")
|
||||||
else
|
value < 0x0100 -> TODO("only low byte")
|
||||||
asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1")
|
else -> asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"^" -> {
|
"^" -> {
|
||||||
if (value and 255 == 0)
|
when {
|
||||||
TODO("only high byte")
|
value and 255 == 0 -> TODO("only high byte")
|
||||||
else
|
value < 0x0100 -> TODO("only low byte")
|
||||||
asmgen.out(" lda $name | xor #<$value | sta $name | lda $name+1 | xor #>$value | sta $name+1")
|
else -> asmgen.out(" lda $name | xor #<$value | sta $name | lda $name+1 | xor #>$value | sta $name+1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"|" -> {
|
"|" -> {
|
||||||
if (value and 255 == 0)
|
when {
|
||||||
TODO("only high byte")
|
value and 255 == 0 -> TODO("only high byte")
|
||||||
else
|
value < 0x0100 -> TODO("only low byte")
|
||||||
asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1")
|
else -> asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
@ -562,6 +593,41 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
|
|
||||||
private fun inplaceModification_word_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
private fun inplaceModification_word_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
||||||
val otherName = asmgen.asmIdentifierName(ident)
|
val otherName = asmgen.asmIdentifierName(ident)
|
||||||
|
val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
|
||||||
|
when (valueDt) {
|
||||||
|
in ByteDatatypes -> {
|
||||||
|
// the other variable is a BYTE type so optimize for that
|
||||||
|
when (operator) {
|
||||||
|
// note: ** (power) operator requires floats.
|
||||||
|
"+" -> asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
clc
|
||||||
|
adc $otherName
|
||||||
|
sta $name
|
||||||
|
bcc +
|
||||||
|
inc $name+1
|
||||||
|
+ """)
|
||||||
|
"-" -> asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
sec
|
||||||
|
sbc $otherName
|
||||||
|
sta $name
|
||||||
|
bcs +
|
||||||
|
dec $name+1
|
||||||
|
+ """)
|
||||||
|
"*" -> TODO()
|
||||||
|
"/" -> TODO()
|
||||||
|
"%" -> TODO("word remainder")
|
||||||
|
"<<" -> TODO()
|
||||||
|
">>" -> TODO()
|
||||||
|
"&" -> TODO()
|
||||||
|
"^" -> TODO()
|
||||||
|
"|" -> TODO()
|
||||||
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in WordDatatypes -> {
|
||||||
|
// the value is a proper 16-bit word, so use both bytes of it.
|
||||||
when (operator) {
|
when (operator) {
|
||||||
// note: ** (power) operator requires floats.
|
// note: ** (power) operator requires floats.
|
||||||
"+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1")
|
"+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1")
|
||||||
@ -582,12 +648,53 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
throw AssemblyError("can only use integer datatypes here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun inplaceModification_word_value_to_variable(name: String, operator: String, value: Expression) {
|
private fun inplaceModification_word_value_to_variable(name: String, operator: String, value: Expression) {
|
||||||
// this should be the last resort for code generation for this,
|
// this should be the last resort for code generation for this,
|
||||||
// because the value is evaluated onto the eval stack (=slow).
|
// because the value is evaluated onto the eval stack (=slow).
|
||||||
asmgen.errors.warn("slow stack evaluation used (4): $name $operator= ${value::class.simpleName}", value.position) // TODO
|
asmgen.errors.warn("slow stack evaluation used (4): $name $operator= ${value::class.simpleName}", value.position) // TODO
|
||||||
asmgen.translateExpression(value)
|
asmgen.translateExpression(value)
|
||||||
|
val valueDt = value.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
|
|
||||||
|
when(valueDt) {
|
||||||
|
in ByteDatatypes -> {
|
||||||
|
// the other variable is a BYTE type so optimize for that
|
||||||
|
when (operator) {
|
||||||
|
// note: ** (power) operator requires floats.
|
||||||
|
"+" -> asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
clc
|
||||||
|
adc $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
sta $name
|
||||||
|
bcc +
|
||||||
|
inc $name+1
|
||||||
|
+ """)
|
||||||
|
"-" -> asmgen.out("""
|
||||||
|
lda $name
|
||||||
|
sec
|
||||||
|
sbc $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
sta $name
|
||||||
|
bcs +
|
||||||
|
dec $name+1
|
||||||
|
+ """)
|
||||||
|
"*" -> TODO()
|
||||||
|
"/" -> TODO()
|
||||||
|
"%" -> TODO("word remainder")
|
||||||
|
"<<" -> TODO()
|
||||||
|
">>" -> TODO()
|
||||||
|
"&" -> TODO()
|
||||||
|
"^" -> TODO()
|
||||||
|
"|" -> TODO()
|
||||||
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in WordDatatypes -> {
|
||||||
|
// the value is a proper 16-bit word, so use both bytes of it.
|
||||||
when (operator) {
|
when (operator) {
|
||||||
// note: ** (power) operator requires floats.
|
// note: ** (power) operator requires floats.
|
||||||
"+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | adc $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
|
"+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | adc $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
|
||||||
@ -607,6 +714,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
"|" -> asmgen.out(" lda $name | ora $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | ora $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
|
"|" -> asmgen.out(" lda $name | ora $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | ora $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw AssemblyError("can only use integer datatypes here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
asmgen.out(" inx")
|
asmgen.out(" inx")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,37 +8,14 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
ubyte A =$22
|
ubyte A =$22
|
||||||
uword addr = $c080
|
ubyte V
|
||||||
|
uword addr = $c0f0
|
||||||
|
|
||||||
c64scr.print_uwhex(addr, true)
|
@($c000) = 123
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr += $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr += $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr += $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr += $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr += $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
addr -= $21
|
A = @($c022-A)
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
c64scr.print_ub(A)
|
||||||
addr -= $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr -= $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
addr -= $21
|
|
||||||
c64scr.print_uwhex(addr, true)
|
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user