mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
6502 start
This commit is contained in:
parent
b7d8f026f4
commit
b52120139c
@ -16,6 +16,16 @@ sub start() {
|
||||
word wv2
|
||||
uword uwv2
|
||||
|
||||
X=X
|
||||
X=X
|
||||
Y=Y
|
||||
X=A
|
||||
A=Y
|
||||
A=ubvar
|
||||
AX=XY
|
||||
XY=XY
|
||||
AY=uwvar
|
||||
XY=uwvar
|
||||
|
||||
bv2 = ub2b(ubvar)
|
||||
ubv2 = b2ub(bvar)
|
||||
|
@ -42,6 +42,8 @@ fun main(args: Array<String>) {
|
||||
as? Directive)?.args?.single()?.name?.toUpperCase()
|
||||
val launcherType = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%launcher"}
|
||||
as? Directive)?.args?.single()?.name?.toUpperCase()
|
||||
moduleAst.loadAddress = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%address"}
|
||||
as? Directive)?.args?.single()?.int ?: 0
|
||||
val zpoption: String? = (moduleAst.statements.singleOrNull { it is Directive && it.directive=="%zeropage"}
|
||||
as? Directive)?.args?.single()?.name?.toUpperCase()
|
||||
val zpType: ZeropageType =
|
||||
|
@ -421,6 +421,8 @@ class Module(override val name: String,
|
||||
this.parent=parent
|
||||
}
|
||||
|
||||
var loadAddress: Int = 0 // can be set with the %address directive
|
||||
|
||||
fun linkParents() {
|
||||
parent = ParentSentinel
|
||||
statements.forEach {it.linkParents(this)}
|
||||
|
@ -159,7 +159,7 @@ class Compiler(private val options: CompilationOptions) {
|
||||
println("\nCreating stackVM code...")
|
||||
|
||||
val namespace = module.definingScope()
|
||||
val program = IntermediateProgram(module.name, heap)
|
||||
val program = IntermediateProgram(module.name, module.loadAddress, heap)
|
||||
|
||||
val translator = StatementTranslator(program, namespace, heap)
|
||||
translator.process(module)
|
||||
@ -178,7 +178,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
val continueStmtLabelStack : Stack<String> = Stack()
|
||||
|
||||
override fun process(block: Block): IStatement {
|
||||
prog.newBlock(block.scopedname, block.address)
|
||||
prog.newBlock(block.scopedname, block.name, block.address)
|
||||
processVariables(block)
|
||||
prog.label(block.scopedname)
|
||||
prog.line(block.position)
|
||||
|
@ -9,9 +9,9 @@ import prog8.compiler.HeapValues
|
||||
import java.io.PrintStream
|
||||
|
||||
|
||||
class IntermediateProgram(val name: String, val heap: HeapValues) {
|
||||
class IntermediateProgram(val name: String, var loadAddress: Int, val heap: HeapValues) {
|
||||
|
||||
private class ProgramBlock(val scopedname: String, val address: Int?) {
|
||||
class ProgramBlock(val scopedname: String, val shortname: String, var address: Int?) {
|
||||
val instructions = mutableListOf<Instruction>()
|
||||
val variables = mutableMapOf<String, Value>()
|
||||
val labels = mutableMapOf<String, Instruction>()
|
||||
@ -20,10 +20,16 @@ class IntermediateProgram(val name: String, val heap: HeapValues) {
|
||||
get() { return variables.size }
|
||||
val numInstructions: Int
|
||||
get() { return instructions.filter { it.opcode!= Opcode.LINE }.size }
|
||||
|
||||
fun getIns(idx: Int): Instruction {
|
||||
if(idx>=0 && idx <instructions.size)
|
||||
return instructions[idx]
|
||||
return Instruction(Opcode.NOP)
|
||||
}
|
||||
}
|
||||
|
||||
private val blocks = mutableListOf<ProgramBlock>()
|
||||
private val memory = mutableMapOf<Int, List<Value>>()
|
||||
val blocks = mutableListOf<ProgramBlock>()
|
||||
val memory = mutableMapOf<Int, List<Value>>()
|
||||
private lateinit var currentBlock: ProgramBlock
|
||||
|
||||
val numVariables: Int
|
||||
@ -273,8 +279,8 @@ class IntermediateProgram(val name: String, val heap: HeapValues) {
|
||||
currentBlock.instructions.add(Instruction(Opcode.LINE, callLabel = "${position.line} ${position.file}"))
|
||||
}
|
||||
|
||||
fun newBlock(scopedname: String, address: Int?) {
|
||||
currentBlock = ProgramBlock(scopedname, address)
|
||||
fun newBlock(scopedname: String, shortname: String, address: Int?) {
|
||||
currentBlock = ProgramBlock(scopedname, shortname, address)
|
||||
blocks.add(currentBlock)
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,371 @@
|
||||
package prog8.compiler.target.c64
|
||||
|
||||
import prog8.compiler.CompilationOptions
|
||||
import prog8.compiler.LauncherType
|
||||
import prog8.compiler.OutputType
|
||||
import prog8.compiler.intermediate.Instruction
|
||||
import prog8.compiler.intermediate.IntermediateProgram
|
||||
import prog8.compiler.intermediate.LabelInstr
|
||||
import prog8.compiler.intermediate.Opcode
|
||||
import prog8.compiler.toHex
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
|
||||
class AssemblyError(msg: String) : RuntimeException(msg)
|
||||
|
||||
|
||||
class AsmGen(val options: CompilationOptions) {
|
||||
fun compileToAssembly(program: IntermediateProgram): AssemblyProgram {
|
||||
println("\nGenerating assembly code from intermediate code... ")
|
||||
// todo generate 6502 assembly
|
||||
val out = File("${program.name}.asm").printWriter()
|
||||
out.use {
|
||||
header(out::println, program)
|
||||
for(block in program.blocks)
|
||||
block2asm(out::println, block)
|
||||
}
|
||||
|
||||
return AssemblyProgram(program.name)
|
||||
}
|
||||
|
||||
private fun header(out: (String)->Unit, program: IntermediateProgram) {
|
||||
val ourName = this.javaClass.name
|
||||
out("; 6502 assembly code for '${program.name}'")
|
||||
out("; generated by $ourName on ${Date()}")
|
||||
out("; assembler syntax is for the 64tasm cross-assembler")
|
||||
out("; output options: output=${options.output} launcher=${options.launcher} zp=${options.zeropage}")
|
||||
out("\n.cpu '6502'\n.enc 'none'\n")
|
||||
|
||||
if(program.loadAddress==0) // fix load address
|
||||
program.loadAddress = if(options.launcher==LauncherType.BASIC) BASIC_LOAD_ADDRESS else RAW_LOAD_ADDRESS
|
||||
|
||||
when {
|
||||
options.launcher == LauncherType.BASIC -> {
|
||||
if (program.loadAddress != 0x0801)
|
||||
throw AssemblyError("BASIC output must have load address $0801")
|
||||
out("; ---- basic program with sys call ----")
|
||||
out("* = ${program.loadAddress.toHex()}")
|
||||
val year = Calendar.getInstance().get(Calendar.YEAR)
|
||||
out("\t.word (+), $year")
|
||||
out("\t.null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8 by idj'")
|
||||
out("+\t.word 0")
|
||||
out("_prog8_entrypoint\t; assembly code starts here\n")
|
||||
}
|
||||
options.output == OutputType.PRG -> {
|
||||
out("; ---- program without sys call ----")
|
||||
out("* = ${program.loadAddress.toHex()}\n")
|
||||
}
|
||||
options.output == OutputType.RAW -> {
|
||||
out("; ---- raw assembler program ----")
|
||||
out("* = ${program.loadAddress.toHex()}\n")
|
||||
}
|
||||
}
|
||||
|
||||
// call the init methods of each block and then jump to the main.start entrypoint
|
||||
out("\t; initialize all blocks(reset vars)")
|
||||
// todo zeropage if it's there
|
||||
for(block in program.blocks)
|
||||
out("\tjsr ${block.scopedname}._prog8_init")
|
||||
out("\tjmp main.start\t; jump to program entrypoint")
|
||||
}
|
||||
|
||||
private fun block2asm(out: (String)->Unit, block: IntermediateProgram.ProgramBlock) {
|
||||
out("\n; ---- block: '${block.shortname}' ----")
|
||||
if(block.address!=null) {
|
||||
out(".cerror * > ${block.address?.toHex()}, 'block address overlaps by ', *-${block.address?.toHex()},' bytes'")
|
||||
out("* = ${block.address?.toHex()}")
|
||||
}
|
||||
out("${block.shortname}\t.proc\n")
|
||||
|
||||
// init the variables
|
||||
out("_prog8_init\t; (re)set vars to initial values")
|
||||
// todo init vars
|
||||
|
||||
var skip = 0
|
||||
for(ins in block.instructions.withIndex()) {
|
||||
if(skip==0)
|
||||
skip = ins2asm(out, ins.index, ins.value, block)
|
||||
else
|
||||
skip--
|
||||
}
|
||||
out("\n\t.pend\n")
|
||||
}
|
||||
|
||||
private val registerStrings = setOf("A", "X", "Y", "AX", "AY", "XY")
|
||||
|
||||
private fun ins2asm(out: (String) -> Unit, insIdx: Int, ins: Instruction, block: IntermediateProgram.ProgramBlock): Int {
|
||||
if(ins is LabelInstr) {
|
||||
if(ins.name==block.shortname)
|
||||
return 0
|
||||
if(ins.name.startsWith("${block.shortname}."))
|
||||
out(ins.name.substring(block.shortname.length+1))
|
||||
else
|
||||
out(ins.name)
|
||||
out("\trts") // todo weg
|
||||
return 0
|
||||
}
|
||||
when(ins.opcode) {
|
||||
Opcode.LINE -> out("\t; src line: ${ins.callLabel}")
|
||||
Opcode.NOP -> out("\tnop") // shouldn't be present anymore though
|
||||
Opcode.SEC -> out("\tsec")
|
||||
Opcode.CLC -> out("\tclc")
|
||||
Opcode.SEI -> out("\tsei")
|
||||
Opcode.CLI -> out("\tcli")
|
||||
Opcode.TERMINATE -> out("\tbrk\t; terminate!")
|
||||
Opcode.B2UB -> {} // is a no-op, just carry on with the byte as-is
|
||||
Opcode.UB2B -> {} // is a no-op, just carry on with the byte as-is
|
||||
Opcode.PUSH_BYTE -> {
|
||||
// check if we load a register (X, Y) with constant value
|
||||
val nextIns = block.getIns(insIdx+1)
|
||||
if(nextIns.opcode==Opcode.POP_VAR_BYTE && nextIns.callLabel in registerStrings) {
|
||||
out("\tld${nextIns.callLabel!!.toLowerCase()} #${ins.arg!!.integerValue().toHex()}")
|
||||
return 1 // skip 1
|
||||
}
|
||||
// todo push_byte
|
||||
}
|
||||
Opcode.PUSH_WORD -> {
|
||||
// check if we load a register (AX, AY, XY) with constant value
|
||||
val nextIns = block.getIns(insIdx+1)
|
||||
if(nextIns.opcode==Opcode.POP_VAR_WORD && nextIns.callLabel in registerStrings) {
|
||||
val regs = nextIns.callLabel!!.toLowerCase()
|
||||
val value = ins.arg!!.integerValue().toHex()
|
||||
out("\tld${regs[0]} #<$value")
|
||||
out("\tld${regs[1]} #>$value")
|
||||
return 1 // skip 1
|
||||
}
|
||||
// todo push_word
|
||||
}
|
||||
Opcode.COPY_VAR_BYTE -> {
|
||||
if(ins.callLabel2 in registerStrings) {
|
||||
if(ins.callLabel in registerStrings) {
|
||||
// copying register -> register
|
||||
when {
|
||||
ins.callLabel == "A" -> out("\tta${ins.callLabel2!!.toLowerCase()}")
|
||||
ins.callLabel == "X" -> if (ins.callLabel2 == "Y") {
|
||||
// 6502 doesn't have txy
|
||||
out("\ttxa\n\ttay")
|
||||
} else out("\ttxa")
|
||||
ins.callLabel == "Y" -> if (ins.callLabel2 == "X") {
|
||||
// 6502 doesn't have tyx
|
||||
out("\ttya\n\ttax")
|
||||
} else out("\ttya")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
// todo copy_var_byte
|
||||
}
|
||||
Opcode.COPY_VAR_WORD -> {
|
||||
if(ins.callLabel2 in registerStrings) {
|
||||
if(ins.callLabel in registerStrings) {
|
||||
// copying registerpair -> registerpair
|
||||
when {
|
||||
ins.callLabel == "AX" -> when (ins.callLabel2) {
|
||||
"AY" -> out("\ttxy")
|
||||
"XY" -> out("\tpha\n\ttxa\n\ttay\n\tpla\n\ttax")
|
||||
}
|
||||
ins.callLabel == "AY" -> when (ins.callLabel2) {
|
||||
"AX" -> out("\tpha\n\ttya\n\ttax\n\tpla")
|
||||
"XY" -> out("\ttax")
|
||||
}
|
||||
ins.callLabel == "XY" -> when (ins.callLabel2) {
|
||||
"AX" -> out("\ttxa\n\tpha\n\ttya\n\ttax\n\tpla")
|
||||
"AY" -> out("\ttxa")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
// todo copy_var_byte
|
||||
}
|
||||
else-> {}
|
||||
// Opcode.PUSH_FLOAT -> TODO()
|
||||
// Opcode.PUSH_MEM_B -> TODO()
|
||||
// Opcode.PUSH_MEM_UB -> TODO()
|
||||
// Opcode.PUSH_MEM_W -> TODO()
|
||||
// Opcode.PUSH_MEM_UW -> TODO()
|
||||
// Opcode.PUSH_MEM_FLOAT -> TODO()
|
||||
// Opcode.PUSH_VAR_BYTE -> TODO()
|
||||
// Opcode.PUSH_VAR_WORD -> TODO()
|
||||
// Opcode.PUSH_VAR_FLOAT -> TODO()
|
||||
// Opcode.DISCARD_BYTE -> TODO()
|
||||
// Opcode.DISCARD_WORD -> TODO()
|
||||
// Opcode.DISCARD_FLOAT -> TODO()
|
||||
// Opcode.POP_MEM_B -> TODO()
|
||||
// Opcode.POP_MEM_UB -> TODO()
|
||||
// Opcode.POP_MEM_W -> TODO()
|
||||
// Opcode.POP_MEM_UW -> TODO()
|
||||
// Opcode.POP_MEM_FLOAT -> TODO()
|
||||
// Opcode.POP_VAR_BYTE -> TODO()
|
||||
// Opcode.POP_VAR_WORD -> TODO()
|
||||
// Opcode.POP_VAR_FLOAT -> TODO()
|
||||
// Opcode.COPY_VAR_BYTE -> TODO()
|
||||
// Opcode.COPY_VAR_WORD -> TODO()
|
||||
// Opcode.COPY_VAR_FLOAT -> TODO()
|
||||
// Opcode.ADD_UB -> TODO()
|
||||
// Opcode.ADD_B -> TODO()
|
||||
// Opcode.ADD_UW -> TODO()
|
||||
// Opcode.ADD_W -> TODO()
|
||||
// Opcode.ADD_F -> TODO()
|
||||
// Opcode.SUB_UB -> TODO()
|
||||
// Opcode.SUB_B -> TODO()
|
||||
// Opcode.SUB_UW -> TODO()
|
||||
// Opcode.SUB_W -> TODO()
|
||||
// Opcode.SUB_F -> TODO()
|
||||
// Opcode.MUL_UB -> TODO()
|
||||
// Opcode.MUL_B -> TODO()
|
||||
// Opcode.MUL_UW -> TODO()
|
||||
// Opcode.MUL_W -> TODO()
|
||||
// Opcode.MUL_F -> TODO()
|
||||
// Opcode.DIV_UB -> TODO()
|
||||
// Opcode.DIV_B -> TODO()
|
||||
// Opcode.DIV_UW -> TODO()
|
||||
// Opcode.DIV_W -> TODO()
|
||||
// Opcode.DIV_F -> TODO()
|
||||
// Opcode.FLOORDIV_UB -> TODO()
|
||||
// Opcode.FLOORDIV_B -> TODO()
|
||||
// Opcode.FLOORDIV_UW -> TODO()
|
||||
// Opcode.FLOORDIV_W -> TODO()
|
||||
// Opcode.FLOORDIV_F -> TODO()
|
||||
// Opcode.REMAINDER_UB -> TODO()
|
||||
// Opcode.REMAINDER_B -> TODO()
|
||||
// Opcode.REMAINDER_UW -> TODO()
|
||||
// Opcode.REMAINDER_W -> TODO()
|
||||
// Opcode.REMAINDER_F -> TODO()
|
||||
// Opcode.POW_UB -> TODO()
|
||||
// Opcode.POW_B -> TODO()
|
||||
// Opcode.POW_UW -> TODO()
|
||||
// Opcode.POW_W -> TODO()
|
||||
// Opcode.POW_F -> TODO()
|
||||
// Opcode.NEG_B -> TODO()
|
||||
// Opcode.NEG_W -> TODO()
|
||||
// Opcode.NEG_F -> TODO()
|
||||
// Opcode.SHL_BYTE -> TODO()
|
||||
// Opcode.SHL_WORD -> TODO()
|
||||
// Opcode.SHL_MEM_BYTE -> TODO()
|
||||
// Opcode.SHL_MEM_WORD -> TODO()
|
||||
// Opcode.SHL_VAR_BYTE -> TODO()
|
||||
// Opcode.SHL_VAR_WORD -> TODO()
|
||||
// Opcode.SHR_BYTE -> TODO()
|
||||
// Opcode.SHR_WORD -> TODO()
|
||||
// Opcode.SHR_MEM_BYTE -> TODO()
|
||||
// Opcode.SHR_MEM_WORD -> TODO()
|
||||
// Opcode.SHR_VAR_BYTE -> TODO()
|
||||
// Opcode.SHR_VAR_WORD -> TODO()
|
||||
// Opcode.ROL_BYTE -> TODO()
|
||||
// Opcode.ROL_WORD -> TODO()
|
||||
// Opcode.ROL_MEM_BYTE -> TODO()
|
||||
// Opcode.ROL_MEM_WORD -> TODO()
|
||||
// Opcode.ROL_VAR_BYTE -> TODO()
|
||||
// Opcode.ROL_VAR_WORD -> TODO()
|
||||
// Opcode.ROR_BYTE -> TODO()
|
||||
// Opcode.ROR_WORD -> TODO()
|
||||
// Opcode.ROR_MEM_BYTE -> TODO()
|
||||
// Opcode.ROR_MEM_WORD -> TODO()
|
||||
// Opcode.ROR_VAR_BYTE -> TODO()
|
||||
// Opcode.ROR_VAR_WORD -> TODO()
|
||||
// Opcode.ROL2_BYTE -> TODO()
|
||||
// Opcode.ROL2_WORD -> TODO()
|
||||
// Opcode.ROL2_MEM_BYTE -> TODO()
|
||||
// Opcode.ROL2_MEM_WORD -> TODO()
|
||||
// Opcode.ROL2_VAR_BYTE -> TODO()
|
||||
// Opcode.ROL2_VAR_WORD -> TODO()
|
||||
// Opcode.ROR2_BYTE -> TODO()
|
||||
// Opcode.ROR2_WORD -> TODO()
|
||||
// Opcode.ROR2_MEM_BYTE -> TODO()
|
||||
// Opcode.ROR2_MEM_WORD -> TODO()
|
||||
// Opcode.ROR2_VAR_BYTE -> TODO()
|
||||
// Opcode.ROR2_VAR_WORD -> TODO()
|
||||
// Opcode.BITAND_BYTE -> TODO()
|
||||
// Opcode.BITAND_WORD -> TODO()
|
||||
// Opcode.BITOR_BYTE -> TODO()
|
||||
// Opcode.BITOR_WORD -> TODO()
|
||||
// Opcode.BITXOR_BYTE -> TODO()
|
||||
// Opcode.BITXOR_WORD -> TODO()
|
||||
// Opcode.INV_BYTE -> TODO()
|
||||
// Opcode.INV_WORD -> TODO()
|
||||
// Opcode.LSB -> TODO()
|
||||
// Opcode.MSB -> TODO()
|
||||
// Opcode.B2WORD -> TODO()
|
||||
// Opcode.UB2UWORD -> TODO()
|
||||
// Opcode.MSB2WORD -> TODO()
|
||||
// Opcode.B2FLOAT -> TODO()
|
||||
// Opcode.UB2FLOAT -> TODO()
|
||||
// Opcode.W2FLOAT -> TODO()
|
||||
// Opcode.UW2FLOAT -> TODO()
|
||||
// Opcode.AND_BYTE -> TODO()
|
||||
// Opcode.AND_WORD -> TODO()
|
||||
// Opcode.OR_BYTE -> TODO()
|
||||
// Opcode.OR_WORD -> TODO()
|
||||
// Opcode.XOR_BYTE -> TODO()
|
||||
// Opcode.XOR_WORD -> TODO()
|
||||
// Opcode.NOT_BYTE -> TODO()
|
||||
// Opcode.NOT_WORD -> TODO()
|
||||
// Opcode.INC_B -> TODO()
|
||||
// Opcode.INC_UB -> TODO()
|
||||
// Opcode.INC_W -> TODO()
|
||||
// Opcode.INC_UW -> TODO()
|
||||
// Opcode.INC_F -> TODO()
|
||||
// Opcode.INC_VAR_B -> TODO()
|
||||
// Opcode.INC_VAR_UB -> TODO()
|
||||
// Opcode.INC_VAR_W -> TODO()
|
||||
// Opcode.INC_VAR_UW -> TODO()
|
||||
// Opcode.INC_VAR_F -> TODO()
|
||||
// Opcode.DEC_B -> TODO()
|
||||
// Opcode.DEC_UB -> TODO()
|
||||
// Opcode.DEC_W -> TODO()
|
||||
// Opcode.DEC_UW -> TODO()
|
||||
// Opcode.DEC_F -> TODO()
|
||||
// Opcode.DEC_VAR_B -> TODO()
|
||||
// Opcode.DEC_VAR_UB -> TODO()
|
||||
// Opcode.DEC_VAR_W -> TODO()
|
||||
// Opcode.DEC_VAR_UW -> TODO()
|
||||
// Opcode.DEC_VAR_F -> TODO()
|
||||
// Opcode.LESS_B -> TODO()
|
||||
// Opcode.LESS_UB -> TODO()
|
||||
// Opcode.LESS_W -> TODO()
|
||||
// Opcode.LESS_UW -> TODO()
|
||||
// Opcode.LESS_F -> TODO()
|
||||
// Opcode.GREATER_B -> TODO()
|
||||
// Opcode.GREATER_UB -> TODO()
|
||||
// Opcode.GREATER_W -> TODO()
|
||||
// Opcode.GREATER_UW -> TODO()
|
||||
// Opcode.GREATER_F -> TODO()
|
||||
// Opcode.LESSEQ_B -> TODO()
|
||||
// Opcode.LESSEQ_UB -> TODO()
|
||||
// Opcode.LESSEQ_W -> TODO()
|
||||
// Opcode.LESSEQ_UW -> TODO()
|
||||
// Opcode.LESSEQ_F -> TODO()
|
||||
// Opcode.GREATEREQ_B -> TODO()
|
||||
// Opcode.GREATEREQ_UB -> TODO()
|
||||
// Opcode.GREATEREQ_W -> TODO()
|
||||
// Opcode.GREATEREQ_UW -> TODO()
|
||||
// Opcode.GREATEREQ_F -> TODO()
|
||||
// Opcode.EQUAL_BYTE -> TODO()
|
||||
// Opcode.EQUAL_WORD -> TODO()
|
||||
// Opcode.EQUAL_F -> TODO()
|
||||
// Opcode.NOTEQUAL_BYTE -> TODO()
|
||||
// Opcode.NOTEQUAL_WORD -> TODO()
|
||||
// Opcode.NOTEQUAL_F -> TODO()
|
||||
// Opcode.READ_INDEXED_VAR_BYTE -> TODO()
|
||||
// Opcode.READ_INDEXED_VAR_WORD -> TODO()
|
||||
// Opcode.READ_INDEXED_VAR_FLOAT -> TODO()
|
||||
// Opcode.WRITE_INDEXED_VAR_BYTE -> TODO()
|
||||
// Opcode.WRITE_INDEXED_VAR_WORD -> TODO()
|
||||
// Opcode.WRITE_INDEXED_VAR_FLOAT -> TODO()
|
||||
// Opcode.JUMP -> TODO()
|
||||
// Opcode.BCS -> TODO()
|
||||
// Opcode.BCC -> TODO()
|
||||
// Opcode.BZ -> TODO()
|
||||
// Opcode.BNZ -> TODO()
|
||||
// Opcode.BNEG -> TODO()
|
||||
// Opcode.BPOS -> TODO()
|
||||
// Opcode.CALL -> TODO()
|
||||
// Opcode.RETURN -> TODO()
|
||||
// Opcode.SYSCALL -> TODO()
|
||||
// Opcode.BREAKPOINT -> TODO()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,9 @@ import kotlin.math.pow
|
||||
const val FLOAT_MAX_POSITIVE = 1.7014118345e+38
|
||||
const val FLOAT_MAX_NEGATIVE = -1.7014118345e+38
|
||||
|
||||
const val BASIC_LOAD_ADDRESS = 0x0801
|
||||
const val RAW_LOAD_ADDRESS = 0xc000
|
||||
|
||||
|
||||
class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
||||
|
@ -88,7 +88,7 @@ Directives
|
||||
- default for ``raw`` output is ``$c000``
|
||||
- default for ``prg`` output is ``$0801``
|
||||
- cannot be changed if you select ``prg`` with a ``basic`` launcher;
|
||||
then it is always ``$081d`` (immediately after the BASIC program), and the BASIC program itself is always at ``$0801``.
|
||||
then it is always ``$081e`` (immediately after the BASIC program), and the BASIC program itself is always at ``$0801``.
|
||||
This is because the C64 expects BASIC programs to start at this address.
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user