restored certain memoryread asm gen

This commit is contained in:
Irmen de Jong 2020-08-21 07:44:50 +02:00
parent 0b717f9e76
commit 335599ed22
4 changed files with 172 additions and 76 deletions

View File

@ -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,

View File

@ -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)
} }
} }
} }

View File

@ -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,24 +593,64 @@ 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)
when (operator) { val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
// note: ** (power) operator requires floats. when (valueDt) {
"+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1") in ByteDatatypes -> {
"-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name | lda $name+1 | sbc $otherName+1 | sta $name+1") // the other variable is a BYTE type so optimize for that
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier when (operator) {
"/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") // note: ** (power) operator requires floats.
"%" -> { "+" -> asmgen.out("""
TODO("word remainder") 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) {
// 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 | sec | sbc $otherName | sta $name | lda $name+1 | sbc $otherName+1 | 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("word remainder")
// if(types==DataType.BYTE) // if(types==DataType.BYTE)
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") // throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
// asmgen.out(" jsr prog8_lib.remainder_ub") // asmgen.out(" jsr prog8_lib.remainder_ub")
}
"<<" -> TODO()
">>" -> TODO()
"&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
"^" -> asmgen.out(" lda $name | xor $otherName | sta $name | lda $name+1 | xor $otherName+1 | sta $name+1")
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
}
}
else -> {
throw AssemblyError("can only use integer datatypes here")
} }
"<<" -> TODO()
">>" -> TODO()
"&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
"^" -> asmgen.out(" lda $name | xor $otherName | sta $name | lda $name+1 | xor $otherName+1 | sta $name+1")
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
else -> throw AssemblyError("invalid operator for in-place modification $operator")
} }
} }
@ -588,25 +659,67 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
// 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)
when (operator) { val valueDt = value.inferType(program).typeOrElse(DataType.STRUCT)
// 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") when(valueDt) {
"-" -> asmgen.out(" lda $name | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | sbc $ESTACK_HI_PLUS1_HEX,x | sta $name+1") in ByteDatatypes -> {
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier // the other variable is a BYTE type so optimize for that
"/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") when (operator) {
"%" -> { // note: ** (power) operator requires floats.
TODO("word remainder") "+" -> 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) {
// 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 | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | sbc $ESTACK_HI_PLUS1_HEX,x | 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("word remainder")
// if(types==DataType.BYTE) // if(types==DataType.BYTE)
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") // throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
// asmgen.out(" jsr prog8_lib.remainder_ub") // asmgen.out(" jsr prog8_lib.remainder_ub")
}
"<<" -> TODO()
">>" -> TODO()
"&" -> asmgen.out(" lda $name | and $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | and $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
"^" -> asmgen.out(" lda $name | xor $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | xor $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("can only use integer datatypes here")
} }
"<<" -> TODO()
">>" -> TODO()
"&" -> asmgen.out(" lda $name | and $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | and $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
"^" -> asmgen.out(" lda $name | xor $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | xor $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")
} }
asmgen.out(" inx") asmgen.out(" inx")
} }

View File

@ -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')
} }
} }