more asm output, added COPY_MEM_XXX optimized opcodes

This commit is contained in:
Irmen de Jong 2018-10-25 00:28:50 +02:00
parent 4effd0b3db
commit f42a036fc5
10 changed files with 275 additions and 85 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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