mirror of
https://github.com/irmen/prog8.git
synced 2025-02-19 11:31:07 +00:00
implemented bit shifting for non-const amounts
This commit is contained in:
parent
9d98746501
commit
bfc8a26381
@ -663,6 +663,33 @@ greatereq_w .proc
|
|||||||
.pend
|
.pend
|
||||||
|
|
||||||
|
|
||||||
|
shiftleft_b .proc
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
bne +
|
||||||
|
rts
|
||||||
|
+ lda c64.ESTACK_LO+1,x
|
||||||
|
- asl a
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
sta c64.ESTACK_LO+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
shiftright_b .proc
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
bne +
|
||||||
|
rts
|
||||||
|
+ lda c64.ESTACK_LO+1,x
|
||||||
|
- lsr a
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
sta c64.ESTACK_LO+1,x
|
||||||
|
rts
|
||||||
|
.pend
|
||||||
|
|
||||||
|
|
||||||
orig_stackpointer .byte 0 ; stores the Stack pointer register at program start
|
orig_stackpointer .byte 0 ; stores the Stack pointer register at program start
|
||||||
|
|
||||||
func_exit .proc
|
func_exit .proc
|
||||||
|
@ -1 +1 @@
|
|||||||
3.2
|
3.3-SNAPSHOT
|
||||||
|
@ -771,12 +771,6 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
if(leftDt !in IntegerDatatypes || rightDt !in IntegerDatatypes)
|
||||||
errors.err("bitwise operator can only be used on integer operands", expr.right.position)
|
errors.err("bitwise operator can only be used on integer operands", expr.right.position)
|
||||||
}
|
}
|
||||||
"<<", ">>" -> {
|
|
||||||
// for now, bit-shifts can only shift by a constant number TODO remove this restriction
|
|
||||||
val constRight = expr.right.constValue(program)
|
|
||||||
if(constRight==null)
|
|
||||||
errors.err("bit-shift can only be done by a constant number (for now)", expr.right.position)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(leftDt !in NumericDatatypes)
|
if(leftDt !in NumericDatatypes)
|
||||||
|
@ -336,8 +336,8 @@ open class Assignment(var target: AssignTarget, var value: Expression, override
|
|||||||
get() {
|
get() {
|
||||||
val binExpr = value as? BinaryExpression
|
val binExpr = value as? BinaryExpression
|
||||||
if(binExpr!=null) {
|
if(binExpr!=null) {
|
||||||
if(binExpr.right !is BinaryExpression && binExpr.left isSameAs target)
|
if(binExpr.left isSameAs target)
|
||||||
return true // A = A <operator> v
|
return true // A = A <operator> Something
|
||||||
|
|
||||||
if(binExpr.operator in associativeOperators) {
|
if(binExpr.operator in associativeOperators) {
|
||||||
if (binExpr.left !is BinaryExpression && binExpr.right isSameAs target)
|
if (binExpr.left !is BinaryExpression && binExpr.right isSameAs target)
|
||||||
|
@ -38,19 +38,18 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun inplaceBinary(target: AssignTarget, binExpr: BinaryExpression, assign: Assignment) {
|
private fun inplaceBinary(target: AssignTarget, binExpr: BinaryExpression, assign: Assignment) {
|
||||||
|
if (binExpr.left isSameAs target) {
|
||||||
if (binExpr.right !is BinaryExpression && binExpr.left isSameAs target) {
|
// A = A <operator> Something
|
||||||
// A = A <operator> 5
|
|
||||||
return inplaceModification(target, binExpr.operator, binExpr.right, assign)
|
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 (binExpr.right isSameAs target) {
|
||||||
if (leftBinExpr != null && binExpr.right isSameAs target) {
|
|
||||||
// A = 5 <operator> A
|
// A = 5 <operator> A
|
||||||
return inplaceModification(target, binExpr.operator, binExpr.left, assign)
|
return inplaceModification(target, binExpr.operator, binExpr.left, assign)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val leftBinExpr = binExpr.left as? BinaryExpression
|
||||||
if (leftBinExpr?.operator == binExpr.operator) {
|
if (leftBinExpr?.operator == binExpr.operator) {
|
||||||
// TODO better optimize the chained asm to avoid intermediate stores/loads?
|
// TODO better optimize the chained asm to avoid intermediate stores/loads?
|
||||||
when {
|
when {
|
||||||
@ -128,8 +127,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
when {
|
when {
|
||||||
valueLv != null -> inplaceModification_word_litval_to_variable(name, operator, valueLv.toInt())
|
valueLv != null -> inplaceModification_word_litval_to_variable(name, dt, operator, valueLv.toInt())
|
||||||
ident != null -> inplaceModification_word_variable_to_variable(name, operator, ident)
|
ident != null -> inplaceModification_word_variable_to_variable(name, dt, 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 -> {
|
// value is DirectMemoryRead -> {
|
||||||
// println("warning: slow stack evaluation used (8): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
// println("warning: slow stack evaluation used (8): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
||||||
@ -145,9 +144,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// }
|
// }
|
||||||
value is TypecastExpression -> {
|
value is TypecastExpression -> {
|
||||||
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
if (tryRemoveRedundantCast(value, target, operator, origAssign)) return
|
||||||
inplaceModification_word_value_to_variable(name, operator, value)
|
inplaceModification_word_value_to_variable(name, dt, operator, value)
|
||||||
}
|
}
|
||||||
else -> inplaceModification_word_value_to_variable(name, operator, value)
|
else -> inplaceModification_word_value_to_variable(name, dt, operator, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
@ -226,7 +225,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
val childDt = value.expression.inferType(program).typeOrElse(DataType.STRUCT)
|
||||||
if (value.type.equalsSize(childDt) || value.type.largerThan(childDt)) {
|
if (value.type.equalsSize(childDt) || value.type.largerThan(childDt)) {
|
||||||
// this typecast is redundant here; the rest of the code knows how to deal with the uncasted value.
|
// this typecast is redundant here; the rest of the code knows how to deal with the uncasted value.
|
||||||
println("***(test) removing redundant typecast ${value.position} $childDt") // TODO
|
|
||||||
inplaceModification(target, operator, value.expression, origAssign)
|
inplaceModification(target, operator, value.expression, origAssign)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -269,9 +267,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||||
"/" -> {
|
"/" -> {
|
||||||
TODO()
|
TODO("div")
|
||||||
// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
}
|
}
|
||||||
"%" -> {
|
"%" -> {
|
||||||
@ -331,11 +329,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
ldx ${C64Zeropage.SCRATCH_REG_X}
|
ldx ${C64Zeropage.SCRATCH_REG_X}
|
||||||
""")
|
""")
|
||||||
}
|
}
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if (value == 0.0)
|
if (value == 0.0)
|
||||||
throw AssemblyError("division by zero")
|
throw AssemblyError("division by zero")
|
||||||
TODO()
|
TODO("div")
|
||||||
// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
}
|
}
|
||||||
"%" -> {
|
"%" -> {
|
||||||
@ -370,16 +368,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
loadByteFromPointerIntoA()
|
loadByteFromPointerIntoA()
|
||||||
asmgen.out(" sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
}
|
}
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("byte remainder")
|
TODO("byte 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("byte asl")
|
"<<" -> TODO("ubyte asl")
|
||||||
">>" -> TODO("byte lsr")
|
">>" -> TODO("ubyte lsr")
|
||||||
"&" -> {
|
"&" -> {
|
||||||
loadByteFromPointerIntoA()
|
loadByteFromPointerIntoA()
|
||||||
asmgen.out(" and $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" and $ESTACK_LO_PLUS1_HEX,x | sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
@ -418,16 +416,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
loadByteFromPointerIntoA()
|
loadByteFromPointerIntoA()
|
||||||
asmgen.out(" sec | sbc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" sec | sbc $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
}
|
}
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("byte remainder")
|
TODO("byte 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("byte asl")
|
"<<" -> TODO("ubyte asl")
|
||||||
">>" -> TODO("byte lsr")
|
">>" -> TODO("ubyte lsr")
|
||||||
"&" -> {
|
"&" -> {
|
||||||
loadByteFromPointerIntoA()
|
loadByteFromPointerIntoA()
|
||||||
asmgen.out(" and $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" and $otherName | sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
@ -464,8 +462,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
loadByteFromPointerInA()
|
loadByteFromPointerInA()
|
||||||
asmgen.out(" sec | sbc #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" sec | sbc #$value | sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
}
|
}
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("byte remainder")
|
TODO("byte remainder")
|
||||||
// if(types==DataType.BYTE)
|
// if(types==DataType.BYTE)
|
||||||
@ -473,16 +471,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||||
}
|
}
|
||||||
"<<" -> {
|
"<<" -> {
|
||||||
if (value > 1) {
|
if (value > 0) {
|
||||||
loadByteFromPointerInA()
|
loadByteFromPointerInA()
|
||||||
repeat(value.toInt()) { asmgen.out(" asl a") }
|
repeat(value) { asmgen.out(" asl a") }
|
||||||
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
">>" -> {
|
">>" -> {
|
||||||
if (value > 1) {
|
if (value > 0) {
|
||||||
loadByteFromPointerInA()
|
loadByteFromPointerInA()
|
||||||
repeat(value.toInt()) { asmgen.out(" lsr a") }
|
repeat(value) { asmgen.out(" lsr a") }
|
||||||
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
|
asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -502,7 +500,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplaceModification_word_litval_to_variable(name: String, operator: String, value: Int) {
|
private fun inplaceModification_word_litval_to_variable(name: String, dt: DataType, 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.
|
||||||
@ -577,17 +575,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||||
}
|
}
|
||||||
"<<" -> {
|
"<<" -> {
|
||||||
if (value > 1) {
|
repeat(value) { asmgen.out(" asl $name | rol $name+1") }
|
||||||
asmgen.out(" lda $name")
|
|
||||||
TODO("word asl")
|
|
||||||
asmgen.out(" sta $name")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
">>" -> {
|
">>" -> {
|
||||||
if (value > 1) {
|
if (value > 0) {
|
||||||
asmgen.out(" lda $name")
|
if(dt==DataType.UWORD) {
|
||||||
TODO("word lsr")
|
repeat(value) { asmgen.out(" lsr $name+1 | ror $name")}
|
||||||
asmgen.out(" sta $name")
|
} else {
|
||||||
|
repeat(value) { asmgen.out(" lda $name+1 | asl a | ror $name+1 | ror $name") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"&" -> {
|
"&" -> {
|
||||||
@ -615,7 +611,7 @@ 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, dt: DataType, operator: String, ident: IdentifierReference) {
|
||||||
val otherName = asmgen.asmIdentifierName(ident)
|
val otherName = asmgen.asmIdentifierName(ident)
|
||||||
val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
|
val valueDt = ident.targetVarDecl(program.namespace)!!.datatype
|
||||||
when (valueDt) {
|
when (valueDt) {
|
||||||
@ -639,14 +635,39 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
bcs +
|
bcs +
|
||||||
dec $name+1
|
dec $name+1
|
||||||
+ """)
|
+ """)
|
||||||
"*" -> TODO()
|
"*" -> TODO("mul")
|
||||||
"/" -> TODO()
|
"/" -> TODO("div")
|
||||||
"%" -> TODO("word remainder")
|
"%" -> TODO("word remainder")
|
||||||
"<<" -> TODO()
|
"<<" -> {
|
||||||
">>" -> TODO()
|
asmgen.out("""
|
||||||
"&" -> TODO()
|
ldy $otherName
|
||||||
"^" -> TODO()
|
- asl $name
|
||||||
"|" -> TODO()
|
rol $name+1
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
}
|
||||||
|
">>" -> {
|
||||||
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
ldy $otherName
|
||||||
|
- lsr $name+1
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
ldy $otherName
|
||||||
|
- lda $name+1
|
||||||
|
asl a
|
||||||
|
ror $name+1
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"&" -> TODO("bitand")
|
||||||
|
"^" -> TODO("bitxor")
|
||||||
|
"|" -> TODO("bitor")
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -656,16 +677,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// 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")
|
||||||
"-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name | lda $name+1 | sbc $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("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("word remainder")
|
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()
|
"<<", ">>" -> throw AssemblyError("shift by a word value not supported, max is a byte")
|
||||||
">>" -> TODO()
|
|
||||||
"&" -> asmgen.out(" lda $name | and $otherName | sta $name | lda $name+1 | and $otherName+1 | sta $name+1")
|
"&" -> 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 | 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")
|
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name | lda $name+1 | ora $otherName+1 | sta $name+1")
|
||||||
@ -678,7 +698,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun inplaceModification_word_value_to_variable(name: String, operator: String, value: Expression) {
|
private fun inplaceModification_word_value_to_variable(name: String, dt: DataType, 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).
|
||||||
println("warning: slow stack evaluation used (4): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
println("warning: slow stack evaluation used (4): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
|
||||||
@ -706,14 +726,50 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
bcs +
|
bcs +
|
||||||
dec $name+1
|
dec $name+1
|
||||||
+ """)
|
+ """)
|
||||||
"*" -> TODO()
|
"*" -> TODO("mul")
|
||||||
"/" -> TODO()
|
"/" -> TODO("div")
|
||||||
"%" -> TODO("word remainder")
|
"%" -> TODO("word remainder")
|
||||||
"<<" -> TODO()
|
"<<" -> {
|
||||||
">>" -> TODO()
|
asmgen.translateExpression(value)
|
||||||
"&" -> TODO()
|
asmgen.out("""
|
||||||
"^" -> TODO()
|
inx
|
||||||
"|" -> TODO()
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- asl $name
|
||||||
|
rol $name+1
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
">>" -> {
|
||||||
|
asmgen.translateExpression(value)
|
||||||
|
if(dt==DataType.UWORD) {
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- lsr $name+1
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""") }
|
||||||
|
else {
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- lda $name+1
|
||||||
|
asl a
|
||||||
|
ror $name+1
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"&" -> TODO("bitand")
|
||||||
|
"^" -> TODO("bitxor")
|
||||||
|
"|" -> TODO("bitor")
|
||||||
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
else -> throw AssemblyError("invalid operator for in-place modification $operator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -723,16 +779,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// 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")
|
||||||
"-" -> 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")
|
"-" -> 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("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("word remainder")
|
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()
|
"<<", ">>" -> throw AssemblyError("shift by a word value not supported, max is a byte")
|
||||||
">>" -> 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 | 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 | 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")
|
"|" -> asmgen.out(" lda $name | ora $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | ora $ESTACK_HI_PLUS1_HEX,x | sta $name+1")
|
||||||
@ -756,16 +811,49 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// note: ** (power) operator requires floats.
|
// note: ** (power) operator requires floats.
|
||||||
"+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
"+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
||||||
"-" -> asmgen.out(" lda $name | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
"-" -> asmgen.out(" lda $name | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("byte remainder")
|
TODO("byte 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.translateExpression(value)
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- asl $name
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
">>" -> {
|
||||||
|
asmgen.translateExpression(value)
|
||||||
|
if(dt==DataType.UBYTE) {
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- lsr $name
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
ldy c64.ESTACK_LO,x
|
||||||
|
beq +
|
||||||
|
- lda $name
|
||||||
|
asl a
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+""")
|
||||||
|
}
|
||||||
|
}
|
||||||
"&" -> asmgen.out(" lda $name | and $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
"&" -> asmgen.out(" lda $name | and $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
||||||
"^" -> asmgen.out(" lda $name | xor $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
"^" -> asmgen.out(" lda $name | xor $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
||||||
"|" -> asmgen.out(" lda $name | ora $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
"|" -> asmgen.out(" lda $name | ora $ESTACK_LO_PLUS1_HEX,x | sta $name")
|
||||||
@ -780,16 +868,38 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// note: ** (power) operator requires floats.
|
// note: ** (power) operator requires floats.
|
||||||
"+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name")
|
"+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name")
|
||||||
"-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name")
|
"-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name")
|
||||||
"*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
"*" -> TODO("mul")// 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("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||||
"%" -> {
|
"%" -> {
|
||||||
TODO("byte remainder")
|
TODO("byte 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("""
|
||||||
|
ldy $otherName
|
||||||
|
- asl $name
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
}
|
||||||
|
">>" -> {
|
||||||
|
if(dt==DataType.UBYTE) {
|
||||||
|
asmgen.out("""
|
||||||
|
ldy $otherName
|
||||||
|
- lsr $name
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
ldy $otherName
|
||||||
|
- lda $name
|
||||||
|
asl a
|
||||||
|
ror $name
|
||||||
|
dey
|
||||||
|
bne -""")
|
||||||
|
}
|
||||||
|
}
|
||||||
"&" -> asmgen.out(" lda $name | and $otherName | sta $name")
|
"&" -> asmgen.out(" lda $name | and $otherName | sta $name")
|
||||||
"^" -> asmgen.out(" lda $name | xor $otherName | sta $name")
|
"^" -> asmgen.out(" lda $name | xor $otherName | sta $name")
|
||||||
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name")
|
"|" -> asmgen.out(" lda $name | ora $otherName | sta $name")
|
||||||
@ -828,17 +938,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||||
}
|
}
|
||||||
"<<" -> {
|
"<<" -> {
|
||||||
if (value > 1) {
|
repeat(value) { asmgen.out(" asl $name") }
|
||||||
asmgen.out(" lda $name")
|
|
||||||
repeat(value.toInt()) { asmgen.out(" asl a") }
|
|
||||||
asmgen.out(" sta $name")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
">>" -> {
|
">>" -> {
|
||||||
if (value > 1) {
|
if(value>0) {
|
||||||
asmgen.out(" lda $name")
|
if (dt == DataType.UBYTE) {
|
||||||
repeat(value.toInt()) { asmgen.out(" lsr a") }
|
repeat(value) { asmgen.out(" lsr $name") }
|
||||||
asmgen.out(" sta $name")
|
} else {
|
||||||
|
repeat(value) { asmgen.out(" lda $name | asl a | ror $name") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"&" -> asmgen.out(" lda $name | and #$value | sta $name")
|
"&" -> asmgen.out(" lda $name | and #$value | sta $name")
|
||||||
|
@ -207,79 +207,78 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
// see if we can apply some optimized routines
|
// see if we can apply some optimized routines
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
">>" -> {
|
">>" -> {
|
||||||
// bit-shifts are always by a constant number (for now)
|
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
val amount = expr.right.constValue(program)!!.number.toInt()
|
val amount = expr.right.constValue(program)?.number?.toInt()
|
||||||
when (leftDt) {
|
if(amount!=null) {
|
||||||
DataType.UBYTE -> {
|
when (leftDt) {
|
||||||
if(amount<=2)
|
DataType.UBYTE -> {
|
||||||
repeat(amount) { asmgen.out(" lsr $ESTACK_LO_PLUS1_HEX,x") }
|
if (amount <= 2)
|
||||||
else {
|
repeat(amount) { asmgen.out(" lsr $ESTACK_LO_PLUS1_HEX,x") }
|
||||||
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x")
|
else {
|
||||||
repeat(amount) { asmgen.out(" lsr a") }
|
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x")
|
||||||
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
repeat(amount) { asmgen.out(" lsr a") }
|
||||||
|
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
DataType.BYTE -> {
|
||||||
DataType.BYTE -> {
|
if (amount <= 2)
|
||||||
if(amount<=2)
|
repeat(amount) { asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x") }
|
||||||
repeat(amount) { asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | asl a | ror $ESTACK_LO_PLUS1_HEX,x") }
|
else {
|
||||||
else {
|
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | sta ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}")
|
||||||
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x | sta ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}")
|
repeat(amount) { asmgen.out(" asl a | ror ${C64MachineDefinition.C64Zeropage.SCRATCH_B1} | lda ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}") }
|
||||||
repeat(amount) { asmgen.out(" asl a | ror ${C64MachineDefinition.C64Zeropage.SCRATCH_B1} | lda ${C64MachineDefinition.C64Zeropage.SCRATCH_B1}") }
|
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
||||||
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
}
|
||||||
}
|
}
|
||||||
}
|
DataType.UWORD -> {
|
||||||
DataType.UWORD -> {
|
var left = amount
|
||||||
var left = amount
|
while (left >= 7) {
|
||||||
while(left>=7) {
|
asmgen.out(" jsr math.shift_right_uw_7")
|
||||||
asmgen.out(" jsr math.shift_right_uw_7")
|
left -= 7
|
||||||
left -= 7
|
}
|
||||||
|
if (left in 0..2)
|
||||||
|
repeat(left) { asmgen.out(" lsr $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
|
||||||
|
else
|
||||||
|
asmgen.out(" jsr math.shift_right_uw_$left")
|
||||||
}
|
}
|
||||||
if (left in 0..2)
|
DataType.WORD -> {
|
||||||
repeat(left) { asmgen.out(" lsr $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
|
var left = amount
|
||||||
else
|
while (left >= 7) {
|
||||||
asmgen.out(" jsr math.shift_right_uw_$left")
|
asmgen.out(" jsr math.shift_right_w_7")
|
||||||
}
|
left -= 7
|
||||||
DataType.WORD -> {
|
}
|
||||||
var left = amount
|
if (left in 0..2)
|
||||||
while(left>=7) {
|
repeat(left) { asmgen.out(" lda $ESTACK_HI_PLUS1_HEX,x | asl a | ror $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
|
||||||
asmgen.out(" jsr math.shift_right_w_7")
|
else
|
||||||
left -= 7
|
asmgen.out(" jsr math.shift_right_w_$left")
|
||||||
}
|
}
|
||||||
if (left in 0..2)
|
else -> throw AssemblyError("weird type")
|
||||||
repeat(left) { asmgen.out(" lda $ESTACK_HI_PLUS1_HEX,x | asl a | ror $ESTACK_HI_PLUS1_HEX,x | ror $ESTACK_LO_PLUS1_HEX,x") }
|
|
||||||
else
|
|
||||||
asmgen.out(" jsr math.shift_right_w_$left")
|
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird type")
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
"<<" -> {
|
"<<" -> {
|
||||||
// bit-shifts are always by a constant number (for now)
|
|
||||||
translateExpression(expr.left)
|
translateExpression(expr.left)
|
||||||
val amount = expr.right.constValue(program)!!.number.toInt()
|
val amount = expr.right.constValue(program)?.number?.toInt()
|
||||||
if (leftDt in ByteDatatypes) {
|
if(amount!=null) {
|
||||||
if(amount<=2)
|
if (leftDt in ByteDatatypes) {
|
||||||
repeat(amount) { asmgen.out(" asl $ESTACK_LO_PLUS1_HEX,x") }
|
if (amount <= 2)
|
||||||
else {
|
repeat(amount) { asmgen.out(" asl $ESTACK_LO_PLUS1_HEX,x") }
|
||||||
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x")
|
else {
|
||||||
repeat(amount) { asmgen.out(" asl a") }
|
asmgen.out(" lda $ESTACK_LO_PLUS1_HEX,x")
|
||||||
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
repeat(amount) { asmgen.out(" asl a") }
|
||||||
|
asmgen.out(" sta $ESTACK_LO_PLUS1_HEX,x")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var left = amount
|
||||||
|
while (left >= 7) {
|
||||||
|
asmgen.out(" jsr math.shift_left_w_7")
|
||||||
|
left -= 7
|
||||||
|
}
|
||||||
|
if (left in 0..2)
|
||||||
|
repeat(left) { asmgen.out(" asl $ESTACK_LO_PLUS1_HEX,x | rol $ESTACK_HI_PLUS1_HEX,x") }
|
||||||
|
else
|
||||||
|
asmgen.out(" jsr math.shift_left_w_$left")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var left=amount
|
|
||||||
while(left>=7) {
|
|
||||||
asmgen.out(" jsr math.shift_left_w_7")
|
|
||||||
left -= 7
|
|
||||||
}
|
|
||||||
if (left in 0..2)
|
|
||||||
repeat(left) { asmgen.out(" asl $ESTACK_LO_PLUS1_HEX,x | rol $ESTACK_HI_PLUS1_HEX,x") }
|
|
||||||
else
|
|
||||||
asmgen.out(" jsr math.shift_left_w_$left")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
val value = expr.right.constValue(program)
|
val value = expr.right.constValue(program)
|
||||||
@ -433,7 +432,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
inx
|
inx
|
||||||
sta $ESTACK_LO_PLUS1_HEX,x
|
sta $ESTACK_LO_PLUS1_HEX,x
|
||||||
""")
|
""")
|
||||||
"<<", ">>" -> throw AssemblyError("bit-shifts not via stack")
|
"<<" -> asmgen.out(" jsr prog8_lib.shiftleft_b")
|
||||||
|
">>" -> asmgen.out(" jsr prog8_lib.shiftright_b")
|
||||||
"<" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.less_ub" else " jsr prog8_lib.less_b")
|
"<" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.less_ub" else " jsr prog8_lib.less_b")
|
||||||
">" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.greater_ub" else " jsr prog8_lib.greater_b")
|
">" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.greater_ub" else " jsr prog8_lib.greater_b")
|
||||||
"<=" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.lesseq_ub" else " jsr prog8_lib.lesseq_b")
|
"<=" -> asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.lesseq_ub" else " jsr prog8_lib.lesseq_b")
|
||||||
|
@ -766,16 +766,6 @@ rndw()
|
|||||||
rndf()
|
rndf()
|
||||||
returns a pseudo-random float between 0.0 and 1.0
|
returns a pseudo-random float between 0.0 and 1.0
|
||||||
|
|
||||||
lsl(x)
|
|
||||||
Shift the bits in x (byte or word) one position to the left.
|
|
||||||
Bit 0 is set to 0 (and the highest bit is shifted into the status register's Carry flag)
|
|
||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
|
||||||
|
|
||||||
lsr(x)
|
|
||||||
Shift the bits in x (byte or word) one position to the right.
|
|
||||||
The highest bit is set to 0 (and bit 0 is shifted into the status register's Carry flag)
|
|
||||||
Modifies in-place, doesn't return a value (so can't be used in an expression).
|
|
||||||
|
|
||||||
rol(x)
|
rol(x)
|
||||||
Rotate the bits in x (byte or word) one position to the left.
|
Rotate the bits in x (byte or word) one position to the left.
|
||||||
This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag,
|
This uses the CPU's rotate semantics: bit 0 will be set to the current value of the Carry flag,
|
||||||
|
@ -5,7 +5,54 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
|
; todo make it possible to use cpu opcodes as varnames such as 'nop'
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
|
byte ub
|
||||||
|
word uw
|
||||||
|
ubyte x = 1
|
||||||
|
ubyte z = 0
|
||||||
|
|
||||||
|
ubyte[] array = [1,2,3]
|
||||||
|
|
||||||
|
ubyte i
|
||||||
|
ub = %00100001
|
||||||
|
for i in 0 to 9 {
|
||||||
|
c64scr.print_ubbin(ub as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
;ub <<= 1
|
||||||
|
;ub <<= x
|
||||||
|
ub <<= (z+1)
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
;ub = %11000110 ; -123
|
||||||
|
ub = -123
|
||||||
|
for i in 0 to 9 {
|
||||||
|
c64scr.print_ubbin(ub as ubyte, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
;ub >>= 1
|
||||||
|
;ub >>= x
|
||||||
|
ub >>= (z+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
uw = %0011100000000011
|
||||||
|
for i in 0 to 17 {
|
||||||
|
c64scr.print_uwbin(uw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
;uw <<= 1
|
||||||
|
;uw <<= x
|
||||||
|
uw <<= (z+1)
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
uw = -12345
|
||||||
|
;uw = %1110000011000100
|
||||||
|
for i in 0 to 17 {
|
||||||
|
c64scr.print_uwbin(uw as uword, true)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
;uw >>= 1
|
||||||
|
;uw >>= x
|
||||||
|
uw >>= (z+1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user