mirror of
https://github.com/irmen/prog8.git
synced 2024-07-08 10:29:09 +00:00
tweaking multiple assignment targets
This commit is contained in:
parent
fad74a6ae0
commit
c90230d33a
31
compiler/examples/swirl-novm.p8
Normal file
31
compiler/examples/swirl-novm.p8
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
%import c64utils
|
||||||
|
%option enable_floats
|
||||||
|
|
||||||
|
~ main {
|
||||||
|
|
||||||
|
const uword width = 320
|
||||||
|
const uword height = 200
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
|
||||||
|
;vm_gfx_clearscr(0)
|
||||||
|
|
||||||
|
float t
|
||||||
|
ubyte color
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
float x = sin(t*1.01) + cos(t*1.1234)
|
||||||
|
float y = cos(t) + sin(t*0.03456)
|
||||||
|
;vm_gfx_pixel(screenx(x), screeny(y), color//16)
|
||||||
|
t += 0.01
|
||||||
|
color++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub screenx(x: float) -> word {
|
||||||
|
return floor(x * flt(width)/4.1) + width // 2
|
||||||
|
}
|
||||||
|
sub screeny(y: float) -> word {
|
||||||
|
return floor(y * flt(height)/4.1) + height // 2
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,12 @@ sub start() {
|
|||||||
byte b1
|
byte b1
|
||||||
|
|
||||||
|
|
||||||
;v1=foo() ; @todo fix return type value error see sub
|
;v1=foo()
|
||||||
|
|
||||||
|
address =c64.MEMBOT(1, 40000.w) ; ok!
|
||||||
|
address =c64.MEMBOT(1, address) ; ok!
|
||||||
|
address =c64.MEMBOT(1, memaddr) ; ok!i
|
||||||
|
;address =c64.MEMBOT(1, wordarray[1]) ; @todo nice error about loading X register from stack
|
||||||
|
|
||||||
A, Y =c64.GETADR() ; ok!
|
A, Y =c64.GETADR() ; ok!
|
||||||
Y, A =c64.GETADR() ; ok!
|
Y, A =c64.GETADR() ; ok!
|
||||||
@ -24,7 +29,6 @@ sub start() {
|
|||||||
memaddr = c64flt.GETADRAY() ; ok!
|
memaddr = c64flt.GETADRAY() ; ok!
|
||||||
wordarray[1] = c64flt.GETADRAY() ; ok!
|
wordarray[1] = c64flt.GETADRAY() ; ok!
|
||||||
v1, v2 =c64.GETADR() ; ok!
|
v1, v2 =c64.GETADR() ; ok!
|
||||||
address =c64.MEMBOT(1, 0.w) ; ok !
|
|
||||||
address =c64.IOBASE() ; ok!
|
address =c64.IOBASE() ; ok!
|
||||||
A = c64.CHRIN() ; ok !
|
A = c64.CHRIN() ; ok !
|
||||||
X = c64.CHRIN() ; ok !
|
X = c64.CHRIN() ; ok !
|
||||||
@ -34,8 +38,8 @@ sub start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub foo() -> ubyte {
|
sub foo() -> byte {
|
||||||
return 1 ; @todo not ubyte but byte (if sub returns byte)
|
return 1 ; @todo fix error: '1' as byte literal (not ubyte)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,25 +304,27 @@ class AstChecker(private val namespace: INameScope,
|
|||||||
override fun process(assignment: Assignment): IStatement {
|
override fun process(assignment: Assignment): IStatement {
|
||||||
|
|
||||||
// assigning from a functioncall COULD return multiple values (from an asm subroutine)
|
// assigning from a functioncall COULD return multiple values (from an asm subroutine)
|
||||||
val stmt = (assignment.value as FunctionCall).target.targetStatement(namespace)
|
if(assignment.value is FunctionCall) {
|
||||||
if(stmt is Subroutine && stmt.returntypes.size>1) {
|
val stmt = (assignment.value as FunctionCall).target.targetStatement(namespace)
|
||||||
if(stmt.isAsmSubroutine) {
|
if (stmt is Subroutine && stmt.returntypes.size > 1) {
|
||||||
if(stmt.returntypes.size != assignment.targets.size)
|
if (stmt.isAsmSubroutine) {
|
||||||
checkResult.add(ExpressionError("number of return values doesn't match number of assignment targets", assignment.value.position))
|
if (stmt.returntypes.size != assignment.targets.size)
|
||||||
else {
|
checkResult.add(ExpressionError("number of return values doesn't match number of assignment targets", assignment.value.position))
|
||||||
if(assignment.targets.all{it.register!=null}) {
|
else {
|
||||||
val returnRegisters = registerSet(stmt.asmReturnvaluesRegisters)
|
if (assignment.targets.all { it.register != null }) {
|
||||||
val targetRegisters = assignment.targets.filter { it.register != null }.map { it.register }.toSet()
|
val returnRegisters = registerSet(stmt.asmReturnvaluesRegisters)
|
||||||
if (returnRegisters != targetRegisters)
|
val targetRegisters = assignment.targets.filter { it.register != null }.map { it.register }.toSet()
|
||||||
checkResult.add(ExpressionError("asmsub return registers $returnRegisters don't match assignment target registers", assignment.position))
|
if (returnRegisters != targetRegisters)
|
||||||
|
checkResult.add(ExpressionError("asmsub return registers $returnRegisters don't match assignment target registers", assignment.position))
|
||||||
|
}
|
||||||
|
for (thing in stmt.returntypes.zip(assignment.targets)) {
|
||||||
|
if (thing.second.determineDatatype(namespace, heap, assignment) != thing.first)
|
||||||
|
checkResult.add(ExpressionError("return type mismatch for target ${thing.second.shortString()}", assignment.value.position))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(thing in stmt.returntypes.zip(assignment.targets)) {
|
} else
|
||||||
if(thing.second.determineDatatype(namespace, heap, assignment)!=thing.first)
|
checkResult.add(ExpressionError("only asmsub subroutines can return multiple values", assignment.value.position))
|
||||||
checkResult.add(ExpressionError("return type mismatch for target ${thing.second.shortString()}", assignment.value.position))
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
checkResult.add(ExpressionError("only asmsub subroutines can return multiple values", assignment.value.position))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultingAssignment = assignment
|
var resultingAssignment = assignment
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package prog8.compiler
|
package prog8.compiler
|
||||||
|
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.cmdline.Compile
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
|
import prog8.ast.RegisterOrPair.*
|
||||||
import prog8.compiler.intermediate.IntermediateProgram
|
import prog8.compiler.intermediate.IntermediateProgram
|
||||||
import prog8.compiler.intermediate.Opcode
|
import prog8.compiler.intermediate.Opcode
|
||||||
import prog8.compiler.intermediate.Value
|
import prog8.compiler.intermediate.Value
|
||||||
@ -792,11 +794,109 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
|
|
||||||
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
|
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
|
||||||
// evaluate the arguments and assign them into the subroutine's argument variables.
|
// evaluate the arguments and assign them into the subroutine's argument variables.
|
||||||
|
prog.line(callPosition)
|
||||||
|
|
||||||
|
if(subroutine.asmParameterRegisters.isNotEmpty()) {
|
||||||
|
if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size)
|
||||||
|
throw CompilerException("no support for mix of register and non-register subroutine arguments")
|
||||||
|
|
||||||
|
// only register arguments (or status-flag bits)
|
||||||
|
var carryParam: Boolean? = null
|
||||||
|
for(arg in arguments.zip(subroutine.asmParameterRegisters)) {
|
||||||
|
if(arg.second.statusflag!=null) {
|
||||||
|
if(arg.second.statusflag==Statusflag.Pc)
|
||||||
|
carryParam = arg.first.constValue(namespace, heap)!!.asBooleanValue
|
||||||
|
else
|
||||||
|
throw CompilerException("no support for status flag parameter: ${arg.second.statusflag}")
|
||||||
|
} else {
|
||||||
|
when (arg.second.registerOrPair!!) {
|
||||||
|
A -> {
|
||||||
|
val assign = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, arg.first, callPosition)
|
||||||
|
assign.linkParents(subroutine.parent)
|
||||||
|
translate(assign)
|
||||||
|
}
|
||||||
|
X -> {
|
||||||
|
// TODO: save X on stack & restore after call
|
||||||
|
val assign = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, arg.first, callPosition)
|
||||||
|
assign.linkParents(subroutine.parent)
|
||||||
|
translate(assign)
|
||||||
|
}
|
||||||
|
Y -> {
|
||||||
|
val assign = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, arg.first, callPosition)
|
||||||
|
assign.linkParents(subroutine.parent)
|
||||||
|
translate(assign)
|
||||||
|
}
|
||||||
|
AX -> {
|
||||||
|
// TODO: save X on stack & restore after call
|
||||||
|
val valueA: IExpression
|
||||||
|
val valueX: IExpression
|
||||||
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
|
if(paramDt==DataType.UBYTE) {
|
||||||
|
valueA=arg.first
|
||||||
|
valueX=LiteralValue.optimalInteger(0, callPosition)
|
||||||
|
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
||||||
|
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
||||||
|
assignA.linkParents(subroutine.parent)
|
||||||
|
assignX.linkParents(subroutine.parent)
|
||||||
|
translate(assignA)
|
||||||
|
translate(assignX)
|
||||||
|
} else if(paramDt==DataType.UWORD) {
|
||||||
|
translate(arg.first)
|
||||||
|
prog.instr(Opcode.POP_REGAX_WORD)
|
||||||
|
} else
|
||||||
|
throw CompilerException("don't know how to pass register parameter of type $paramDt")
|
||||||
|
}
|
||||||
|
AY -> {
|
||||||
|
val valueA: IExpression
|
||||||
|
val valueY: IExpression
|
||||||
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
|
if(paramDt==DataType.UBYTE) {
|
||||||
|
valueA=arg.first
|
||||||
|
valueY=LiteralValue.optimalInteger(0, callPosition)
|
||||||
|
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
|
||||||
|
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
||||||
|
assignA.linkParents(subroutine.parent)
|
||||||
|
assignY.linkParents(subroutine.parent)
|
||||||
|
translate(assignA)
|
||||||
|
translate(assignY)
|
||||||
|
} else if(paramDt==DataType.UWORD) {
|
||||||
|
translate(arg.first)
|
||||||
|
prog.instr(Opcode.POP_REGAY_WORD)
|
||||||
|
} else
|
||||||
|
throw CompilerException("don't know how to pass register parameter of type $paramDt")
|
||||||
|
}
|
||||||
|
XY -> {
|
||||||
|
// TODO: save X on stack & restore after call
|
||||||
|
val valueX: IExpression
|
||||||
|
val valueY: IExpression
|
||||||
|
val paramDt = arg.first.resultingDatatype(namespace, heap)
|
||||||
|
if(paramDt==DataType.UBYTE) {
|
||||||
|
valueX=arg.first
|
||||||
|
valueY=LiteralValue.optimalInteger(0, callPosition)
|
||||||
|
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
|
||||||
|
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
|
||||||
|
assignX.linkParents(subroutine.parent)
|
||||||
|
assignY.linkParents(subroutine.parent)
|
||||||
|
translate(assignX)
|
||||||
|
translate(assignY)
|
||||||
|
} else if(paramDt==DataType.UWORD) {
|
||||||
|
translate(arg.first)
|
||||||
|
prog.instr(Opcode.POP_REGXY_WORD)
|
||||||
|
} else
|
||||||
|
throw CompilerException("don't know how to pass register parameter of type $paramDt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// carry is set last, to avoid clobbering it when loading the other parameters
|
||||||
|
when(carryParam) {
|
||||||
|
true -> prog.instr(Opcode.SEC)
|
||||||
|
false -> prog.instr(Opcode.CLC)
|
||||||
|
}
|
||||||
|
|
||||||
if(subroutine.asmReturnvaluesRegisters.isNotEmpty()) {
|
|
||||||
TODO("call asmsub by loading registers instead")
|
|
||||||
} else {
|
} else {
|
||||||
prog.line(callPosition)
|
// only regular (non-register) arguments
|
||||||
for (arg in arguments.zip(subroutine.parameters)) {
|
for (arg in arguments.zip(subroutine.parameters)) {
|
||||||
translate(arg.first)
|
translate(arg.first)
|
||||||
val opcode = opcodePopvar(arg.second.type)
|
val opcode = opcodePopvar(arg.second.type)
|
||||||
@ -1195,22 +1295,22 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
if(registerOrStatus.statusflag!=null)
|
if(registerOrStatus.statusflag!=null)
|
||||||
return
|
return
|
||||||
when(registerOrStatus.registerOrPair){
|
when(registerOrStatus.registerOrPair){
|
||||||
RegisterOrPair.A -> {
|
A -> {
|
||||||
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.A, target.position), target.position)
|
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.A, target.position), target.position)
|
||||||
assignment.linkParents(parent)
|
assignment.linkParents(parent)
|
||||||
translate(assignment)
|
translate(assignment)
|
||||||
}
|
}
|
||||||
RegisterOrPair.X -> {
|
X -> {
|
||||||
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.X, target.position), target.position)
|
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.X, target.position), target.position)
|
||||||
assignment.linkParents(parent)
|
assignment.linkParents(parent)
|
||||||
translate(assignment)
|
translate(assignment)
|
||||||
}
|
}
|
||||||
RegisterOrPair.Y -> {
|
Y -> {
|
||||||
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.Y, target.position), target.position)
|
val assignment = Assignment(listOf(target), null, RegisterExpr(Register.Y, target.position), target.position)
|
||||||
assignment.linkParents(parent)
|
assignment.linkParents(parent)
|
||||||
translate(assignment)
|
translate(assignment)
|
||||||
}
|
}
|
||||||
RegisterOrPair.AX -> {
|
AX -> {
|
||||||
// deal with register pair AX: target = A + X*256
|
// deal with register pair AX: target = A + X*256
|
||||||
val targetDt = target.determineDatatype(namespace, heap, parent)
|
val targetDt = target.determineDatatype(namespace, heap, parent)
|
||||||
if(targetDt!=DataType.UWORD)
|
if(targetDt!=DataType.UWORD)
|
||||||
@ -1218,7 +1318,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
prog.instr(Opcode.PUSH_REGAX_WORD)
|
prog.instr(Opcode.PUSH_REGAX_WORD)
|
||||||
popValueIntoTarget(target, targetDt)
|
popValueIntoTarget(target, targetDt)
|
||||||
}
|
}
|
||||||
RegisterOrPair.AY -> {
|
AY -> {
|
||||||
// deal with register pair AY: target = A + Y*256
|
// deal with register pair AY: target = A + Y*256
|
||||||
val targetDt = target.determineDatatype(namespace, heap, parent)
|
val targetDt = target.determineDatatype(namespace, heap, parent)
|
||||||
if(targetDt!=DataType.UWORD)
|
if(targetDt!=DataType.UWORD)
|
||||||
@ -1226,7 +1326,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
|||||||
prog.instr(Opcode.PUSH_REGAY_WORD)
|
prog.instr(Opcode.PUSH_REGAY_WORD)
|
||||||
popValueIntoTarget(target, targetDt)
|
popValueIntoTarget(target, targetDt)
|
||||||
}
|
}
|
||||||
RegisterOrPair.XY -> {
|
XY -> {
|
||||||
// deal with register pair XY: target = X + Y*256
|
// deal with register pair XY: target = X + Y*256
|
||||||
val targetDt = target.determineDatatype(namespace, heap, parent)
|
val targetDt = target.determineDatatype(namespace, heap, parent)
|
||||||
if(targetDt!=DataType.UWORD)
|
if(targetDt!=DataType.UWORD)
|
||||||
|
@ -28,6 +28,9 @@ enum class Opcode {
|
|||||||
POP_VAR_BYTE, // pop (u)byte value into variable
|
POP_VAR_BYTE, // pop (u)byte value into variable
|
||||||
POP_VAR_WORD, // pop (u)word value into variable
|
POP_VAR_WORD, // pop (u)word value into variable
|
||||||
POP_VAR_FLOAT, // pop float value into variable
|
POP_VAR_FLOAT, // pop float value into variable
|
||||||
|
POP_REGAX_WORD, // pop uword from stack into A/X registers
|
||||||
|
POP_REGAY_WORD, // pop uword from stack into A/Y registers
|
||||||
|
POP_REGXY_WORD, // pop uword from stack into X/Y registers
|
||||||
|
|
||||||
// numeric arithmetic
|
// numeric arithmetic
|
||||||
ADD_UB,
|
ADD_UB,
|
||||||
|
@ -462,6 +462,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
Opcode.PUSH_REGAY_WORD -> {
|
Opcode.PUSH_REGAY_WORD -> {
|
||||||
" sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex "
|
" sta ${ESTACK_LO.toHex()},x | tya | sta ${ESTACK_HI.toHex()},x | dex "
|
||||||
}
|
}
|
||||||
|
Opcode.POP_REGAX_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself")
|
||||||
|
Opcode.POP_REGXY_WORD -> throw AssemblyError("cannot load X register from stack because it's used as the stack pointer itself")
|
||||||
|
Opcode.POP_REGAY_WORD -> {
|
||||||
|
" inx | lda ${ESTACK_LO.toHex()},x | ldy ${ESTACK_HI.toHex()},x "
|
||||||
|
}
|
||||||
|
|
||||||
Opcode.READ_INDEXED_VAR_BYTE -> { // @todo is this correct?
|
Opcode.READ_INDEXED_VAR_BYTE -> { // @todo is this correct?
|
||||||
"""
|
"""
|
||||||
@ -2440,13 +2445,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
|
|
||||||
|
|
||||||
// ---------- some special operations ------------------
|
// ---------- some special operations ------------------
|
||||||
// var word = AY register pair
|
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
|
||||||
"""
|
|
||||||
sta ${segment[1].callLabel}
|
|
||||||
sty ${segment[1].callLabel}+1
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
// var word = AX register pair
|
// var word = AX register pair
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
"""
|
"""
|
||||||
@ -2454,6 +2452,13 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
stx ${segment[1].callLabel}+1
|
stx ${segment[1].callLabel}+1
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
|
// var word = AY register pair
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
sta ${segment[1].callLabel}
|
||||||
|
sty ${segment[1].callLabel}+1
|
||||||
|
"""
|
||||||
|
},
|
||||||
// var word = XY register pair
|
// var word = XY register pair
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
"""
|
"""
|
||||||
@ -2461,13 +2466,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
sty ${segment[1].callLabel}+1
|
sty ${segment[1].callLabel}+1
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
// mem word = AY register pair
|
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
|
||||||
"""
|
|
||||||
sta ${hexVal(segment[1])}
|
|
||||||
sty ${hexValPlusOne(segment[1])}
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
// mem word = AX register pair
|
// mem word = AX register pair
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_REGAX_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
||||||
"""
|
"""
|
||||||
@ -2475,16 +2473,70 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
stx ${hexValPlusOne(segment[1])}
|
stx ${hexValPlusOne(segment[1])}
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
|
// mem word = AY register pair
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_REGAY_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
sta ${hexVal(segment[1])}
|
||||||
|
sty ${hexValPlusOne(segment[1])}
|
||||||
|
"""
|
||||||
|
},
|
||||||
// mem word = XY register pair
|
// mem word = XY register pair
|
||||||
AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_REGXY_WORD, Opcode.POP_MEM_WORD)) { segment ->
|
||||||
"""
|
"""
|
||||||
stx ${hexVal(segment[1])}
|
stx ${hexVal(segment[1])}
|
||||||
sty ${hexValPlusOne(segment[1])}
|
sty ${hexValPlusOne(segment[1])}
|
||||||
"""
|
"""
|
||||||
|
},
|
||||||
|
|
||||||
|
// AX register pair = word value
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAX_WORD)) { segment ->
|
||||||
|
val value = hexVal(segment[0])
|
||||||
|
" lda #<$value | ldx #>$value"
|
||||||
|
},
|
||||||
|
// AY register pair = word value
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGAY_WORD)) { segment ->
|
||||||
|
val value = hexVal(segment[0])
|
||||||
|
" lda #<$value | ldy #>$value"
|
||||||
|
},
|
||||||
|
// XY register pair = word value
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_REGXY_WORD)) { segment ->
|
||||||
|
val value = hexVal(segment[0])
|
||||||
|
" ldx #<$value | ldy #>$value"
|
||||||
|
},
|
||||||
|
// AX register pair = word var
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAX_WORD)) { segment ->
|
||||||
|
" lda #<${segment[0].callLabel} | ldx #>${segment[0].callLabel}"
|
||||||
|
},
|
||||||
|
// AY register pair = word var
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGAY_WORD)) { segment ->
|
||||||
|
" lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel}"
|
||||||
|
},
|
||||||
|
// XY register pair = word var
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_REGXY_WORD)) { segment ->
|
||||||
|
" ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel}"
|
||||||
|
},
|
||||||
|
// AX register pair = mem word
|
||||||
|
AsmPattern(
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAX_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAX_WORD)) { segment ->
|
||||||
|
" lda ${hexVal(segment[0])} | ldx ${hexValPlusOne(segment[0])}"
|
||||||
|
},
|
||||||
|
// AY register pair = mem word
|
||||||
|
AsmPattern(
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGAY_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGAY_WORD)) { segment ->
|
||||||
|
" lda ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}"
|
||||||
|
},
|
||||||
|
// XY register pair = mem word
|
||||||
|
AsmPattern(
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.POP_REGXY_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_W, Opcode.POP_REGXY_WORD)) { segment ->
|
||||||
|
" ldx ${hexVal(segment[0])} | ldy ${hexValPlusOne(segment[0])}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// // @todo assignment: floatarray[idxbyte] = float
|
// // @todo assignment: floatarray[idxbyte] = float
|
||||||
// AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment ->
|
// AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment ->
|
||||||
// val floatConst = getFloatConst(segment[0].arg!!)
|
// val floatConst = getFloatConst(segment[0].arg!!)
|
||||||
|
@ -777,6 +777,21 @@ class StackVm(private var traceOutputFile: String?) {
|
|||||||
val y=variables["Y"]!!.integerValue()
|
val y=variables["Y"]!!.integerValue()
|
||||||
evalstack.push(Value(DataType.UWORD, y*256+x))
|
evalstack.push(Value(DataType.UWORD, y*256+x))
|
||||||
}
|
}
|
||||||
|
Opcode.POP_REGAX_WORD -> {
|
||||||
|
val value=evalstack.pop().integerValue()
|
||||||
|
variables["A"] = Value(DataType.UBYTE, value and 255)
|
||||||
|
variables["X"] = Value(DataType.UBYTE, value shr 8)
|
||||||
|
}
|
||||||
|
Opcode.POP_REGAY_WORD -> {
|
||||||
|
val value=evalstack.pop().integerValue()
|
||||||
|
variables["A"] = Value(DataType.UBYTE, value and 255)
|
||||||
|
variables["Y"] = Value(DataType.UBYTE, value shr 8)
|
||||||
|
}
|
||||||
|
Opcode.POP_REGXY_WORD -> {
|
||||||
|
val value=evalstack.pop().integerValue()
|
||||||
|
variables["X"] = Value(DataType.UBYTE, value and 255)
|
||||||
|
variables["Y"] = Value(DataType.UBYTE, value shr 8)
|
||||||
|
}
|
||||||
Opcode.POP_VAR_BYTE -> {
|
Opcode.POP_VAR_BYTE -> {
|
||||||
val value = evalstack.pop()
|
val value = evalstack.pop()
|
||||||
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
checkDt(value, DataType.UBYTE, DataType.BYTE)
|
||||||
|
Loading…
Reference in New Issue
Block a user