mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
little refactor of huge if statement
This commit is contained in:
parent
da57f76de3
commit
b717f1c7eb
@ -388,88 +388,389 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
if(expr.type !in IntegerDatatypes)
|
if(expr.type !in IntegerDatatypes)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) {
|
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor"))
|
||||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
return optimizedLogicalOrBitwiseExpr(expr, assign.target)
|
||||||
if (expr.right.isSimple()) {
|
if(expr.operator == "==" || expr.operator == "!=")
|
||||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
return optimizedEqualityExpr(expr, assign.target)
|
||||||
assignLogicalWithSimpleRightOperandByte(assign.target, expr.left, expr.operator, expr.right)
|
if(expr.operator=="+" || expr.operator=="-")
|
||||||
return true
|
return optimizedPlusMinExpr(expr, assign.target)
|
||||||
}
|
if(expr.operator=="<<" || expr.operator==">>")
|
||||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
return optimizedBitshiftExpr(expr, assign.target)
|
||||||
assignLogicalWithSimpleRightOperandByte(assign.target, expr.right, expr.operator, expr.left)
|
if(expr.operator=="*")
|
||||||
return true
|
return optimizedMultiplyExpr(expr, assign.target)
|
||||||
}
|
if(expr.operator=="/")
|
||||||
}
|
return optimizedDivideExpr(expr, assign.target)
|
||||||
|
if(expr.operator=="%")
|
||||||
|
return optimizedRemainderExpr(expr, assign.target)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedRemainderExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
|
when(expr.type) {
|
||||||
|
DataType.UBYTE -> {
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
asmgen.out(" pha")
|
||||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
||||||
when (expr.operator) {
|
if(target.register==RegisterOrPair.A)
|
||||||
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
asmgen.out(" cmp #0") // fix the status register
|
||||||
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
else
|
||||||
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
else -> throw AssemblyError("invalid operator")
|
|
||||||
}
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
DataType.UWORD -> {
|
||||||
if (expr.right.isSimple()) {
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
asmgen.out(" jsr math.divmod_uw_asm")
|
||||||
assignLogicalWithSimpleRightOperandWord(assign.target, expr.left, expr.operator, expr.right)
|
assignVariableWord(target, "P8ZP_SCRATCH_W2")
|
||||||
return true
|
|
||||||
}
|
|
||||||
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
|
||||||
assignLogicalWithSimpleRightOperandWord(assign.target, expr.right, expr.operator, expr.left)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
|
||||||
when (expr.operator) {
|
|
||||||
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_W1 | pha | tya | and P8ZP_SCRATCH_W1+1 | tay | pla")
|
|
||||||
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_W1 | pha | tya | ora P8ZP_SCRATCH_W1+1 | tay | pla")
|
|
||||||
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_W1 | pha | tya | eor P8ZP_SCRATCH_W1+1 | tay | pla")
|
|
||||||
else -> throw AssemblyError("invalid operator")
|
|
||||||
}
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
else -> return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(expr.operator == "==" || expr.operator == "!=") {
|
private fun optimizedDivideExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
// expression datatype is BOOL (ubyte) but operands can be anything
|
when(expr.type) {
|
||||||
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes &&
|
DataType.UBYTE -> {
|
||||||
expr.left.isSimple() && expr.right.isSimple()) {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
asmgen.out(" pha")
|
||||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
||||||
if(expr.operator=="==") {
|
assignRegisterByte(target, CpuRegister.Y, false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
DataType.BYTE -> {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, true)
|
||||||
|
asmgen.out(" pha")
|
||||||
|
assignExpressionToRegister(expr.right, RegisterOrPair.Y, true)
|
||||||
|
asmgen.out(" pla | jsr math.divmod_b_asm")
|
||||||
|
assignRegisterByte(target, CpuRegister.Y, true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
DataType.UWORD -> {
|
||||||
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
|
asmgen.out(" jsr math.divmod_uw_asm")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
|
asmgen.out(" jsr math.divmod_w_asm")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedMultiplyExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
|
val value = expr.right.asConstInteger()
|
||||||
|
if(value==null) {
|
||||||
|
when(expr.type) {
|
||||||
|
in ByteDatatypes -> {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type in SignedDatatypes)
|
||||||
|
asmgen.out(" pha")
|
||||||
|
assignExpressionToRegister(expr.right, RegisterOrPair.Y, expr.type in SignedDatatypes)
|
||||||
|
asmgen.out(" pla | jsr math.multiply_bytes")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
in WordDatatypes -> {
|
||||||
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
|
asmgen.out(" jsr math.multiply_words")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
when (expr.type) {
|
||||||
|
in ByteDatatypes -> {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type in SignedDatatypes)
|
||||||
|
if (value in asmgen.optimizedByteMultiplications)
|
||||||
|
asmgen.out(" jsr math.mul_byte_${value}")
|
||||||
|
else
|
||||||
|
asmgen.out(" ldy #$value | jsr math.multiply_bytes")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
in WordDatatypes -> {
|
||||||
|
if (value in asmgen.optimizedWordMultiplications) {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type in SignedDatatypes)
|
||||||
|
asmgen.out(" jsr math.mul_word_${value}")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
||||||
|
asmgen.out(" jsr math.multiply_words")
|
||||||
|
}
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedBitshiftExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
|
val shifts = expr.right.asConstInteger()
|
||||||
|
if(shifts!=null) {
|
||||||
|
val dt = expr.left.type
|
||||||
|
if(dt in ByteDatatypes && shifts in 0..7) {
|
||||||
|
val signed = dt == DataType.BYTE
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
|
||||||
|
if(expr.operator=="<<") {
|
||||||
|
repeat(shifts) {
|
||||||
|
asmgen.out(" asl a")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(signed && shifts>0) {
|
||||||
|
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
|
||||||
|
} else {
|
||||||
|
repeat(shifts) {
|
||||||
|
asmgen.out(" lsr a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assignRegisterByte(target, CpuRegister.A, signed)
|
||||||
|
return true
|
||||||
|
} else if(dt in WordDatatypes && shifts in 0..7) {
|
||||||
|
val signed = dt == DataType.WORD
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
|
||||||
|
if(expr.operator=="<<") {
|
||||||
|
if(shifts>0) {
|
||||||
|
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||||
|
repeat(shifts) {
|
||||||
|
asmgen.out(" asl a | rol P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
asmgen.out(" ldy P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(signed) {
|
||||||
|
// TODO("shift AY >> $shifts signed")
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
if(shifts>0) {
|
||||||
|
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||||
|
repeat(shifts) {
|
||||||
|
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a")
|
||||||
|
}
|
||||||
|
asmgen.out(" ldy P8ZP_SCRATCH_B1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedPlusMinExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
|
val dt = expr.type
|
||||||
|
val left = expr.left
|
||||||
|
val right = expr.right
|
||||||
|
if(dt in ByteDatatypes) {
|
||||||
|
when (right) {
|
||||||
|
is PtIdentifier -> {
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
|
||||||
|
val symname = asmgen.asmVariableName(right)
|
||||||
|
if(expr.operator=="+")
|
||||||
|
asmgen.out(" clc | adc $symname")
|
||||||
|
else
|
||||||
|
asmgen.out(" sec | sbc $symname")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
is PtNumber -> {
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
|
||||||
|
if(expr.operator=="+")
|
||||||
|
asmgen.out(" clc | adc #${right.number.toHex()}")
|
||||||
|
else
|
||||||
|
asmgen.out(" sec | sbc #${right.number.toHex()}")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
||||||
|
asmgen.out(" pha")
|
||||||
|
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", right.type)
|
||||||
|
asmgen.out(" pla")
|
||||||
|
if(expr.operator=="+")
|
||||||
|
asmgen.out(" clc | adc P8ZP_SCRATCH_B1")
|
||||||
|
else
|
||||||
|
asmgen.out(" sec | sbc P8ZP_SCRATCH_B1")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(dt in WordDatatypes) {
|
||||||
|
|
||||||
|
fun doAddOrSubWordExpr() {
|
||||||
|
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||||
|
if(expr.operator=="+")
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc P8ZP_SCRATCH_W1
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
adc P8ZP_SCRATCH_W1+1
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
else
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc P8ZP_SCRATCH_W1
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
sbc P8ZP_SCRATCH_W1+1
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (right) {
|
||||||
|
is PtAddressOf -> {
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
||||||
|
val symbol = asmgen.asmVariableName(right.identifier)
|
||||||
|
if(expr.operator=="+")
|
||||||
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc #<$symbol
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
adc #>$symbol
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
else
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc #<$symbol
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
sbc #>$symbol
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
is PtIdentifier -> {
|
||||||
|
val symname = asmgen.asmVariableName(right)
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
||||||
|
if(expr.operator=="+")
|
||||||
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc $symname
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
adc $symname+1
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
else
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc $symname
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
sbc $symname+1
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
is PtNumber -> {
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
||||||
|
if(expr.operator=="+") {
|
||||||
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc #<${right.number.toHex()}
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
adc #>${right.number.toHex()}
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
} else if(expr.operator=="-") {
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc #<${right.number.toHex()}
|
||||||
|
pha
|
||||||
|
tya
|
||||||
|
sbc #>${right.number.toHex()}
|
||||||
|
tay
|
||||||
|
pla""")
|
||||||
|
}
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
is PtTypeCast -> {
|
||||||
|
val castedValue = right.value
|
||||||
|
if(right.type in WordDatatypes && castedValue.type in ByteDatatypes && castedValue is PtIdentifier) {
|
||||||
|
val castedSymname = asmgen.asmVariableName(castedValue)
|
||||||
|
assignExpressionToRegister(left, RegisterOrPair.AY, dt == DataType.WORD)
|
||||||
|
if (expr.operator == "+")
|
||||||
|
asmgen.out(
|
||||||
|
"""
|
||||||
|
clc
|
||||||
|
adc $castedSymname
|
||||||
|
bcc +
|
||||||
|
iny
|
||||||
|
+"""
|
||||||
|
)
|
||||||
|
else
|
||||||
|
asmgen.out(
|
||||||
|
"""
|
||||||
|
sec
|
||||||
|
sbc $castedSymname
|
||||||
|
bcs +
|
||||||
|
dey
|
||||||
|
+"""
|
||||||
|
)
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
doAddOrSubWordExpr()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
doAddOrSubWordExpr()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedEqualityExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
|
// expression datatype is BOOL (ubyte) but operands can be anything
|
||||||
|
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes &&
|
||||||
|
expr.left.isSimple() && expr.right.isSimple()) {
|
||||||
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||||
|
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||||
|
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||||
|
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||||
|
if(expr.operator=="==") {
|
||||||
|
asmgen.out("""
|
||||||
cmp P8ZP_SCRATCH_B1
|
cmp P8ZP_SCRATCH_B1
|
||||||
bne +
|
bne +
|
||||||
lda #1
|
lda #1
|
||||||
bne ++
|
bne ++
|
||||||
+ lda #0
|
+ lda #0
|
||||||
+""")
|
+""")
|
||||||
} else {
|
} else {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
cmp P8ZP_SCRATCH_B1
|
cmp P8ZP_SCRATCH_B1
|
||||||
beq +
|
beq +
|
||||||
lda #1
|
lda #1
|
||||||
bne ++
|
bne ++
|
||||||
+ lda #0
|
+ lda #0
|
||||||
+""")
|
+""")
|
||||||
}
|
}
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
return true
|
return true
|
||||||
} else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes &&
|
} else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes &&
|
||||||
expr.left.isSimple() && expr.right.isSimple()) {
|
expr.left.isSimple() && expr.right.isSimple()) {
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||||
if(expr.operator=="==") {
|
if(expr.operator=="==") {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
cmp P8ZP_SCRATCH_W1
|
cmp P8ZP_SCRATCH_W1
|
||||||
bne +
|
bne +
|
||||||
cpy P8ZP_SCRATCH_W1+1
|
cpy P8ZP_SCRATCH_W1+1
|
||||||
@ -478,8 +779,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
bne ++
|
bne ++
|
||||||
+ lda #0
|
+ lda #0
|
||||||
+""")
|
+""")
|
||||||
} else {
|
} else {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
cmp P8ZP_SCRATCH_W1
|
cmp P8ZP_SCRATCH_W1
|
||||||
bne +
|
bne +
|
||||||
cpy P8ZP_SCRATCH_W1+1
|
cpy P8ZP_SCRATCH_W1+1
|
||||||
@ -488,339 +789,60 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
beq ++
|
beq ++
|
||||||
+ lda #1
|
+ lda #1
|
||||||
+""")
|
+""")
|
||||||
}
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
else if(expr.operator=="+" || expr.operator=="-") {
|
return false
|
||||||
val dt = expr.type
|
}
|
||||||
val left = expr.left
|
|
||||||
val right = expr.right
|
|
||||||
if(dt in ByteDatatypes) {
|
|
||||||
when (right) {
|
|
||||||
is PtIdentifier -> {
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
|
|
||||||
val symname = asmgen.asmVariableName(right)
|
|
||||||
if(expr.operator=="+")
|
|
||||||
asmgen.out(" clc | adc $symname")
|
|
||||||
else
|
|
||||||
asmgen.out(" sec | sbc $symname")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, dt in SignedDatatypes)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
is PtNumber -> {
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.A, dt==DataType.BYTE)
|
|
||||||
if(expr.operator=="+")
|
|
||||||
asmgen.out(" clc | adc #${right.number.toHex()}")
|
|
||||||
else
|
|
||||||
asmgen.out(" sec | sbc #${right.number.toHex()}")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, dt in SignedDatatypes)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
|
||||||
asmgen.out(" pha")
|
|
||||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", right.type)
|
|
||||||
asmgen.out(" pla")
|
|
||||||
if(expr.operator=="+")
|
|
||||||
asmgen.out(" clc | adc P8ZP_SCRATCH_B1")
|
|
||||||
else
|
|
||||||
asmgen.out(" sec | sbc P8ZP_SCRATCH_B1")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, dt in SignedDatatypes)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(dt in WordDatatypes) {
|
|
||||||
|
|
||||||
fun doAddOrSubWordExpr() {
|
private fun optimizedLogicalOrBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||||
if(expr.operator=="+")
|
if (expr.right.isSimple()) {
|
||||||
asmgen.out("""
|
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||||
clc
|
assignLogicalWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
|
||||||
adc P8ZP_SCRATCH_W1
|
return true
|
||||||
pha
|
|
||||||
tya
|
|
||||||
adc P8ZP_SCRATCH_W1+1
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
else
|
|
||||||
asmgen.out("""
|
|
||||||
sec
|
|
||||||
sbc P8ZP_SCRATCH_W1
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
sbc P8ZP_SCRATCH_W1+1
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
}
|
}
|
||||||
|
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||||
|
assignLogicalWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
when (right) {
|
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||||
is PtAddressOf -> {
|
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||||
val symbol = asmgen.asmVariableName(right.identifier)
|
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||||
if(expr.operator=="+")
|
when (expr.operator) {
|
||||||
asmgen.out("""
|
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||||
clc
|
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||||
adc #<$symbol
|
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
|
||||||
pha
|
else -> throw AssemblyError("invalid operator")
|
||||||
tya
|
|
||||||
adc #>$symbol
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
else
|
|
||||||
asmgen.out("""
|
|
||||||
sec
|
|
||||||
sbc #<$symbol
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
sbc #>$symbol
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
is PtIdentifier -> {
|
|
||||||
val symname = asmgen.asmVariableName(right)
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
|
||||||
if(expr.operator=="+")
|
|
||||||
asmgen.out("""
|
|
||||||
clc
|
|
||||||
adc $symname
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
adc $symname+1
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
else
|
|
||||||
asmgen.out("""
|
|
||||||
sec
|
|
||||||
sbc $symname
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
sbc $symname+1
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
is PtNumber -> {
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt==DataType.WORD)
|
|
||||||
if(expr.operator=="+") {
|
|
||||||
asmgen.out("""
|
|
||||||
clc
|
|
||||||
adc #<${right.number.toHex()}
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
adc #>${right.number.toHex()}
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
} else if(expr.operator=="-") {
|
|
||||||
asmgen.out("""
|
|
||||||
sec
|
|
||||||
sbc #<${right.number.toHex()}
|
|
||||||
pha
|
|
||||||
tya
|
|
||||||
sbc #>${right.number.toHex()}
|
|
||||||
tay
|
|
||||||
pla""")
|
|
||||||
}
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
is PtTypeCast -> {
|
|
||||||
val castedValue = right.value
|
|
||||||
if(right.type in WordDatatypes && castedValue.type in ByteDatatypes && castedValue is PtIdentifier) {
|
|
||||||
val castedSymname = asmgen.asmVariableName(castedValue)
|
|
||||||
assignExpressionToRegister(left, RegisterOrPair.AY, dt == DataType.WORD)
|
|
||||||
if (expr.operator == "+")
|
|
||||||
asmgen.out(
|
|
||||||
"""
|
|
||||||
clc
|
|
||||||
adc $castedSymname
|
|
||||||
bcc +
|
|
||||||
iny
|
|
||||||
+"""
|
|
||||||
)
|
|
||||||
else
|
|
||||||
asmgen.out(
|
|
||||||
"""
|
|
||||||
sec
|
|
||||||
sbc $castedSymname
|
|
||||||
bcs +
|
|
||||||
dey
|
|
||||||
+"""
|
|
||||||
)
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
doAddOrSubWordExpr()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
doAddOrSubWordExpr()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
assignRegisterByte(target, CpuRegister.A, false)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
else if(expr.operator=="<<" || expr.operator==">>") {
|
else if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||||
val shifts = expr.right.asConstInteger()
|
if (expr.right.isSimple()) {
|
||||||
if(shifts!=null) {
|
if (expr.right is PtNumber || expr.right is PtIdentifier) {
|
||||||
val dt = expr.left.type
|
assignLogicalWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
|
||||||
if(dt in ByteDatatypes && shifts in 0..7) {
|
|
||||||
val signed = dt == DataType.BYTE
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
|
|
||||||
if(expr.operator=="<<") {
|
|
||||||
repeat(shifts) {
|
|
||||||
asmgen.out(" asl a")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(signed && shifts>0) {
|
|
||||||
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
|
|
||||||
} else {
|
|
||||||
repeat(shifts) {
|
|
||||||
asmgen.out(" lsr a")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, signed)
|
|
||||||
return true
|
return true
|
||||||
} else if(dt in WordDatatypes && shifts in 0..7) {
|
}
|
||||||
val signed = dt == DataType.WORD
|
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
|
assignLogicalWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
|
||||||
if(expr.operator=="<<") {
|
|
||||||
if(shifts>0) {
|
|
||||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
|
||||||
repeat(shifts) {
|
|
||||||
asmgen.out(" asl a | rol P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
asmgen.out(" ldy P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(signed) {
|
|
||||||
// TODO("shift AY >> $shifts signed")
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
if(shifts>0) {
|
|
||||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
|
||||||
repeat(shifts) {
|
|
||||||
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a")
|
|
||||||
}
|
|
||||||
asmgen.out(" ldy P8ZP_SCRATCH_B1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
|
||||||
else if(expr.operator=="*") {
|
when (expr.operator) {
|
||||||
val value = expr.right.asConstInteger()
|
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_W1 | pha | tya | and P8ZP_SCRATCH_W1+1 | tay | pla")
|
||||||
if(value==null) {
|
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_W1 | pha | tya | ora P8ZP_SCRATCH_W1+1 | tay | pla")
|
||||||
when(expr.type) {
|
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_W1 | pha | tya | eor P8ZP_SCRATCH_W1+1 | tay | pla")
|
||||||
in ByteDatatypes -> {
|
else -> throw AssemblyError("invalid operator")
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type in SignedDatatypes)
|
|
||||||
asmgen.out(" pha")
|
|
||||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, expr.type in SignedDatatypes)
|
|
||||||
asmgen.out(" pla | jsr math.multiply_bytes")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
in WordDatatypes -> {
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
|
||||||
asmgen.out(" jsr math.multiply_words")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when (expr.type) {
|
|
||||||
in ByteDatatypes -> {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type in SignedDatatypes)
|
|
||||||
if (value in asmgen.optimizedByteMultiplications)
|
|
||||||
asmgen.out(" jsr math.mul_byte_${value}")
|
|
||||||
else
|
|
||||||
asmgen.out(" ldy #$value | jsr math.multiply_bytes")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
in WordDatatypes -> {
|
|
||||||
if (value in asmgen.optimizedWordMultiplications) {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.AY, expr.type in SignedDatatypes)
|
|
||||||
asmgen.out(" jsr math.mul_word_${value}")
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
|
||||||
asmgen.out(" jsr math.multiply_words")
|
|
||||||
}
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
else if(expr.operator=="/") {
|
|
||||||
when(expr.type) {
|
|
||||||
DataType.UBYTE -> {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
|
||||||
asmgen.out(" pha")
|
|
||||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
|
||||||
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.Y, false)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
DataType.BYTE -> {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, true)
|
|
||||||
asmgen.out(" pha")
|
|
||||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, true)
|
|
||||||
asmgen.out(" pla | jsr math.divmod_b_asm")
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.Y, true)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
DataType.UWORD -> {
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
|
||||||
asmgen.out(" jsr math.divmod_uw_asm")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
DataType.WORD -> {
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
|
||||||
asmgen.out(" jsr math.divmod_w_asm")
|
|
||||||
assignRegisterpairWord(assign.target, RegisterOrPair.AY)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(expr.operator=="%") {
|
|
||||||
when(expr.type) {
|
|
||||||
DataType.UBYTE -> {
|
|
||||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
|
||||||
asmgen.out(" pha")
|
|
||||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
|
||||||
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
|
||||||
if(assign.target.register==RegisterOrPair.A)
|
|
||||||
asmgen.out(" cmp #0") // fix the status register
|
|
||||||
else
|
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
DataType.UWORD -> {
|
|
||||||
asmgen.assignWordOperandsToAYAndVar(expr.right, expr.left, "P8ZP_SCRATCH_W1")
|
|
||||||
asmgen.out(" jsr math.divmod_uw_asm")
|
|
||||||
assignVariableWord(assign.target, "P8ZP_SCRATCH_W2")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,16 +3,11 @@
|
|||||||
|
|
||||||
main
|
main
|
||||||
{
|
{
|
||||||
; 00f9
|
|
||||||
sub start()
|
sub start()
|
||||||
{
|
{
|
||||||
word bb
|
; uword zc = $ea31
|
||||||
|
word zc = -5583
|
||||||
when bb {
|
cx16.r1L = (zc>>10) as ubyte
|
||||||
0,1,22 -> bb+=10
|
txt.print_ub(cx16.r1L) ; 250
|
||||||
33,44,55 -> bb+=20
|
|
||||||
42345 -> bb+=99
|
|
||||||
else -> bb+=30
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user