mirror of
https://github.com/irmen/prog8.git
synced 2024-10-04 12:57:29 +00:00
more asm output, added COPY_MEM_XXX optimized opcodes
This commit is contained in:
parent
4effd0b3db
commit
f42a036fc5
@ -19,26 +19,41 @@ sub start() {
|
||||
float fl2 = 2.2
|
||||
|
||||
memory byte mbyte = $c000
|
||||
memory byte mbyte2 = $d000
|
||||
memory ubyte mubyte = $c001
|
||||
memory ubyte mubyte2 = $d001
|
||||
memory word mword = $c002
|
||||
memory word mword2 = $d002
|
||||
memory uword muword = $c004
|
||||
memory uword muword2 = $d004
|
||||
memory float mfloat = $c006
|
||||
memory float mfloat2 = $d006
|
||||
|
||||
; b = 1
|
||||
; derp = 1
|
||||
; w = 1
|
||||
; uw = 1
|
||||
; fl1 = 2.345
|
||||
;
|
||||
; b = b2
|
||||
; derp = pixely
|
||||
; w = w2
|
||||
; uw = uw2
|
||||
; fl1 = fl2
|
||||
;
|
||||
; b = mbyte
|
||||
; derp = mubyte
|
||||
; w = mword
|
||||
; uw = muword
|
||||
; fl1 = mfloat
|
||||
;
|
||||
; mbyte = 1
|
||||
; mubyte = 1
|
||||
; mword = 1
|
||||
; muword = 1
|
||||
; mfloat = 3.456
|
||||
|
||||
uw2 = uw
|
||||
w2 = w
|
||||
b2 = b
|
||||
derp=pixely
|
||||
fl2 = fl1
|
||||
fl2++
|
||||
|
||||
mbyte = 99
|
||||
mubyte = 99
|
||||
mword = 99 ; @todo fix ast error literal value missing wordvalue
|
||||
muword = 99 ; @todo fix ast error literal value missing wordvalue
|
||||
mword = 999.w
|
||||
muword = 999.w
|
||||
mfloat = 1.23456
|
||||
%breakpoint
|
||||
|
||||
mbyte = b
|
||||
mubyte = derp
|
||||
@ -46,12 +61,13 @@ sub start() {
|
||||
muword = uw
|
||||
mfloat = fl2
|
||||
|
||||
; @todo fix deze assignments:
|
||||
b = mbyte
|
||||
derp = mubyte
|
||||
w = mword
|
||||
uw = muword
|
||||
fl2 = mfloat
|
||||
%breakpoint
|
||||
|
||||
mbyte = mbyte2
|
||||
mubyte = mubyte2
|
||||
mword = mword2
|
||||
muword = muword2
|
||||
mfloat = mfloat2
|
||||
|
||||
|
||||
return
|
||||
|
@ -4,6 +4,7 @@ import prog8.stackvm.Syscall
|
||||
|
||||
open class Instruction(val opcode: Opcode,
|
||||
val arg: Value? = null,
|
||||
val arg2: Value? = null,
|
||||
val callLabel: String? = null,
|
||||
val callLabel2: String? = null)
|
||||
{
|
||||
@ -24,6 +25,10 @@ open class Instruction(val opcode: Opcode,
|
||||
// opcodes that manipulate a variable
|
||||
"${opcode.toString().toLowerCase()} ${callLabel?:""} ${callLabel2?:""}".trimEnd()
|
||||
}
|
||||
opcode in setOf(Opcode.COPY_MEM_BYTE, Opcode.COPY_MEM_WORD, Opcode.COPY_MEM_FLOAT) -> {
|
||||
// opcodes with two (address) args
|
||||
"${opcode.toString().toLowerCase()} $arg $arg2"
|
||||
}
|
||||
callLabel==null -> "${opcode.toString().toLowerCase()} $argStr"
|
||||
else -> "${opcode.toString().toLowerCase()} $callLabel $argStr"
|
||||
}
|
||||
@ -33,7 +38,7 @@ open class Instruction(val opcode: Opcode,
|
||||
}
|
||||
}
|
||||
|
||||
class LabelInstr(val name: String) : Instruction(opcode = Opcode.NOP) {
|
||||
class LabelInstr(val name: String) : Instruction(Opcode.NOP, null, null) {
|
||||
override fun toString(): String {
|
||||
return "\n$name:"
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
Opcode.PUSH_VAR_BYTE ->
|
||||
if (it[1].value.opcode == Opcode.POP_VAR_BYTE) {
|
||||
if (it[0].value.callLabel != it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_BYTE, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_BYTE, null, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
@ -88,7 +88,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
Opcode.PUSH_VAR_WORD ->
|
||||
if (it[1].value.opcode == Opcode.POP_VAR_WORD) {
|
||||
if (it[0].value.callLabel != it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_WORD, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_WORD, null, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
@ -96,7 +96,31 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
Opcode.PUSH_VAR_FLOAT ->
|
||||
if (it[1].value.opcode == Opcode.POP_VAR_FLOAT) {
|
||||
if (it[0].value.callLabel != it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_FLOAT, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_VAR_FLOAT, null, null, it[0].value.callLabel, it[1].value.callLabel)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
}
|
||||
Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB ->
|
||||
if(it[1].value.opcode == Opcode.POP_MEM_B || it[1].value.opcode == Opcode.POP_MEM_UB) {
|
||||
if(it[0].value.arg != it[1].value.arg)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_BYTE, it[0].value.arg, it[1].value.arg)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
}
|
||||
Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW ->
|
||||
if(it[1].value.opcode == Opcode.POP_MEM_W || it[1].value.opcode == Opcode.POP_MEM_UW) {
|
||||
if(it[0].value.arg != it[1].value.arg)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_WORD, it[0].value.arg, it[1].value.arg)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
}
|
||||
Opcode.PUSH_MEM_FLOAT ->
|
||||
if(it[1].value.opcode == Opcode.POP_MEM_FLOAT) {
|
||||
if(it[0].value.arg != it[1].value.arg)
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.COPY_MEM_FLOAT, it[0].value.arg, it[1].value.arg)
|
||||
else
|
||||
instructionsToReplace[it[0].index] = Instruction(Opcode.NOP)
|
||||
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
|
||||
@ -279,7 +303,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
||||
}
|
||||
|
||||
fun instr(opcode: Opcode, arg: Value? = null, callLabel: String? = null) {
|
||||
currentBlock.instructions.add(Instruction(opcode, arg, callLabel))
|
||||
currentBlock.instructions.add(Instruction(opcode, arg, callLabel = callLabel))
|
||||
}
|
||||
|
||||
fun label(labelname: String) {
|
||||
|
@ -32,6 +32,9 @@ enum class Opcode {
|
||||
COPY_VAR_BYTE,
|
||||
COPY_VAR_WORD,
|
||||
COPY_VAR_FLOAT,
|
||||
COPY_MEM_BYTE,
|
||||
COPY_MEM_WORD,
|
||||
COPY_MEM_FLOAT,
|
||||
|
||||
// numeric arithmetic
|
||||
ADD_UB,
|
||||
|
@ -38,9 +38,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
when {
|
||||
it is LabelInstr -> LabelInstr(symname(it.name, block))
|
||||
it.opcode == Opcode.INLINE_ASSEMBLY -> it
|
||||
else -> Instruction(it.opcode, it.arg,
|
||||
if (it.callLabel != null) symname(it.callLabel, block) else null,
|
||||
if (it.callLabel2 != null) symname(it.callLabel2, block) else null)
|
||||
else ->
|
||||
Instruction(it.opcode, it.arg, it.arg2,
|
||||
callLabel = if (it.callLabel != null) symname(it.callLabel, block) else null,
|
||||
callLabel2 = if (it.callLabel2 != null) symname(it.callLabel2, block) else null)
|
||||
}
|
||||
}.toMutableList()
|
||||
val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
|
||||
@ -318,7 +319,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
|
||||
private fun instr2asm(ins: List<Instruction>): Int {
|
||||
// find best patterns (matching the most of the lines, then with the smallest weight)
|
||||
val fragments = findPatterns(ins).sortedWith(compareBy({it.segmentSize}, {it.prio}))
|
||||
val fragments = findPatterns(ins).sortedBy { it.segmentSize }
|
||||
if(fragments.isEmpty()) {
|
||||
// we didn't find any matching patterns (complex multi-instruction fragments), try simple ones
|
||||
val firstIns = ins[0]
|
||||
@ -409,39 +410,39 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
// val floatConst = getFloatConst(ins.arg)
|
||||
// " lda #<$floatConst | ldy #>$floatConst | jsr prog8_lib.push_float"
|
||||
// }
|
||||
Opcode.PUSH_VAR_BYTE -> {
|
||||
when(ins.callLabel) {
|
||||
"X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
||||
"A" -> " sta ${ESTACK_LO.toHex()},x | dex"
|
||||
"Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
|
||||
else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
|
||||
}
|
||||
}
|
||||
Opcode.PUSH_VAR_WORD -> {
|
||||
when (ins.callLabel) {
|
||||
"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")
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
|
||||
Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
|
||||
"""
|
||||
lda ${ins.arg!!.integerValue().toHex()}
|
||||
sta ${ESTACK_LO.toHex()},x
|
||||
dex
|
||||
"""
|
||||
}
|
||||
Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
|
||||
"""
|
||||
lda ${ins.arg!!.integerValue().toHex()}
|
||||
sta ${ESTACK_LO.toHex()},x
|
||||
lda ${(ins.arg.integerValue()+1).toHex()}
|
||||
sta ${ESTACK_HI.toHex()},x
|
||||
dex
|
||||
"""
|
||||
}
|
||||
// Opcode.PUSH_VAR_BYTE -> {
|
||||
// when(ins.callLabel) {
|
||||
// "X" -> throw CompilerException("makes no sense to push X, it's used as a stack pointer itself")
|
||||
// "A" -> " sta ${ESTACK_LO.toHex()},x | dex"
|
||||
// "Y" -> " tya | sta ${ESTACK_LO.toHex()},x | dex"
|
||||
// else -> " lda ${ins.callLabel} | sta ${ESTACK_LO.toHex()},x | dex"
|
||||
// }
|
||||
// }
|
||||
// Opcode.PUSH_VAR_WORD -> {
|
||||
// when (ins.callLabel) {
|
||||
// "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")
|
||||
// "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"
|
||||
// }
|
||||
// }
|
||||
// Opcode.PUSH_VAR_FLOAT -> " lda #<${ins.callLabel} | ldy #>${ins.callLabel}| jsr prog8_lib.push_float"
|
||||
// Opcode.PUSH_MEM_B, Opcode.PUSH_MEM_UB -> {
|
||||
// """
|
||||
// lda ${ins.arg!!.integerValue().toHex()}
|
||||
// sta ${ESTACK_LO.toHex()},x
|
||||
// dex
|
||||
// """
|
||||
// }
|
||||
// Opcode.PUSH_MEM_W, Opcode.PUSH_MEM_UW -> {
|
||||
// """
|
||||
// lda ${ins.arg!!.integerValue().toHex()}
|
||||
// sta ${ESTACK_LO.toHex()},x
|
||||
// lda ${(ins.arg.integerValue()+1).toHex()}
|
||||
// sta ${ESTACK_HI.toHex()},x
|
||||
// dex
|
||||
// """
|
||||
// }
|
||||
|
||||
Opcode.POP_MEM_B, Opcode.POP_MEM_UB -> {
|
||||
"""
|
||||
@ -500,7 +501,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
return " st${ins.callLabel!!.toLowerCase()} ${ins.callLabel2}"
|
||||
else ->
|
||||
// var -> var
|
||||
return " lda ${ins.callLabel}\n\tsta ${ins.callLabel2}"
|
||||
return " lda ${ins.callLabel} | sta ${ins.callLabel2}"
|
||||
}
|
||||
}
|
||||
Opcode.COPY_VAR_WORD -> {
|
||||
@ -556,6 +557,29 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
"""
|
||||
}
|
||||
|
||||
Opcode.COPY_MEM_BYTE -> " lda ${ins.arg!!.integerValue().toHex()} | sta ${ins.arg2!!.integerValue().toHex()}"
|
||||
Opcode.COPY_MEM_WORD -> {
|
||||
"""
|
||||
lda ${ins.arg!!.integerValue().toHex()}
|
||||
sta ${ins.arg2!!.integerValue().toHex()}
|
||||
lda ${(ins.arg.integerValue()+1).toHex()}
|
||||
sta ${(ins.arg2.integerValue()+1).toHex()}
|
||||
"""
|
||||
}
|
||||
Opcode.COPY_MEM_FLOAT -> {
|
||||
"""
|
||||
lda #<${ins.arg!!.integerValue().toHex()}
|
||||
ldy #>${ins.arg.integerValue().toHex()}
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||
lda #<${ins.arg2!!.integerValue().toHex()}
|
||||
ldy #>${ins.arg2.integerValue().toHex()}
|
||||
sta ${C64Zeropage.SCRATCH_W2}
|
||||
sty ${C64Zeropage.SCRATCH_W2+1}
|
||||
jsr prog8_lib.copy_float
|
||||
"""
|
||||
}
|
||||
|
||||
Opcode.INC_VAR_UB, Opcode.INC_VAR_B -> {
|
||||
when (ins.callLabel) {
|
||||
"A" -> " clc | adc #1"
|
||||
@ -729,8 +753,17 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
// check for direct var assignments that should have been converted into COPY_VAR_XXX opcodes
|
||||
if((opcodes[0]==Opcode.PUSH_VAR_BYTE && opcodes[1]==Opcode.POP_VAR_BYTE) ||
|
||||
(opcodes[0]==Opcode.PUSH_VAR_WORD && opcodes[1]==Opcode.POP_VAR_WORD) ||
|
||||
(opcodes[0]==Opcode.PUSH_VAR_FLOAT && opcodes[1]==Opcode.POP_VAR_FLOAT)) {
|
||||
throw AssemblyError("push+pop var should have been changed into COPY_VAR_XXX opcode")
|
||||
(opcodes[0]==Opcode.PUSH_VAR_FLOAT && opcodes[1]==Opcode.POP_VAR_FLOAT) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_B && opcodes[1]==Opcode.POP_MEM_B) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_B && opcodes[1]==Opcode.POP_MEM_UB) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[1]==Opcode.POP_MEM_B) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_UB && opcodes[1]==Opcode.POP_MEM_UB) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_W && opcodes[1]==Opcode.POP_MEM_W) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_W && opcodes[1]==Opcode.POP_MEM_UW) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[1]==Opcode.POP_MEM_W) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_UW && opcodes[1]==Opcode.POP_MEM_UW) ||
|
||||
(opcodes[0]==Opcode.PUSH_MEM_FLOAT && opcodes[1]==Opcode.POP_MEM_FLOAT)) {
|
||||
throw AssemblyError("push+pop var/mem should have been changed into COPY_VAR_XXX opcode")
|
||||
}
|
||||
|
||||
// check for operations that modify a single value, by putting it on the stack (and popping it afterwards)
|
||||
@ -783,7 +816,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
if(pattern.sequence == opcodes.subList(0, pattern.sequence.size)) {
|
||||
val asm = pattern.asm(segment)
|
||||
if(asm!=null)
|
||||
result.add(AsmFragment(asm, pattern.prio, pattern.sequence.size))
|
||||
result.add(AsmFragment(asm, pattern.sequence.size))
|
||||
}
|
||||
}
|
||||
|
||||
@ -975,14 +1008,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
}
|
||||
}
|
||||
|
||||
class AsmFragment(val asm: String, val prio: Int, var segmentSize: Int=0)
|
||||
class AsmFragment(val asm: String, var segmentSize: Int=0)
|
||||
|
||||
class AsmPattern(val sequence: List<Opcode>, val prio: Int, val asm: (List<Instruction>)->String?)
|
||||
class AsmPattern(val sequence: List<Opcode>, val asm: (List<Instruction>)->String?)
|
||||
|
||||
private val patterns = listOf(
|
||||
|
||||
// assignment: var = byte
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
|
||||
when (segment[1].callLabel) {
|
||||
"A", "X", "Y" ->
|
||||
" ld${segment[1].callLabel!!.toLowerCase()} #${segment[0].arg!!.integerValue().toHex()}"
|
||||
@ -991,16 +1024,33 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
}
|
||||
},
|
||||
|
||||
// assignment: mem = bytevar/ubytevar
|
||||
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_B)) { segment ->
|
||||
" lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||
},
|
||||
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.POP_MEM_UB)) { segment ->
|
||||
" lda ${segment[0].callLabel} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||
},
|
||||
|
||||
// assignment: mem = byte/ubyte
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_B), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_B)) { segment ->
|
||||
" lda #${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||
},
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_UB), 9) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.POP_MEM_UB)) { segment ->
|
||||
" lda #${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].arg!!.integerValue().toHex()}"
|
||||
},
|
||||
|
||||
// assignment: (u)bytevar = membyte
|
||||
AsmPattern(listOf(Opcode.PUSH_MEM_B, Opcode.POP_VAR_BYTE)) { segment ->
|
||||
" lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
||||
},
|
||||
AsmPattern(listOf(Opcode.PUSH_MEM_UB, Opcode.POP_VAR_BYTE)) { segment ->
|
||||
" lda ${segment[0].arg!!.integerValue().toHex()} | sta ${segment[1].callLabel}"
|
||||
},
|
||||
|
||||
|
||||
// assignment: var = word
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_VAR_WORD)) { segment ->
|
||||
val number = segment[0].arg!!.integerValue().toHex()
|
||||
when (segment[1].callLabel) {
|
||||
"AX" -> " lda #<$number | ldx #>$number"
|
||||
@ -1016,8 +1066,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
}
|
||||
},
|
||||
|
||||
// assignment: mem = wordvar/uwordvar
|
||||
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.POP_MEM_W)) { segment ->
|
||||
"""
|
||||
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 ->
|
||||
"""
|
||||
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
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_W), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_W)) { segment ->
|
||||
"""
|
||||
lda #<${segment[0].arg!!.integerValue().toHex()}
|
||||
sta ${segment[1].arg!!.integerValue().toHex()}
|
||||
@ -1025,7 +1093,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
sta ${(segment[1].arg!!.integerValue()+1).toHex()}
|
||||
"""
|
||||
},
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_UW), 9) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.POP_MEM_UW)) { segment ->
|
||||
"""
|
||||
lda #<${segment[0].arg!!.integerValue().toHex()}
|
||||
sta ${segment[1].arg!!.integerValue().toHex()}
|
||||
@ -1034,8 +1102,26 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
"""
|
||||
},
|
||||
|
||||
// assignment: (u)wordvar = memword
|
||||
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.POP_VAR_WORD)) { segment ->
|
||||
"""
|
||||
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 ->
|
||||
"""
|
||||
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
|
||||
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
|
||||
val floatConst = getFloatConst(segment[0].arg!!)
|
||||
"""
|
||||
lda #<$floatConst
|
||||
@ -1050,8 +1136,23 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
"""
|
||||
},
|
||||
|
||||
// assignment: var = memfloat
|
||||
AsmPattern(listOf(Opcode.PUSH_MEM_FLOAT, Opcode.POP_VAR_FLOAT)) { segment ->
|
||||
"""
|
||||
lda #<${segment[0].arg!!.integerValue().toHex()}
|
||||
ldy #>${segment[0].arg!!.integerValue().toHex()}
|
||||
sta ${C64Zeropage.SCRATCH_W1}
|
||||
sty ${C64Zeropage.SCRATCH_W1+1}
|
||||
lda #<${segment[1].callLabel}
|
||||
ldy #>${segment[1].callLabel}
|
||||
sta ${C64Zeropage.SCRATCH_W2}
|
||||
sty ${C64Zeropage.SCRATCH_W2+1}
|
||||
jsr prog8_lib.copy_float
|
||||
"""
|
||||
},
|
||||
|
||||
// assignment: mem = float
|
||||
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
|
||||
val floatConst = getFloatConst(segment[0].arg!!)
|
||||
"""
|
||||
lda #<$floatConst
|
||||
@ -1067,7 +1168,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
},
|
||||
|
||||
// assignment: mem = floatvar
|
||||
AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_VAR_FLOAT, Opcode.POP_MEM_FLOAT)) { segment ->
|
||||
"""
|
||||
lda #<${segment[0].callLabel}
|
||||
ldy #>${segment[0].callLabel}
|
||||
@ -1081,8 +1182,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
"""
|
||||
},
|
||||
|
||||
|
||||
// assignment: var = bytearray[index]
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE), 10) { segment ->
|
||||
AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.READ_INDEXED_VAR_BYTE, Opcode.POP_VAR_BYTE)) { segment ->
|
||||
val index = segment[0].arg!!.integerValue()
|
||||
when (segment[2].callLabel) {
|
||||
"A", "X", "Y" ->
|
||||
|
@ -46,7 +46,7 @@ class AssemblyProgram(val name: String) {
|
||||
for(line in File(viceMonListFile).readLines()) {
|
||||
val match = pattern.matchEntire(line)
|
||||
if(match!=null)
|
||||
breakpoints.add("break \$" + match.groupValues[0]) // todo check this
|
||||
breakpoints.add("break \$" + match.groupValues[1])
|
||||
}
|
||||
val num = breakpoints.size
|
||||
breakpoints.add(0, "; vice monitor breakpoint list now follows")
|
||||
|
@ -606,7 +606,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
|
||||
DataType.WORD -> {
|
||||
// we can convert to WORD: any UBYTE/BYTE, UWORD <= 32767, FLOAT that's an integer -32768..32767
|
||||
if(lv.type==DataType.UBYTE || lv.type==DataType.BYTE)
|
||||
assignment.value = LiteralValue(DataType.WORD, lv.bytevalue!!, position=lv.position)
|
||||
assignment.value = LiteralValue(DataType.WORD, wordvalue=lv.bytevalue!!.toInt(), position=lv.position)
|
||||
else if(lv.type==DataType.UWORD && lv.wordvalue!! <= 32767)
|
||||
assignment.value = LiteralValue(DataType.WORD, wordvalue=lv.wordvalue, position=lv.position)
|
||||
else if(lv.type==DataType.FLOAT) {
|
||||
|
@ -126,7 +126,13 @@ class Program (val name: String,
|
||||
Opcode.LINE -> Instruction(opcode, null, callLabel = args)
|
||||
Opcode.COPY_VAR_BYTE, Opcode.COPY_VAR_WORD, Opcode.COPY_VAR_FLOAT -> {
|
||||
val (v1, v2) = args!!.split(splitpattern, limit = 2)
|
||||
Instruction(opcode, null, v1, v2)
|
||||
Instruction(opcode, null, null, v1, v2)
|
||||
}
|
||||
Opcode.COPY_MEM_BYTE, Opcode.COPY_MEM_WORD, Opcode.COPY_MEM_FLOAT -> {
|
||||
val (v1, v2) = args!!.split(splitpattern, limit = 2)
|
||||
val address1 = getArgValue(v1, heap)
|
||||
val address2 = getArgValue(v2, heap)
|
||||
Instruction(opcode, address1, address2)
|
||||
}
|
||||
Opcode.JUMP, Opcode.CALL, Opcode.BNEG, Opcode.BPOS,
|
||||
Opcode.BZ, Opcode.BNZ, Opcode.BCS, Opcode.BCC -> {
|
||||
|
@ -812,6 +812,21 @@ class StackVm(private var traceOutputFile: String?) {
|
||||
checkDt(dest, DataType.FLOAT)
|
||||
variables[ins.callLabel2!!] = source
|
||||
}
|
||||
Opcode.COPY_MEM_BYTE -> {
|
||||
val sourceAddr = ins.arg!!.integerValue()
|
||||
val destAddr = ins.arg2!!.integerValue()
|
||||
mem.setUByte(destAddr, mem.getUByte(sourceAddr))
|
||||
}
|
||||
Opcode.COPY_MEM_WORD -> {
|
||||
val sourceAddr = ins.arg!!.integerValue()
|
||||
val destAddr = ins.arg2!!.integerValue()
|
||||
mem.setUWord(destAddr, mem.getUWord(sourceAddr))
|
||||
}
|
||||
Opcode.COPY_MEM_FLOAT -> {
|
||||
val sourceAddr = ins.arg!!.integerValue()
|
||||
val destAddr = ins.arg2!!.integerValue()
|
||||
mem.setFloat(destAddr, mem.getFloat(sourceAddr))
|
||||
}
|
||||
Opcode.POP_VAR_FLOAT -> {
|
||||
val value = evalstack.pop()
|
||||
checkDt(value, DataType.FLOAT)
|
||||
|
@ -282,10 +282,10 @@ class TestStackVmOpcodes {
|
||||
@Test
|
||||
fun testCopyVar() {
|
||||
val ins = mutableListOf(
|
||||
Instruction(Opcode.COPY_VAR_BYTE, null, "bvar1", "bvar2"),
|
||||
Instruction(Opcode.COPY_VAR_WORD, null, "wvar1", "wvar2"),
|
||||
Instruction(Opcode.COPY_VAR_FLOAT, null, "fvar1", "fvar2"),
|
||||
Instruction(Opcode.COPY_VAR_WORD, null, "wvar1", "bvar2"))
|
||||
Instruction(Opcode.COPY_VAR_BYTE, null, null, "bvar1", "bvar2"),
|
||||
Instruction(Opcode.COPY_VAR_WORD, null, null, "wvar1", "wvar2"),
|
||||
Instruction(Opcode.COPY_VAR_FLOAT, null, null, "fvar1", "fvar2"),
|
||||
Instruction(Opcode.COPY_VAR_WORD, null, null, "wvar1", "bvar2"))
|
||||
val vars = mapOf(
|
||||
"bvar1" to Value(DataType.UBYTE, 1),
|
||||
"bvar2" to Value(DataType.UBYTE, 2),
|
||||
@ -305,6 +305,25 @@ class TestStackVmOpcodes {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCopyMem() {
|
||||
val ins = mutableListOf(
|
||||
Instruction(Opcode.COPY_MEM_BYTE, Value(DataType.UWORD, 0xc000), Value(DataType.UWORD, 0xc001)),
|
||||
Instruction(Opcode.COPY_MEM_WORD, Value(DataType.UWORD, 0xc100), Value(DataType.UWORD, 0xc102)),
|
||||
Instruction(Opcode.COPY_MEM_FLOAT, Value(DataType.UWORD, 0xc200), Value(DataType.UWORD, 0xc300)))
|
||||
val mem=mapOf(0xc000 to listOf(Value(DataType.UBYTE, 0x45)),
|
||||
0xc100 to listOf(Value(DataType.UWORD, 0xc2ca)),
|
||||
0xc200 to listOf(Value(DataType.FLOAT, 42.25)))
|
||||
vm.load(makeProg(ins, mem=mem), null)
|
||||
assertEquals(0, vm.mem.getUByte(0xc001))
|
||||
assertEquals(0, vm.mem.getUWord(0xc102))
|
||||
assertEquals(0.0, vm.mem.getFloat(0xc300))
|
||||
vm.step(3)
|
||||
assertEquals(0x45, vm.mem.getUByte(0xc001))
|
||||
assertEquals(0xc2ca, vm.mem.getUWord(0xc102))
|
||||
assertEquals(42.25, vm.mem.getFloat(0xc300))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAdd() {
|
||||
testBinaryOperator(Value(DataType.UBYTE, 140), Opcode.ADD_UB, Value(DataType.UBYTE, 222), Value(DataType.UBYTE, 106))
|
||||
|
Loading…
Reference in New Issue
Block a user