mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
added DUP opcodes
This commit is contained in:
parent
70462ffe6d
commit
5ff79073f4
@ -931,7 +931,7 @@ internal class AstChecker(private val program: Program,
|
||||
if (constvalue == null)
|
||||
checkResult.add(SyntaxError("value of a when choice must be a constant", whenChoice.position))
|
||||
else if (constvalue.type !in IntegerDatatypes)
|
||||
checkResult.add(SyntaxError("value of a when choice must be an integer", whenChoice.position))
|
||||
checkResult.add(SyntaxError("value of a when choice must be a byte or word", whenChoice.position))
|
||||
} else {
|
||||
if(whenChoice !== (whenChoice.parent as WhenStatement).choices.last())
|
||||
checkResult.add(SyntaxError("else choice must be the last one", whenChoice.position))
|
||||
|
@ -110,6 +110,7 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
val variable = VarDecl(VarDeclType.VAR, strvalue.type, false, null, autoVarName, strvalue,
|
||||
isArray = false, autoGenerated = false, position = strvalue.position)
|
||||
addVarDecl(strvalue.definingScope(), variable)
|
||||
println("MADE ANONVAR $variable") // XXX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2083,26 +2083,55 @@ internal class Compiler(private val program: Program) {
|
||||
|
||||
private fun translate(whenstmt: WhenStatement) {
|
||||
val conditionDt = whenstmt.condition.inferType(program)
|
||||
if(conditionDt !in IntegerDatatypes)
|
||||
throw CompilerException("when condition must be integer")
|
||||
translate(whenstmt.condition)
|
||||
if(whenstmt.choices.isEmpty()) {
|
||||
when(conditionDt) {
|
||||
in ByteDatatypes -> prog.instr(Opcode.DISCARD_BYTE)
|
||||
in WordDatatypes -> prog.instr(Opcode.DISCARD_WORD)
|
||||
else -> throw CompilerException("when condition must be integer")
|
||||
}
|
||||
if (conditionDt in ByteDatatypes) prog.instr(Opcode.DISCARD_BYTE)
|
||||
else prog.instr(Opcode.DISCARD_WORD)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO compare
|
||||
val endOfWhenLabel = makeLabel(whenstmt, "when_end")
|
||||
|
||||
val choiceLabels = mutableListOf<String>()
|
||||
var previousValue = 0
|
||||
for(choice in whenstmt.choiceValues(program)) {
|
||||
if(choice.first==null) {
|
||||
val choiceVal = choice.first
|
||||
if(choiceVal==null) {
|
||||
// the else clause
|
||||
translate(choice.second.statements)
|
||||
} else {
|
||||
val subtract = choiceVal-previousValue
|
||||
previousValue = choiceVal
|
||||
if (conditionDt in ByteDatatypes) {
|
||||
prog.instr(Opcode.DUP_B)
|
||||
prog.instr(Opcode.PUSH_BYTE, RuntimeValue(conditionDt!!, subtract))
|
||||
prog.instr(opcodeCompare(conditionDt))
|
||||
}
|
||||
else {
|
||||
prog.instr(Opcode.DUP_W)
|
||||
prog.instr(Opcode.PUSH_WORD, RuntimeValue(conditionDt!!, subtract))
|
||||
prog.instr(opcodeCompare(conditionDt))
|
||||
}
|
||||
val choiceLabel = makeLabel(whenstmt, "choice_$choiceVal")
|
||||
choiceLabels.add(choiceLabel)
|
||||
prog.instr(Opcode.BZ, callLabel = choiceLabel)
|
||||
}
|
||||
}
|
||||
prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel)
|
||||
|
||||
TODO("whenstmt $whenstmt with choice values ${whenstmt.choiceValues(program).map{it.first}}")
|
||||
for(choice in whenstmt.choices.zip(choiceLabels)) {
|
||||
// TODO the various code blocks here, don't forget to jump to the end label at their eind
|
||||
prog.label(choice.second)
|
||||
prog.instr(Opcode.NOP)
|
||||
prog.instr(Opcode.JUMP, callLabel = endOfWhenLabel)
|
||||
}
|
||||
|
||||
prog.label(endOfWhenLabel)
|
||||
|
||||
if (conditionDt in ByteDatatypes) prog.instr(Opcode.DISCARD_BYTE)
|
||||
else prog.instr(Opcode.DISCARD_WORD)
|
||||
}
|
||||
|
||||
private fun translateAsmInclude(args: List<DirectiveArg>, source: Path) {
|
||||
|
@ -19,6 +19,8 @@ enum class Opcode {
|
||||
PUSH_REGAY_WORD, // push registers A/Y as a 16-bit word
|
||||
PUSH_REGXY_WORD, // push registers X/Y as a 16-bit word
|
||||
PUSH_ADDR_HEAPVAR, // push the address of the variable that's on the heap (string or array)
|
||||
DUP_B, // duplicate the top byte on the stack
|
||||
DUP_W, // duplicate the top word on the stack
|
||||
|
||||
// popping values off the (evaluation) stack, possibly storing them in another location
|
||||
DISCARD_BYTE, // discard top byte value
|
||||
|
@ -475,6 +475,12 @@ class AsmGen(private val options: CompilationOptions, private val program: Inter
|
||||
Opcode.RRESTOREX -> " sta ${C64Zeropage.SCRATCH_REG} | pla | tax | lda ${C64Zeropage.SCRATCH_REG}"
|
||||
Opcode.DISCARD_BYTE -> " inx"
|
||||
Opcode.DISCARD_WORD -> " inx"
|
||||
Opcode.DUP_B -> {
|
||||
" dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x"
|
||||
}
|
||||
Opcode.DUP_W -> {
|
||||
" dex | lda ${(ESTACK_LO+1).toHex()},x | sta ${ESTACK_LO.toHex()},x | lda ${(ESTACK_HI+1).toHex()},x | sta ${ESTACK_HI.toHex()},x "
|
||||
}
|
||||
Opcode.DISCARD_FLOAT -> " inx | inx | inx"
|
||||
Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel2 ?: "") // All of the inline assembly is stored in the calllabel2 property. the '@inline@' is a special marker to accept it.
|
||||
Opcode.INCLUDE_FILE -> {
|
||||
|
@ -376,6 +376,16 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
val value = evalstack.pop()
|
||||
checkDt(value, DataType.FLOAT)
|
||||
}
|
||||
Opcode.DUP_B -> {
|
||||
val value = evalstack.peek()
|
||||
checkDt(value, DataType.BYTE, DataType.UBYTE)
|
||||
evalstack.push(value)
|
||||
}
|
||||
Opcode.DUP_W -> {
|
||||
val value = evalstack.peek()
|
||||
checkDt(value, DataType.WORD, DataType.UWORD)
|
||||
evalstack.push(value)
|
||||
}
|
||||
Opcode.POP_MEM_BYTE -> {
|
||||
val value = evalstack.pop()
|
||||
checkDt(value, DataType.BYTE, DataType.UBYTE)
|
||||
|
@ -7,6 +7,22 @@
|
||||
sub start() {
|
||||
A=10
|
||||
Y=22
|
||||
uword uw = A*Y
|
||||
|
||||
when uw {
|
||||
12345 -> {
|
||||
A=44
|
||||
}
|
||||
12346 -> {
|
||||
A=44
|
||||
}
|
||||
12347 -> {
|
||||
A=44
|
||||
}
|
||||
else -> {
|
||||
A=0
|
||||
}
|
||||
}
|
||||
|
||||
when 4+A+Y {
|
||||
10 -> {
|
||||
@ -14,6 +30,9 @@
|
||||
}
|
||||
5 -> c64scr.print("five")
|
||||
30 -> c64scr.print("thirty")
|
||||
31 -> c64scr.print("thirty1")
|
||||
32 -> c64scr.print("thirty2")
|
||||
33 -> c64scr.print("thirty3")
|
||||
99 -> c64scr.print("nn")
|
||||
55 -> {
|
||||
; should be optimized away
|
||||
@ -21,7 +40,7 @@
|
||||
56 -> {
|
||||
; should be optimized away
|
||||
}
|
||||
57 -> {
|
||||
57243 -> {
|
||||
; should be optimized away
|
||||
}
|
||||
else -> {
|
||||
|
@ -197,7 +197,7 @@ scoped_identifier : NAME ('.' NAME)* ;
|
||||
|
||||
register : 'A' | 'X' | 'Y' ;
|
||||
|
||||
registerorpair : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ; // only used in subroutine params and returnvalues
|
||||
registerorpair : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ; // pairs can only be used in subroutine params and returnvalues
|
||||
|
||||
statusregister : 'Pc' | 'Pz' | 'Pn' | 'Pv' ;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /home/irmen/Projects/prog8/parser/antlr/prog8.g4 by ANTLR 4.7.2
|
||||
// Generated from prog8.g4 by ANTLR 4.7.2
|
||||
|
||||
package prog8.parser;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from /home/irmen/Projects/prog8/parser/antlr/prog8.g4 by ANTLR 4.7.2
|
||||
// Generated from prog8.g4 by ANTLR 4.7.2
|
||||
|
||||
package prog8.parser;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user