added DUP opcodes

This commit is contained in:
Irmen de Jong 2019-07-09 04:09:29 +02:00
parent 70462ffe6d
commit 5ff79073f4
10 changed files with 80 additions and 13 deletions

View File

@ -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))

View File

@ -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
}
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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 -> {

View 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)

View File

@ -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 -> {

View File

@ -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' ;

View File

@ -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;

View File

@ -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;