mirror of
https://github.com/irmen/prog8.git
synced 2025-01-30 00:31:00 +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))
|
||||
}
|
||||
}
|
||||
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) {
|
||||
return listOf(IAstModification.ReplaceNode(
|
||||
typecast,
|
||||
|
@ -72,10 +72,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
assignFromMemoryByte(assign.target, null, read.addressExpression as IdentifierReference)
|
||||
}
|
||||
else -> {
|
||||
TODO("assign from memread $assign") // see inplaceModification() ?
|
||||
// asmgen.translateExpression(read.addressExpression)
|
||||
// asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
||||
// assignFromRegister(assign.target, CpuRegister.A)
|
||||
asmgen.translateExpression(read.addressExpression)
|
||||
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | inx")
|
||||
assignFromRegister(assign.target, CpuRegister.A)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
val arrayIdx = target.arrayindexed
|
||||
val identifier = target.identifier
|
||||
val memory = target.memoryAddress
|
||||
val targetDt = target.inferType(program, origAssign).typeOrElse(DataType.STRUCT)
|
||||
val valueLv = (value as? NumericLiteralValue)?.number
|
||||
val ident = value as? IdentifierReference
|
||||
|
||||
@ -124,9 +125,34 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
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)
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
@ -235,6 +261,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
|
||||
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)
|
||||
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) {
|
||||
// note: ** (power) operator requires floats.
|
||||
// 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)
|
||||
TODO("only high byte")
|
||||
else
|
||||
asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1")
|
||||
when {
|
||||
value and 255 == 0 -> TODO("only high byte")
|
||||
value < 0x0100 -> TODO("only low byte")
|
||||
else -> asmgen.out(" lda $name | and #<$value | sta $name | lda $name+1 | and #>$value | sta $name+1")
|
||||
}
|
||||
}
|
||||
"^" -> {
|
||||
if (value and 255 == 0)
|
||||
TODO("only high byte")
|
||||
else
|
||||
asmgen.out(" lda $name | xor #<$value | sta $name | lda $name+1 | xor #>$value | sta $name+1")
|
||||
when {
|
||||
value and 255 == 0 -> TODO("only high byte")
|
||||
value < 0x0100 -> TODO("only low byte")
|
||||
else -> asmgen.out(" lda $name | xor #<$value | sta $name | lda $name+1 | xor #>$value | sta $name+1")
|
||||
}
|
||||
}
|
||||
"|" -> {
|
||||
if (value and 255 == 0)
|
||||
TODO("only high byte")
|
||||
else
|
||||
asmgen.out(" lda $name | ora #<$value | sta $name | lda $name+1 | ora #>$value | sta $name+1")
|
||||
when {
|
||||
value and 255 == 0 -> TODO("only high byte")
|
||||
value < 0x0100 -> TODO("only low byte")
|
||||
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")
|
||||
}
|
||||
@ -562,24 +593,64 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
|
||||
private fun inplaceModification_word_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
|
||||
val otherName = asmgen.asmIdentifierName(ident)
|
||||
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")
|
||||
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) {
|
||||
// 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)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// 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).
|
||||
asmgen.errors.warn("slow stack evaluation used (4): $name $operator= ${value::class.simpleName}", value.position) // TODO
|
||||
asmgen.translateExpression(value)
|
||||
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")
|
||||
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) {
|
||||
// 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)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// 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")
|
||||
}
|
||||
|
||||
|
@ -8,37 +8,14 @@ main {
|
||||
sub start() {
|
||||
|
||||
ubyte A =$22
|
||||
uword addr = $c080
|
||||
ubyte V
|
||||
uword addr = $c0f0
|
||||
|
||||
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
|
||||
c64scr.print_uwhex(addr, true)
|
||||
c64.CHROUT('\n')
|
||||
@($c000) = 123
|
||||
|
||||
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)
|
||||
A = @($c022-A)
|
||||
|
||||
c64scr.print_ub(A)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user