mirror of
https://github.com/irmen/prog8.git
synced 2024-07-01 09:29:29 +00:00
more asm output
This commit is contained in:
parent
595bf7ad4b
commit
5203dad7c1
|
@ -45,6 +45,46 @@ sub start() {
|
||||||
memory float mfloat = $c006
|
memory float mfloat = $c006
|
||||||
memory float mfloat2 = $d006
|
memory float mfloat2 = $d006
|
||||||
|
|
||||||
|
;label:
|
||||||
|
;
|
||||||
|
; while A>99 {
|
||||||
|
; X=22
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; repeat {
|
||||||
|
; X=22
|
||||||
|
; } until A>99
|
||||||
|
;
|
||||||
|
; for X in 0 to 99 {
|
||||||
|
; Y=33
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; for ubyte derp in 2 to 44 {
|
||||||
|
; X=44
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; if A<22 goto label
|
||||||
|
;
|
||||||
|
; if X<22 {
|
||||||
|
; A=99
|
||||||
|
; } else {
|
||||||
|
; Y=42
|
||||||
|
; }
|
||||||
|
|
||||||
|
Y=42
|
||||||
|
AY=42
|
||||||
|
AY=42555
|
||||||
|
Y = ub
|
||||||
|
AY= ub
|
||||||
|
AY= uw
|
||||||
|
|
||||||
|
Y = mubyte
|
||||||
|
AY = mubyte
|
||||||
|
AY = muword
|
||||||
|
|
||||||
|
Y = ubarr1[2]
|
||||||
|
AY = ubarr1[2]
|
||||||
|
AY = uwarr1[2]
|
||||||
|
|
||||||
barr1[2]=42
|
barr1[2]=42
|
||||||
ubarr1[2]=42
|
ubarr1[2]=42
|
||||||
|
@ -52,6 +92,10 @@ sub start() {
|
||||||
uwarr1[2]=42555
|
uwarr1[2]=42555
|
||||||
farr1[2]=42.5678
|
farr1[2]=42.5678
|
||||||
|
|
||||||
|
ubarr1[2]=X
|
||||||
|
uwarr1[2]=XY
|
||||||
|
; farr1[2]=XY ; @todo
|
||||||
|
|
||||||
barr1[2] = b
|
barr1[2] = b
|
||||||
ubarr1[2] = ub
|
ubarr1[2] = ub
|
||||||
warr1[2] = w
|
warr1[2] = w
|
||||||
|
@ -68,62 +112,88 @@ sub start() {
|
||||||
ub = ubarr1[2]
|
ub = ubarr1[2]
|
||||||
w = warr1[2]
|
w = warr1[2]
|
||||||
uw = uwarr1[2]
|
uw = uwarr1[2]
|
||||||
fl1 = farr1[2]
|
; fl1 = farr1[2] ; @todo
|
||||||
|
|
||||||
mbyte= barr1[2]
|
mbyte= barr1[2]
|
||||||
mubyte = ubarr1[2]
|
mubyte = ubarr1[2]
|
||||||
mword = warr1[2]
|
mword = warr1[2]
|
||||||
muword = uwarr1[2]
|
muword = uwarr1[2]
|
||||||
mfloat = farr1[2]
|
; mfloat = farr1[2] ; @todo
|
||||||
|
|
||||||
barr1[2] = barr2[3]
|
barr1[2] = barr2[3]
|
||||||
ubarr1[2] = ubarr2[3]
|
ubarr1[2] = ubarr2[3]
|
||||||
warr1[2] = warr2[3]
|
warr1[2] = warr2[3]
|
||||||
uwarr1[2] = uwarr2[3]
|
uwarr1[2] = uwarr2[3]
|
||||||
farr1[2] = farr2[3]
|
; farr1[2] = farr2[3] ; @todo
|
||||||
|
|
||||||
|
|
||||||
|
XY[2]=42
|
||||||
|
XY[2] = ub
|
||||||
|
XY[2] = mubyte
|
||||||
|
ub = XY[2]
|
||||||
|
uw = XY[2]
|
||||||
|
;fl1 = XY[2] ; @todo
|
||||||
|
mubyte = XY[2]
|
||||||
|
muword = XY[2]
|
||||||
|
;mfloat = XY[2] ; @todo
|
||||||
|
XY[2] = AY[3] ; @todo wat is de output hiervan???
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; b = 1
|
b = 1
|
||||||
; ub = 1
|
ub = 1
|
||||||
; w = 1
|
w = 1
|
||||||
; uw = 1
|
uw = 1
|
||||||
; fl1 = 2.345
|
fl1 = 2.345
|
||||||
;
|
|
||||||
; b = b2
|
b = b2
|
||||||
; ub = pixely
|
ub = pixely
|
||||||
; w = w2
|
w = b2
|
||||||
; uw = uw2
|
w = w2
|
||||||
; fl1 = fl2
|
w = ub
|
||||||
;
|
uw = ub
|
||||||
; b = mbyte
|
uw = uw2
|
||||||
; ub = mubyte
|
;fl1 = ub ; @todo
|
||||||
; w = mword
|
;fl1 = b2 ; @todo
|
||||||
; uw = muword
|
;fl1 = uw2 ; @todo
|
||||||
; fl1 = mfloat
|
;fl1 = w2 ; @todo
|
||||||
;
|
fl1 = fl2
|
||||||
; mbyte = 1
|
|
||||||
; mubyte = 1
|
b = mbyte
|
||||||
; mword = 1
|
ub = mubyte
|
||||||
; muword = 1
|
w = mword
|
||||||
; mfloat = 3.456
|
w = mbyte
|
||||||
|
w = mubyte
|
||||||
|
uw = mubyte
|
||||||
|
uw = muword
|
||||||
|
fl1 = mfloat
|
||||||
|
;fl1 = mbyte ; @todo
|
||||||
|
;fl1 = mword ; @todo
|
||||||
|
;fl1 = mubyte ; @todo
|
||||||
|
;fl1 = muword ; @todo
|
||||||
|
|
||||||
|
mbyte = 1
|
||||||
|
mubyte = 1
|
||||||
|
mword = 1
|
||||||
|
muword = 1
|
||||||
|
mfloat = 3.456
|
||||||
|
|
||||||
|
%breakpoint
|
||||||
|
|
||||||
|
mbyte = b
|
||||||
|
mubyte = ub
|
||||||
|
mword = w
|
||||||
|
muword = uw
|
||||||
|
mfloat = fl2
|
||||||
|
|
||||||
|
%breakpoint
|
||||||
|
|
||||||
|
mbyte = mbyte2
|
||||||
|
mubyte = mubyte2
|
||||||
|
mword = mword2
|
||||||
|
muword = muword2
|
||||||
|
mfloat = mfloat2
|
||||||
|
|
||||||
; %breakpoint
|
|
||||||
;
|
|
||||||
; mbyte = b
|
|
||||||
; mubyte = ub
|
|
||||||
; mword = w
|
|
||||||
; muword = uw
|
|
||||||
; mfloat = fl2
|
|
||||||
;
|
|
||||||
; %breakpoint
|
|
||||||
;
|
|
||||||
; mbyte = mbyte2
|
|
||||||
; mubyte = mubyte2
|
|
||||||
; mword = mword2
|
|
||||||
; muword = muword2
|
|
||||||
; mfloat = mfloat2
|
|
||||||
;
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -931,7 +931,7 @@ class AstChecker(private val namespace: INameScope,
|
||||||
val result = when(targetDatatype) {
|
val result = when(targetDatatype) {
|
||||||
DataType.BYTE -> sourceDatatype==DataType.BYTE
|
DataType.BYTE -> sourceDatatype==DataType.BYTE
|
||||||
DataType.UBYTE -> sourceDatatype==DataType.UBYTE
|
DataType.UBYTE -> sourceDatatype==DataType.UBYTE
|
||||||
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD
|
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.WORD
|
||||||
DataType.UWORD -> sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.UWORD
|
DataType.UWORD -> sourceDatatype==DataType.UBYTE || sourceDatatype==DataType.UWORD
|
||||||
DataType.FLOAT -> sourceDatatype in NumericDatatypes
|
DataType.FLOAT -> sourceDatatype in NumericDatatypes
|
||||||
DataType.STR -> sourceDatatype==DataType.STR
|
DataType.STR -> sourceDatatype==DataType.STR
|
||||||
|
|
|
@ -120,18 +120,20 @@ class AstIdentifiersChecker : IAstProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun process(forLoop: ForLoop): IStatement {
|
override fun process(forLoop: ForLoop): IStatement {
|
||||||
// if the for loop as a decltype, it means to declare the loopvar inside the loop body
|
// if the for loop has a decltype, it means to declare the loopvar inside the loop body
|
||||||
// rather than reusing an already declared loopvar from an outer scope.
|
// rather than reusing an already declared loopvar from an outer scope.
|
||||||
if(forLoop.loopRegister!=null && forLoop.decltype!=null) {
|
if(forLoop.loopRegister!=null) {
|
||||||
checkResult.add(SyntaxError("register loop variables cannot be explicitly declared with a datatype", forLoop.position))
|
if(forLoop.decltype!=null)
|
||||||
} else {
|
checkResult.add(SyntaxError("register loop variables cannot be explicitly declared with a datatype", forLoop.position))
|
||||||
val loopVar = forLoop.loopVar!!
|
if(forLoop.loopRegister == Register.X || forLoop.loopRegister==Register.XY || forLoop.loopRegister==Register.AX)
|
||||||
val varName = loopVar.nameInSource.last()
|
checkResult.add(SyntaxError("it's not possible to write to the X register because it's used as an internal pointer", forLoop.position))
|
||||||
|
} else if(forLoop.loopVar!=null) {
|
||||||
|
val varName = forLoop.loopVar.nameInSource.last()
|
||||||
when (forLoop.decltype) {
|
when (forLoop.decltype) {
|
||||||
DataType.UBYTE, DataType.UWORD -> {
|
DataType.UBYTE, DataType.UWORD -> {
|
||||||
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(loopVar.nameInSource, forLoop.body.statements.first())
|
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
|
||||||
if(existing==null) {
|
if(existing==null) {
|
||||||
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, loopVar.position)
|
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, forLoop.loopVar.position)
|
||||||
vardecl.linkParents(forLoop.body)
|
vardecl.linkParents(forLoop.body)
|
||||||
forLoop.body.statements.add(0, vardecl)
|
forLoop.body.statements.add(0, vardecl)
|
||||||
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
||||||
|
@ -143,4 +145,10 @@ class AstIdentifiersChecker : IAstProcessor {
|
||||||
}
|
}
|
||||||
return super.process(forLoop)
|
return super.process(forLoop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun process(assignTarget: AssignTarget): AssignTarget {
|
||||||
|
if(assignTarget.register==Register.X || assignTarget.register==Register.AX || assignTarget.register==Register.XY)
|
||||||
|
checkResult.add(SyntaxError("it's not possible to write to the X register because it's used as an internal pointer", assignTarget.position))
|
||||||
|
return super.process(assignTarget)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,8 +440,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
BranchCondition.CC -> Opcode.BCS
|
BranchCondition.CC -> Opcode.BCS
|
||||||
BranchCondition.EQ, BranchCondition.Z -> Opcode.BNZ
|
BranchCondition.EQ, BranchCondition.Z -> Opcode.BNZ
|
||||||
BranchCondition.NE, BranchCondition.NZ -> Opcode.BZ
|
BranchCondition.NE, BranchCondition.NZ -> Opcode.BZ
|
||||||
BranchCondition.VS -> TODO("Opcode.BVC")
|
BranchCondition.VS -> Opcode.BVC
|
||||||
BranchCondition.VC -> TODO("Opcode.BVS")
|
BranchCondition.VC -> Opcode.BVS
|
||||||
BranchCondition.MI, BranchCondition.NEG -> Opcode.BPOS
|
BranchCondition.MI, BranchCondition.NEG -> Opcode.BPOS
|
||||||
BranchCondition.PL, BranchCondition.POS -> Opcode.BNEG
|
BranchCondition.PL, BranchCondition.POS -> Opcode.BNEG
|
||||||
}
|
}
|
||||||
|
@ -470,6 +470,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
* An IF statement: IF (condition-expression) { stuff } else { other_stuff }
|
* An IF statement: IF (condition-expression) { stuff } else { other_stuff }
|
||||||
* Which is translated into:
|
* Which is translated into:
|
||||||
* <condition-expression evaluation>
|
* <condition-expression evaluation>
|
||||||
|
* TEST
|
||||||
* BZ _stmt_999_else
|
* BZ _stmt_999_else
|
||||||
* stuff
|
* stuff
|
||||||
* JUMP _stmt_999_end
|
* JUMP _stmt_999_end
|
||||||
|
@ -480,6 +481,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
*
|
*
|
||||||
* or when there is no else block:
|
* or when there is no else block:
|
||||||
* <condition-expression evaluation>
|
* <condition-expression evaluation>
|
||||||
|
* TEST
|
||||||
* BZ _stmt_999_end
|
* BZ _stmt_999_end
|
||||||
* stuff
|
* stuff
|
||||||
* _stmt_999_end:
|
* _stmt_999_end:
|
||||||
|
@ -491,11 +493,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
translate(stmt.condition)
|
translate(stmt.condition)
|
||||||
val labelEnd = makeLabel("end")
|
val labelEnd = makeLabel("end")
|
||||||
if(stmt.elsepart.isEmpty()) {
|
if(stmt.elsepart.isEmpty()) {
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BZ, callLabel = labelEnd)
|
prog.instr(Opcode.BZ, callLabel = labelEnd)
|
||||||
translate(stmt.truepart)
|
translate(stmt.truepart)
|
||||||
prog.label(labelEnd)
|
prog.label(labelEnd)
|
||||||
} else {
|
} else {
|
||||||
val labelElse = makeLabel("else")
|
val labelElse = makeLabel("else")
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BZ, callLabel = labelElse)
|
prog.instr(Opcode.BZ, callLabel = labelElse)
|
||||||
translate(stmt.truepart)
|
translate(stmt.truepart)
|
||||||
prog.instr(Opcode.JUMP, callLabel = labelEnd)
|
prog.instr(Opcode.JUMP, callLabel = labelEnd)
|
||||||
|
@ -1473,6 +1477,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
prog.instr(opcodePush(zero.type), Value(zero.type, numElements))
|
prog.instr(opcodePush(zero.type), Value(zero.type, numElements))
|
||||||
prog.instr(opcodePushvar(zero.type), callLabel = indexVar)
|
prog.instr(opcodePushvar(zero.type), callLabel = indexVar)
|
||||||
prog.instr(opcodeSub(zero.type))
|
prog.instr(opcodeSub(zero.type))
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
||||||
|
|
||||||
prog.label(breakLabel)
|
prog.label(breakLabel)
|
||||||
|
@ -1535,6 +1540,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
prog.instr(opcodePush(varDt), Value(varDt, range.last + range.step))
|
prog.instr(opcodePush(varDt), Value(varDt, range.last + range.step))
|
||||||
prog.instr(opcodePushvar(varDt), callLabel = varname)
|
prog.instr(opcodePushvar(varDt), callLabel = varname)
|
||||||
prog.instr(opcodeSub(varDt))
|
prog.instr(opcodeSub(varDt))
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
||||||
|
|
||||||
prog.label(breakLabel)
|
prog.label(breakLabel)
|
||||||
|
@ -1692,6 +1698,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
* continue -> goto condition
|
* continue -> goto condition
|
||||||
* continue:
|
* continue:
|
||||||
* <evaluate condition>
|
* <evaluate condition>
|
||||||
|
* test
|
||||||
* bnz loop
|
* bnz loop
|
||||||
* break:
|
* break:
|
||||||
* nop
|
* nop
|
||||||
|
@ -1707,6 +1714,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
prog.label(continueLabel)
|
prog.label(continueLabel)
|
||||||
translate(stmt.condition)
|
translate(stmt.condition)
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
prog.instr(Opcode.BNZ, callLabel = loopLabel)
|
||||||
prog.label(breakLabel)
|
prog.label(breakLabel)
|
||||||
prog.instr(Opcode.NOP)
|
prog.instr(Opcode.NOP)
|
||||||
|
@ -1726,6 +1734,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
* continue -> goto condition
|
* continue -> goto condition
|
||||||
* condition:
|
* condition:
|
||||||
* <evaluate untilCondition>
|
* <evaluate untilCondition>
|
||||||
|
* test
|
||||||
* bz goto loop
|
* bz goto loop
|
||||||
* break:
|
* break:
|
||||||
* nop
|
* nop
|
||||||
|
@ -1740,6 +1749,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
prog.label(continueLabel)
|
prog.label(continueLabel)
|
||||||
translate(stmt.untilCondition)
|
translate(stmt.untilCondition)
|
||||||
|
prog.instr(Opcode.TEST)
|
||||||
prog.instr(Opcode.BZ, callLabel = loopLabel)
|
prog.instr(Opcode.BZ, callLabel = loopLabel)
|
||||||
prog.label(breakLabel)
|
prog.label(breakLabel)
|
||||||
prog.instr(Opcode.NOP)
|
prog.instr(Opcode.NOP)
|
||||||
|
|
|
@ -158,6 +158,8 @@ enum class Opcode {
|
||||||
DEC_VAR_F,
|
DEC_VAR_F,
|
||||||
|
|
||||||
// comparisons
|
// comparisons
|
||||||
|
// @todo the comparisons now push the result back on the stack. Optimize this to work with processor flags exclusively. This does mean you can no longer use a logical boolean result as a byte 0/1 value ?
|
||||||
|
TEST, // pop top value from stack and test it. Sets cpu flags (zero, negative, overflow) accordingly.
|
||||||
LESS_B,
|
LESS_B,
|
||||||
LESS_UB,
|
LESS_UB,
|
||||||
LESS_W,
|
LESS_W,
|
||||||
|
@ -193,16 +195,16 @@ enum class Opcode {
|
||||||
WRITE_INDEXED_VAR_WORD,
|
WRITE_INDEXED_VAR_WORD,
|
||||||
WRITE_INDEXED_VAR_FLOAT,
|
WRITE_INDEXED_VAR_FLOAT,
|
||||||
|
|
||||||
// branching
|
// branching, without consuming a value from the stack
|
||||||
JUMP,
|
JUMP,
|
||||||
BCS,
|
BCS, // branch if carry set
|
||||||
BCC,
|
BCC, // branch if carry clear
|
||||||
BZ, // branch if value on top of stack is zero
|
BZ, // branch if zero flag
|
||||||
BNZ, // branch if value on top of stack is not zero
|
BNZ, // branch if not zero flag
|
||||||
BNEG, // branch if value on top of stack < 0
|
BNEG, // branch if negative flag
|
||||||
BPOS, // branch if value on top of stack >= 0
|
BPOS, // branch if not negative flag
|
||||||
// BVS, // status flag V (overflow) not implemented
|
BVS, // branch if overflow flag
|
||||||
// BVC, // status flag V (overflow) not implemented
|
BVC, // branch if not overflow flag
|
||||||
|
|
||||||
// subroutine calling
|
// subroutine calling
|
||||||
CALL,
|
CALL,
|
||||||
|
|
|
@ -400,50 +400,50 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
"_prog8_breakpoint_$breakpointCounter\tnop"
|
"_prog8_breakpoint_$breakpointCounter\tnop"
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode.PUSH_BYTE -> {
|
// Opcode.PUSH_BYTE -> {
|
||||||
" lda #${ins.arg!!.integerValue().toHex()} | sta ${ESTACK_LO.toHex()},x | dex"
|
// " lda #${ins.arg!!.integerValue().toHex()} | sta ${ESTACK_LO.toHex()},x | dex"
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_WORD -> {
|
// Opcode.PUSH_WORD -> {
|
||||||
val value = ins.arg!!.integerValue().toHex()
|
// val value = ins.arg!!.integerValue().toHex()
|
||||||
" lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex"
|
// " lda #<$value | sta ${ESTACK_LO.toHex()},x | lda #>$value | sta ${ESTACK_HI.toHex()},x | dex"
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_FLOAT -> {
|
// Opcode.PUSH_FLOAT -> {
|
||||||
val floatConst = getFloatConst(ins.arg!!)
|
// val floatConst = getFloatConst(ins.arg!!)
|
||||||
" lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float"
|
// " lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float"
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_VAR_BYTE -> {
|
// Opcode.PUSH_VAR_BYTE -> {
|
||||||
when(ins.callLabel) {
|
// when(ins.callLabel) {
|
||||||
"X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
// "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
||||||
"A" -> " sta ${ESTACK_LO.toHex()},x | dex"
|
// "A" -> " sta ${ESTACK_LO.toHex()},x | dex"
|
||||||
"Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
|
// "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
|
||||||
else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
|
// else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_VAR_WORD -> {
|
// Opcode.PUSH_VAR_WORD -> {
|
||||||
when (ins.callLabel) {
|
// when (ins.callLabel) {
|
||||||
"AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
// "AX" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
||||||
"XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
// "XY" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
||||||
"AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
|
// "AY" -> " sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
|
||||||
else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
|
// else -> " lda ${ins.callLabel} | ldy ${ins.callLabel}+1 | sta ${ESTACK_LO.toHex()},x | pha | tya | sta ${ESTACK_HI.toHex()},x | pla | dex"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
|
// Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
|
||||||
Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
|
// Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
|
||||||
"""
|
// """
|
||||||
lda ${ins.arg!!.integerValue().toHex()}
|
// lda ${ins.arg!!.integerValue().toHex()}
|
||||||
sta ${ESTACK_LO.toHex()},x
|
// sta ${ESTACK_LO.toHex()},x
|
||||||
dex
|
// dex
|
||||||
"""
|
// """
|
||||||
}
|
// }
|
||||||
Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
|
// Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
|
||||||
"""
|
// """
|
||||||
lda ${ins.arg!!.integerValue().toHex()}
|
// lda ${ins.arg!!.integerValue().toHex()}
|
||||||
sta ${ESTACK_LO.toHex()},x
|
// sta ${ESTACK_LO.toHex()},x
|
||||||
lda ${(ins.arg.integerValue()+1).toHex()}
|
// lda ${(ins.arg.integerValue()+1).toHex()}
|
||||||
sta ${ESTACK_HI.toHex()},x
|
// sta ${ESTACK_HI.toHex()},x
|
||||||
dex
|
// dex
|
||||||
"""
|
// """
|
||||||
}
|
// }
|
||||||
|
|
||||||
Opcode.POP_MEM_B, Opcode.POP_MEM_UB -> {
|
Opcode.POP_MEM_B, Opcode.POP_MEM_UB -> {
|
||||||
"""
|
"""
|
||||||
|
@ -678,10 +678,12 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
|
|
||||||
Opcode.BCS -> " bcs ${ins.callLabel}"
|
Opcode.BCS -> " bcs ${ins.callLabel}"
|
||||||
Opcode.BCC -> " bcc ${ins.callLabel}"
|
Opcode.BCC -> " bcc ${ins.callLabel}"
|
||||||
Opcode.BZ -> " beq ${ins.callLabel}"
|
|
||||||
Opcode.BNZ -> " bne ${ins.callLabel}"
|
|
||||||
Opcode.BNEG -> " bmi ${ins.callLabel}"
|
Opcode.BNEG -> " bmi ${ins.callLabel}"
|
||||||
Opcode.BPOS -> " bpl ${ins.callLabel}"
|
Opcode.BPOS -> " bpl ${ins.callLabel}"
|
||||||
|
Opcode.BVC -> " bvc ${ins.callLabel}"
|
||||||
|
Opcode.BVS -> " bvs ${ins.callLabel}"
|
||||||
|
Opcode.BZ -> " beq ${ins.callLabel}"
|
||||||
|
Opcode.BNZ -> " bne ${ins.callLabel}"
|
||||||
Opcode.UB2FLOAT -> " jsr prog8_lib.ub2float"
|
Opcode.UB2FLOAT -> " jsr prog8_lib.ub2float"
|
||||||
Opcode.B2FLOAT -> " jsr prog8_lib.b2float"
|
Opcode.B2FLOAT -> " jsr prog8_lib.b2float"
|
||||||
Opcode.UW2FLOAT -> " jsr prog8_lib.uw2float"
|
Opcode.UW2FLOAT -> " jsr prog8_lib.uw2float"
|
||||||
|
@ -1035,10 +1037,16 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
|
|
||||||
// assignment: mem = bytevar/ubytevar
|
// assignment: mem = bytevar/ubytevar
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_B)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_B)) { segment ->
|
||||||
" lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
when(segment[0].callLabel) {
|
||||||
|
"A", "X", "Y" -> TODO("$segment")
|
||||||
|
else -> " lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_UB)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_UB)) { segment ->
|
||||||
" lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
when(segment[0].callLabel) {
|
||||||
|
"A", "X", "Y" -> TODO("$segment")
|
||||||
|
else -> " lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// assignment: mem = byte/ubyte
|
// assignment: mem = byte/ubyte
|
||||||
|
@ -1051,10 +1059,16 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
|
|
||||||
// assignment: (u)bytevar = membyte
|
// assignment: (u)bytevar = membyte
|
||||||
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE)) { segment ->
|
||||||
" lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
when(segment[1].callLabel) {
|
||||||
|
"A", "X", "Y" -> " ld${segment[1].callLabel!!.toLowerCase()} ${segment[0].arg!!.integerValue().toHex()}"
|
||||||
|
else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment ->
|
||||||
" lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
when(segment[1].callLabel) {
|
||||||
|
"A", "X", "Y" -> " ld${segment[1].callLabel!!.toLowerCase()} ${segment[0].arg!!.integerValue().toHex()}"
|
||||||
|
else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -1077,20 +1091,32 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
|
|
||||||
// assignment: mem = wordvar/uwordvar
|
// assignment: mem = wordvar/uwordvar
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_W)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_W)) { segment ->
|
||||||
"""
|
when(segment[0].callLabel) {
|
||||||
lda ${segment[0].callLabel}
|
"AX" -> TODO("$segment")
|
||||||
sta ${segment[1].arg!!.integerValue().toHex()}
|
"AY" -> TODO("$segment")
|
||||||
lda ${segment[0].callLabel}+1
|
"XY" -> TODO("$segment")
|
||||||
sta ${(segment[1].arg!!.integerValue()+1).toHex()}
|
else ->
|
||||||
"""
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
sta ${segment[1].arg!!.integerValue().toHex()}
|
||||||
|
lda ${segment[0].callLabel}+1
|
||||||
|
sta ${(segment[1].arg!!.integerValue()+1).toHex()}
|
||||||
|
"""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_UW)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_UW)) { segment ->
|
||||||
"""
|
when(segment[0].callLabel) {
|
||||||
lda ${segment[0].callLabel}
|
"AX" -> TODO("$segment")
|
||||||
sta ${segment[1].arg!!.integerValue().toHex()}
|
"AY" -> TODO("$segment")
|
||||||
lda ${segment[0].callLabel}+1
|
"XY" -> TODO("$segment")
|
||||||
sta ${(segment[1].arg!!.integerValue()+1).toHex()}
|
else ->
|
||||||
"""
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
sta ${segment[1].arg!!.integerValue().toHex()}
|
||||||
|
lda ${segment[0].callLabel}+1
|
||||||
|
sta ${(segment[1].arg!!.integerValue()+1).toHex()}
|
||||||
|
"""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// assignment: mem = word/uword
|
// assignment: mem = word/uword
|
||||||
|
@ -1113,20 +1139,32 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
|
|
||||||
// assignment: (u)wordvar = memword
|
// assignment: (u)wordvar = memword
|
||||||
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
"""
|
when(segment[1].callLabel) {
|
||||||
lda ${segment[0].arg!!.integerValue().toHex()}
|
"AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
sta ${segment[1].callLabel}
|
"AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
|
"XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
sta ${segment[1].callLabel}+1
|
else ->
|
||||||
"""
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${segment[1].callLabel}
|
||||||
|
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
|
||||||
|
sta ${segment[1].callLabel}+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
"""
|
when(segment[1].callLabel) {
|
||||||
lda ${segment[0].arg!!.integerValue().toHex()}
|
"AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
sta ${segment[1].callLabel}
|
"AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
|
"XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy ${(segment[0].arg!!.integerValue()+1).toHex()}"
|
||||||
sta ${segment[1].callLabel}+1
|
else ->
|
||||||
"""
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${segment[1].callLabel}
|
||||||
|
lda ${(segment[0].arg!!.integerValue()+1).toHex()}
|
||||||
|
sta ${segment[1].callLabel}+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// assignment: var = float
|
// assignment: var = float
|
||||||
|
@ -1191,17 +1229,396 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||||
"""
|
"""
|
||||||
},
|
},
|
||||||
|
|
||||||
// @todo add all indexed assignment forms
|
// assignment: uwordvar = ubytevar
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
when(segment[0].callLabel) {
|
||||||
|
"A", "X", "Y" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " lda ${segment[0].callLabel} | ldx #0"
|
||||||
|
"AY" -> " lda ${segment[0].callLabel} | ldy #0"
|
||||||
|
"XY" -> " ldx ${segment[0].callLabel} | ldy #0"
|
||||||
|
else -> " lda ${segment[0].callLabel} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordvar = bytevar (sign extended)
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
when(segment[0].callLabel) {
|
||||||
|
"A", "X", "Y" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO(" $segment")
|
||||||
|
"AY" -> TODO(" $segment")
|
||||||
|
"XY" -> TODO(" $segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
sta ${segment[2].callLabel}
|
||||||
|
ora #$7f
|
||||||
|
bmi +
|
||||||
|
lda #0
|
||||||
|
+ sta ${segment[2].callLabel}+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordvar = membyte (sign extended)
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.B2WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${segment[2].callLabel}
|
||||||
|
ora #$7f
|
||||||
|
bmi +
|
||||||
|
lda #0
|
||||||
|
+ sta ${segment[2].callLabel}+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: uwordvar = mem ubyte
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldx #0"
|
||||||
|
"AY" -> " lda ${segment[0].arg!!.integerValue().toHex()} | ldy #0"
|
||||||
|
"XY" -> " ldx ${segment[0].arg!!.integerValue().toHex()} | ldy #0"
|
||||||
|
else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel} | lda #0 | sta ${segment[2].callLabel}+1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: uwordvar = ubytearray[index_byte]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[0].arg!!.integerValue().toHex()
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[3].callLabel) {
|
||||||
|
"AX" -> " lda ${segment[1].callLabel}+$index | ldx #0"
|
||||||
|
"AY" -> " lda ${segment[1].callLabel}+$index | ldy #0"
|
||||||
|
"XY" -> " ldx ${segment[1].callLabel}+$index | ldy #0"
|
||||||
|
else -> " lda ${segment[1].callLabel}+$index | sta ${segment[3].callLabel} | lda #0 | sta ${segment[3].callLabel}+1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: mem uword = ubytearray[index_byte]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.UB2UWORD, Opcode.POP_MEM_UW)) { segment ->
|
||||||
|
val index = segment[0].arg!!.integerValue().toHex()
|
||||||
|
"""
|
||||||
|
lda ${segment[1].callLabel}+$index
|
||||||
|
ldy ${segment[1].callLabel}+$index+1
|
||||||
|
sta ${segment[3].arg!!.integerValue().toHex()}
|
||||||
|
sty ${(segment[3].arg!!.integerValue()+1).toHex()}
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// assignment: (u)wordvar = (u)wordarray[index_byte]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[0].arg!!.integerValue()*2
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " lda ${segment[1].callLabel}+$index | ldx ${segment[1].callLabel}+$index+1"
|
||||||
|
"AY" -> " lda ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+$index+1"
|
||||||
|
"XY" -> " ldx ${segment[1].callLabel}+$index | ldy ${segment[1].callLabel}+$index+1"
|
||||||
|
else -> " lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel} | lda ${segment[1].callLabel}+$index+1,x | sta ${segment[2].callLabel}+1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// assignment: bytearray[idxbyte] = byte
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()
|
||||||
|
val value = segment[0].arg!!.integerValue().toHex()
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda #$value | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda #$value | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda #$value | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
else -> " lda #$value | sta ${segment[2].callLabel}+$index"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: bytearray[idxbyte] = bytevar
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()
|
||||||
|
val saveValue: String
|
||||||
|
val loadValue: String
|
||||||
|
when(segment[0].callLabel) {
|
||||||
|
"A" -> {
|
||||||
|
saveValue = ""
|
||||||
|
loadValue = ""
|
||||||
|
}
|
||||||
|
"X" -> {
|
||||||
|
saveValue = ""
|
||||||
|
loadValue = "txa"
|
||||||
|
}
|
||||||
|
"Y" -> {
|
||||||
|
saveValue = "sty ${C64Zeropage.SCRATCH_B1}"
|
||||||
|
loadValue = "lda ${C64Zeropage.SCRATCH_B1}"
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
saveValue = ""
|
||||||
|
loadValue = "lda ${segment[0].callLabel}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " $saveValue | sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | $loadValue | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"AY" -> " $saveValue | sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | $loadValue | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"XY" -> " $saveValue | stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | $loadValue | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
else -> " $loadValue | sta ${segment[2].callLabel}+$index"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: bytearray[idxbyte] = membyte
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${segment[2].callLabel}+$index
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: bytearray[idxbyte] = memubyte
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda ${segment[0].arg!!.integerValue().toHex()} | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda ${segment[0].arg!!.integerValue().toHex()} | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda ${segment[0].arg!!.integerValue().toHex()} | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
else -> " lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[2].callLabel}+$index"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordarray[idxbyte] = word
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()*2
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda #<${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
ldy #>${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${segment[2].callLabel}+$index
|
||||||
|
sty ${segment[2].callLabel}+$index+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordarray[idxbyte] = wordvar
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()*2
|
||||||
|
when(segment[0].callLabel) {
|
||||||
|
"AX" -> " sta ${segment[2].callLabel}+$index | stx ${segment[2].callLabel}+$index+1"
|
||||||
|
"AY" -> " sta ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+$index+1"
|
||||||
|
"XY" -> " stx ${segment[2].callLabel}+$index | sty ${segment[2].callLabel}+$index+1"
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
ldy ${segment[0].callLabel}+1
|
||||||
|
sta ${segment[2].callLabel}+$index
|
||||||
|
sty ${segment[2].callLabel}+$index+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordarray[idxbyte] = memword
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()*2
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
ldy ${segment[0].arg!!.integerValue().toHex()}+1
|
||||||
|
sta ${segment[2].callLabel}+$index
|
||||||
|
sty ${segment[2].callLabel}+$index+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordarray[idxbyte] = memuword (=same as above)
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue()*2
|
||||||
|
when(segment[2].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
ldy ${segment[0].arg!!.integerValue().toHex()}+1
|
||||||
|
sta ${segment[2].callLabel}+$index
|
||||||
|
sty ${segment[2].callLabel}+$index+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: floatarray[idxbyte] = float
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment ->
|
||||||
|
val floatConst = getFloatConst(segment[0].arg!!)
|
||||||
|
val index = segment[1].arg!!.integerValue() * Mflpt5.MemorySize
|
||||||
|
"""
|
||||||
|
lda #<$floatConst
|
||||||
|
ldy #>$floatConst
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||||
|
lda #<(${segment[2].callLabel}+$index)
|
||||||
|
ldy #>(${segment[2].callLabel}+$index+1)
|
||||||
|
sta ${C64Zeropage.SCRATCH_W2}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W2+1}
|
||||||
|
jsr prog8_lib.copy_float
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// assignment: floatarray[idxbyte] = floatvar
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue() * Mflpt5.MemorySize
|
||||||
|
"""
|
||||||
|
lda #<${segment[0].callLabel}
|
||||||
|
ldy #>${segment[0].callLabel}
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||||
|
lda #<(${segment[2].callLabel}+$index)
|
||||||
|
ldy #>(${segment[2].callLabel}+$index+1)
|
||||||
|
sta ${C64Zeropage.SCRATCH_W2}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W2+1}
|
||||||
|
jsr prog8_lib.copy_float
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// assignment: floatarray[idxbyte] = memfloat
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_FLOAT)) { segment ->
|
||||||
|
val index = segment[1].arg!!.integerValue() * Mflpt5.MemorySize
|
||||||
|
"""
|
||||||
|
lda #<${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
ldy #>${segment[0].arg!!.integerValue().toHex()}
|
||||||
|
sta ${C64Zeropage.SCRATCH_W1}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||||
|
lda #<(${segment[2].callLabel}+$index)
|
||||||
|
ldy #>(${segment[2].callLabel}+$index+1)
|
||||||
|
sta ${C64Zeropage.SCRATCH_W2}
|
||||||
|
sty ${C64Zeropage.SCRATCH_W2+1}
|
||||||
|
jsr prog8_lib.copy_float
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
|
||||||
// assignment: var = bytearray[index]
|
// assignment: var = bytearray[index]
|
||||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
|
||||||
val index = segment[0].arg!!.integerValue()
|
val index = segment[0].arg!!.integerValue()
|
||||||
when (segment[2].callLabel) {
|
when(segment[1].callLabel) {
|
||||||
"A", "X", "Y" ->
|
"AX" -> TODO("$segment")
|
||||||
" ld${segment[2].callLabel!!.toLowerCase()} ${segment[1].callLabel}+$index"
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
else ->
|
else ->
|
||||||
TODO("assign byte to array indexed")
|
when (segment[2].callLabel) {
|
||||||
|
"A", "X", "Y" ->
|
||||||
|
" ld${segment[2].callLabel!!.toLowerCase()} ${segment[1].callLabel}+$index"
|
||||||
|
else ->
|
||||||
|
" lda ${segment[1].callLabel}+$index | sta ${segment[2].callLabel}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// assignment: mem(u)byte = (u)bytearray[index]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_B)) { segment ->
|
||||||
|
val address = segment[2].arg!!.integerValue().toHex()
|
||||||
|
val index = segment[0].arg!!.integerValue()
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
"AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
"XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
else -> " lda ${segment[1].callLabel}+$index | sta $address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_MEM_UB)) { segment ->
|
||||||
|
val address = segment[2].arg!!.integerValue().toHex()
|
||||||
|
val index = segment[0].arg!!.integerValue()
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
"AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
"XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | ldy #$index | lda (${C64Zeropage.SCRATCH_W1}),y | sta $address"
|
||||||
|
else -> " lda ${segment[1].callLabel}+$index | sta $address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// assignment: mem(u)word = (u)wordarray[index]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_W)) { segment ->
|
||||||
|
val index = segment[0].arg!!.integerValue()*2
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[1].callLabel}+$index
|
||||||
|
ldy ${segment[1].callLabel}+1+$index
|
||||||
|
sta ${segment[2].arg!!.integerValue().toHex()}
|
||||||
|
sty ${(segment[2].arg!!.integerValue()+1).toHex()}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.POP_MEM_UW)) { segment ->
|
||||||
|
val index = segment[0].arg!!.integerValue()*2
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[1].callLabel}+$index
|
||||||
|
ldy ${segment[1].callLabel}+1+$index
|
||||||
|
sta ${segment[2].arg!!.integerValue().toHex()}
|
||||||
|
sty ${(segment[2].arg!!.integerValue()+1).toHex()}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// assignment: bytearray2[index2] = bytearray1[index1]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_BYTE)) { segment->
|
||||||
|
val index1 = segment[0].arg!!.integerValue()
|
||||||
|
val index2 = segment[2].arg!!.integerValue()
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[3].callLabel) {
|
||||||
|
"AX" -> " sta ${C64Zeropage.SCRATCH_W1} | stx ${C64Zeropage.SCRATCH_W1+1} | lda ${segment[1].callLabel}+$index1 | ldy #$index2 | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"AY" -> " sta ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | lda ${segment[1].callLabel}+$index1 | ldy #$index2 | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
"XY" -> " stx ${C64Zeropage.SCRATCH_W1} | sty ${C64Zeropage.SCRATCH_W1+1} | lda ${segment[1].callLabel}+$index1 | ldy #$index2 | sta (${C64Zeropage.SCRATCH_W1}),y"
|
||||||
|
else -> " lda ${segment[1].callLabel}+$index1 | sta ${segment[3].callLabel}+$index2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// assignment: wordarrayw[index2] = wordarray1[index1]
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_WORD, Opcode.PUSH_BYTE, Opcode.WRITE_INDEXED_VAR_WORD)) { segment->
|
||||||
|
val index1 = segment[0].arg!!.integerValue()*2
|
||||||
|
val index2 = segment[2].arg!!.integerValue()*2
|
||||||
|
when(segment[1].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
when(segment[3].callLabel) {
|
||||||
|
"AX" -> TODO("$segment")
|
||||||
|
"AY" -> TODO("$segment")
|
||||||
|
"XY" -> TODO("$segment")
|
||||||
|
else ->
|
||||||
|
"""
|
||||||
|
lda ${segment[1].callLabel}+$index1
|
||||||
|
ldy ${segment[1].callLabel}+$index1+1
|
||||||
|
sta ${segment[3].callLabel}+$index2
|
||||||
|
sty ${segment[3].callLabel}+$index2+1
|
||||||
|
"""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,9 @@ import prog8.functions.BuiltinFunctions
|
||||||
todo optimize addition with self into shift 1 (A+=A -> A<<=1)
|
todo optimize addition with self into shift 1 (A+=A -> A<<=1)
|
||||||
todo assignment optimization: optimize some simple multiplications and divisions into shifts (A*=2 -> lsl(A), X=X/2 -> lsr(X) )
|
todo assignment optimization: optimize some simple multiplications and divisions into shifts (A*=2 -> lsl(A), X=X/2 -> lsr(X) )
|
||||||
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
|
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
|
||||||
todo merge sequence of assignments into one (as long as the value is a constant and the target not a MEMORY type!)
|
todo merge sequence of assignments into one to avoid repeated value loads (as long as the value is a constant and the target not a MEMORY type!)
|
||||||
todo report more always true/always false conditions
|
todo report more always true/always false conditions
|
||||||
todo inline subroutines that are only called once
|
todo (optionally?) inline subroutines that are "sufficiently small" (=VERY small, say 0-3 statements, otherwise code size will explode and short branches will suffer)
|
||||||
todo inline subroutines that are "sufficiently small"
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class StatementOptimizer(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
class StatementOptimizer(private val namespace: INameScope, private val heap: HeapValues) : IAstProcessor {
|
||||||
|
|
|
@ -100,6 +100,10 @@ class StackVm(private var traceOutputFile: String?) {
|
||||||
val mem = Memory()
|
val mem = Memory()
|
||||||
var P_carry: Boolean = false
|
var P_carry: Boolean = false
|
||||||
private set
|
private set
|
||||||
|
var P_negative: Boolean = false
|
||||||
|
private set
|
||||||
|
var P_zero: Boolean = false
|
||||||
|
private set
|
||||||
var P_irqd: Boolean = false
|
var P_irqd: Boolean = false
|
||||||
private set
|
private set
|
||||||
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
|
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
|
||||||
|
@ -739,13 +743,18 @@ class StackVm(private var traceOutputFile: String?) {
|
||||||
Opcode.BCC ->
|
Opcode.BCC ->
|
||||||
return if(P_carry) ins.nextAlt!! else ins.next
|
return if(P_carry) ins.nextAlt!! else ins.next
|
||||||
Opcode.BZ ->
|
Opcode.BZ ->
|
||||||
return if(evalstack.pop().numericValue().toDouble()==0.0) ins.next else ins.nextAlt!!
|
return if(P_zero) ins.next else ins.nextAlt!!
|
||||||
Opcode.BNZ ->
|
Opcode.BNZ ->
|
||||||
return if(evalstack.pop().numericValue().toDouble()!=0.0) ins.next else ins.nextAlt!!
|
return if(P_zero) ins.nextAlt!! else ins.next
|
||||||
Opcode.BNEG ->
|
Opcode.BNEG ->
|
||||||
return if(evalstack.pop().numericValue().toDouble()<0.0) ins.next else ins.nextAlt!!
|
return if(P_negative) ins.next else ins.nextAlt!!
|
||||||
Opcode.BPOS -> {
|
Opcode.BPOS ->
|
||||||
return if (evalstack.pop().numericValue().toDouble() >= 0.0) ins.next else ins.nextAlt!!
|
return if(P_negative) ins.nextAlt!! else ins.next
|
||||||
|
Opcode.BVS, Opcode.BVC -> throw VmExecutionException("stackVM doesn't support the overflow flag")
|
||||||
|
Opcode.TEST -> {
|
||||||
|
val value=evalstack.pop().numericValue().toDouble()
|
||||||
|
P_zero = value == 0.0
|
||||||
|
P_negative = value < 0.0
|
||||||
}
|
}
|
||||||
Opcode.CALL ->
|
Opcode.CALL ->
|
||||||
callstack.push(ins.nextAlt)
|
callstack.push(ins.nextAlt)
|
||||||
|
@ -1329,6 +1338,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||||
Opcode.RSAVE -> {
|
Opcode.RSAVE -> {
|
||||||
evalstack.push(Value(DataType.UBYTE, if(P_irqd) 1 else 0))
|
evalstack.push(Value(DataType.UBYTE, if(P_irqd) 1 else 0))
|
||||||
evalstack.push(Value(DataType.UBYTE, if(P_carry) 1 else 0))
|
evalstack.push(Value(DataType.UBYTE, if(P_carry) 1 else 0))
|
||||||
|
evalstack.push(Value(DataType.UBYTE, if(P_negative) 1 else 0))
|
||||||
|
evalstack.push(Value(DataType.UBYTE, if(P_zero) 1 else 0))
|
||||||
evalstack.push(variables["X"])
|
evalstack.push(variables["X"])
|
||||||
evalstack.push(variables["Y"])
|
evalstack.push(variables["Y"])
|
||||||
evalstack.push(variables["A"])
|
evalstack.push(variables["A"])
|
||||||
|
@ -1337,6 +1348,8 @@ class StackVm(private var traceOutputFile: String?) {
|
||||||
variables["A"] = evalstack.pop()
|
variables["A"] = evalstack.pop()
|
||||||
variables["X"] = evalstack.pop()
|
variables["X"] = evalstack.pop()
|
||||||
variables["Y"] = evalstack.pop()
|
variables["Y"] = evalstack.pop()
|
||||||
|
P_zero = evalstack.pop().asBooleanValue
|
||||||
|
P_negative = evalstack.pop().asBooleanValue
|
||||||
P_carry = evalstack.pop().asBooleanValue
|
P_carry = evalstack.pop().asBooleanValue
|
||||||
P_irqd = evalstack.pop().asBooleanValue
|
P_irqd = evalstack.pop().asBooleanValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,8 @@ class TestStackVmOpcodes {
|
||||||
vm.load(makeProg(ins), null)
|
vm.load(makeProg(ins), null)
|
||||||
assertFalse(vm.P_carry)
|
assertFalse(vm.P_carry)
|
||||||
assertFalse(vm.P_irqd)
|
assertFalse(vm.P_irqd)
|
||||||
|
assertFalse(vm.P_negative)
|
||||||
|
assertFalse(vm.P_zero)
|
||||||
vm.step(1)
|
vm.step(1)
|
||||||
assertTrue(vm.P_carry)
|
assertTrue(vm.P_carry)
|
||||||
assertFalse(vm.P_irqd)
|
assertFalse(vm.P_irqd)
|
||||||
|
@ -862,17 +864,19 @@ class TestStackVmOpcodes {
|
||||||
fun testBZ() {
|
fun testBZ() {
|
||||||
val ins = mutableListOf(
|
val ins = mutableListOf(
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BZ, callLabel = "label"),
|
Instruction(Opcode.BZ, callLabel = "label"),
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BZ, callLabel = "label"),
|
Instruction(Opcode.BZ, callLabel = "label"),
|
||||||
Instruction(Opcode.LINE, callLabel = "string1"),
|
Instruction(Opcode.LINE, callLabel = "string1"),
|
||||||
Instruction(Opcode.TERMINATE),
|
Instruction(Opcode.TERMINATE),
|
||||||
Instruction(Opcode.LINE, callLabel = "string2"))
|
Instruction(Opcode.LINE, callLabel = "string2"))
|
||||||
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
||||||
vm.load(makeProg(ins, labels=labels), null)
|
vm.load(makeProg(ins, labels=labels), null)
|
||||||
vm.step(2)
|
|
||||||
assertEquals("", vm.sourceLine)
|
|
||||||
vm.step(3)
|
vm.step(3)
|
||||||
|
assertEquals("", vm.sourceLine)
|
||||||
|
vm.step(4)
|
||||||
assertEquals("string2", vm.sourceLine)
|
assertEquals("string2", vm.sourceLine)
|
||||||
assertEquals(0, vm.callstack.size)
|
assertEquals(0, vm.callstack.size)
|
||||||
assertEquals(0, vm.evalstack.size)
|
assertEquals(0, vm.evalstack.size)
|
||||||
|
@ -882,17 +886,19 @@ class TestStackVmOpcodes {
|
||||||
fun testBNZ() {
|
fun testBNZ() {
|
||||||
val ins = mutableListOf(
|
val ins = mutableListOf(
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BNZ, callLabel = "label"),
|
Instruction(Opcode.BNZ, callLabel = "label"),
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BNZ, callLabel = "label"),
|
Instruction(Opcode.BNZ, callLabel = "label"),
|
||||||
Instruction(Opcode.LINE, callLabel = "string1"),
|
Instruction(Opcode.LINE, callLabel = "string1"),
|
||||||
Instruction(Opcode.TERMINATE),
|
Instruction(Opcode.TERMINATE),
|
||||||
Instruction(Opcode.LINE, callLabel = "string2"))
|
Instruction(Opcode.LINE, callLabel = "string2"))
|
||||||
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
||||||
vm.load(makeProg(ins, labels=labels), null)
|
vm.load(makeProg(ins, labels=labels), null)
|
||||||
vm.step(2)
|
|
||||||
assertEquals("", vm.sourceLine)
|
|
||||||
vm.step(3)
|
vm.step(3)
|
||||||
|
assertEquals("", vm.sourceLine)
|
||||||
|
vm.step(4)
|
||||||
assertEquals("string2", vm.sourceLine)
|
assertEquals("string2", vm.sourceLine)
|
||||||
assertEquals(0, vm.callstack.size)
|
assertEquals(0, vm.callstack.size)
|
||||||
assertEquals(0, vm.evalstack.size)
|
assertEquals(0, vm.evalstack.size)
|
||||||
|
@ -902,21 +908,24 @@ class TestStackVmOpcodes {
|
||||||
fun testBNEG() {
|
fun testBNEG() {
|
||||||
val ins = mutableListOf(
|
val ins = mutableListOf(
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BNEG, callLabel = "label"),
|
Instruction(Opcode.BNEG, callLabel = "label"),
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 1)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BNEG, callLabel = "label"),
|
Instruction(Opcode.BNEG, callLabel = "label"),
|
||||||
Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, -99)),
|
Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, -99)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BNEG, callLabel = "label"),
|
Instruction(Opcode.BNEG, callLabel = "label"),
|
||||||
Instruction(Opcode.LINE, callLabel = "string1"),
|
Instruction(Opcode.LINE, callLabel = "string1"),
|
||||||
Instruction(Opcode.TERMINATE),
|
Instruction(Opcode.TERMINATE),
|
||||||
Instruction(Opcode.LINE, callLabel = "string2"))
|
Instruction(Opcode.LINE, callLabel = "string2"))
|
||||||
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
||||||
vm.load(makeProg(ins, labels=labels), null)
|
vm.load(makeProg(ins, labels=labels), null)
|
||||||
vm.step(2)
|
vm.step(3)
|
||||||
assertEquals("", vm.sourceLine)
|
|
||||||
vm.step(2)
|
|
||||||
assertEquals("", vm.sourceLine)
|
assertEquals("", vm.sourceLine)
|
||||||
vm.step(3)
|
vm.step(3)
|
||||||
|
assertEquals("", vm.sourceLine)
|
||||||
|
vm.step(4)
|
||||||
assertEquals("string2", vm.sourceLine)
|
assertEquals("string2", vm.sourceLine)
|
||||||
assertEquals(0, vm.callstack.size)
|
assertEquals(0, vm.callstack.size)
|
||||||
assertEquals(0, vm.evalstack.size)
|
assertEquals(0, vm.evalstack.size)
|
||||||
|
@ -926,17 +935,19 @@ class TestStackVmOpcodes {
|
||||||
fun testBPOS() {
|
fun testBPOS() {
|
||||||
val ins = mutableListOf(
|
val ins = mutableListOf(
|
||||||
Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, -99)),
|
Instruction(Opcode.PUSH_FLOAT, Value(DataType.FLOAT, -99)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BPOS, callLabel = "label"),
|
Instruction(Opcode.BPOS, callLabel = "label"),
|
||||||
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
Instruction(Opcode.PUSH_WORD, Value(DataType.UWORD, 0)),
|
||||||
|
Instruction(Opcode.TEST),
|
||||||
Instruction(Opcode.BPOS, callLabel = "label"),
|
Instruction(Opcode.BPOS, callLabel = "label"),
|
||||||
Instruction(Opcode.LINE, callLabel = "string1"),
|
Instruction(Opcode.LINE, callLabel = "string1"),
|
||||||
Instruction(Opcode.TERMINATE),
|
Instruction(Opcode.TERMINATE),
|
||||||
Instruction(Opcode.LINE, callLabel = "string2"))
|
Instruction(Opcode.LINE, callLabel = "string2"))
|
||||||
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
|
||||||
vm.load(makeProg(ins, labels=labels), null)
|
vm.load(makeProg(ins, labels=labels), null)
|
||||||
vm.step(2)
|
|
||||||
assertEquals("", vm.sourceLine)
|
|
||||||
vm.step(3)
|
vm.step(3)
|
||||||
|
assertEquals("", vm.sourceLine)
|
||||||
|
vm.step(4)
|
||||||
assertEquals("string2", vm.sourceLine)
|
assertEquals("string2", vm.sourceLine)
|
||||||
assertEquals(0, vm.callstack.size)
|
assertEquals(0, vm.callstack.size)
|
||||||
assertEquals(0, vm.evalstack.size)
|
assertEquals(0, vm.evalstack.size)
|
||||||
|
|
|
@ -29,6 +29,7 @@ ror2_word
|
||||||
|
|
||||||
|
|
||||||
; @todo: stubs for now
|
; @todo: stubs for now
|
||||||
|
; @todo: move float operations to their own library (only included when floats are enabled)
|
||||||
|
|
||||||
ub2float
|
ub2float
|
||||||
rts
|
rts
|
||||||
|
@ -63,6 +64,9 @@ sub_f
|
||||||
mul_f
|
mul_f
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
neg_f
|
||||||
|
rts
|
||||||
|
|
||||||
sub_uw
|
sub_uw
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -72,5 +76,73 @@ less_ub
|
||||||
less_f
|
less_f
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
func_sin
|
||||||
|
rts
|
||||||
|
func_cos
|
||||||
|
rts
|
||||||
|
func_abs
|
||||||
|
rts
|
||||||
|
func_acos
|
||||||
|
rts
|
||||||
|
func_asin
|
||||||
|
rts
|
||||||
|
func_tan
|
||||||
|
rts
|
||||||
|
func_atan
|
||||||
|
rts
|
||||||
|
func_ln
|
||||||
|
rts
|
||||||
|
func_log2
|
||||||
|
rts
|
||||||
|
func_log10
|
||||||
|
rts
|
||||||
|
func_sqrt
|
||||||
|
rts
|
||||||
|
func_rad
|
||||||
|
rts
|
||||||
|
func_deg
|
||||||
|
rts
|
||||||
|
func_round
|
||||||
|
rts
|
||||||
|
func_floor
|
||||||
|
rts
|
||||||
|
func_ceil
|
||||||
|
rts
|
||||||
|
func_max
|
||||||
|
rts
|
||||||
|
func_min
|
||||||
|
rts
|
||||||
|
func_avg
|
||||||
|
rts
|
||||||
|
func_sum
|
||||||
|
rts
|
||||||
|
func_len
|
||||||
|
rts
|
||||||
|
func_any
|
||||||
|
rts
|
||||||
|
func_all
|
||||||
|
rts
|
||||||
|
func_rnd
|
||||||
|
rts
|
||||||
|
func_rndw
|
||||||
|
rts
|
||||||
|
func_rndf
|
||||||
|
rts
|
||||||
|
func_wrd
|
||||||
|
rts
|
||||||
|
func_uwrd
|
||||||
|
rts
|
||||||
|
func_str2byte
|
||||||
|
rts
|
||||||
|
func_str2ubyte
|
||||||
|
rts
|
||||||
|
func_str2word
|
||||||
|
rts
|
||||||
|
func_str2uword
|
||||||
|
rts
|
||||||
|
func_str2float
|
||||||
|
rts
|
||||||
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user