From 067426016dabf408ddfab3f3ffba6d21ca79266d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 17 Oct 2018 01:01:01 +0200 Subject: [PATCH] more asm --- compiler/examples/test.p8 | 51 +++---- compiler/src/prog8/ast/AstChecker.kt | 10 ++ .../intermediate/IntermediateProgram.kt | 5 + .../src/prog8/compiler/intermediate/Opcode.kt | 10 -- .../src/prog8/compiler/target/c64/AsmGen.kt | 136 +++++++++++++----- .../compiler/target/c64/AssemblyProgram.kt | 2 +- .../prog8/optimizing/StatementOptimizer.kt | 2 +- compiler/src/prog8/stackvm/StackVm.kt | 50 ------- compiler/test/StackVMOpcodeTests.kt | 20 --- prog8lib/c64lib.p8 | 128 ++++++++--------- prog8lib/mathlib.p8 | 24 ++-- 11 files changed, 217 insertions(+), 221 deletions(-) diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 99f018279..bde920a8f 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,29 +1,5 @@ %import c64utils - -~ block2 $4000 { - return -} - -~ block3 $3000 { - return -} - -~ blockNoAddr1 { - return -} - -~ blockNoAddr2 { - return -} - -~ block4 $6000 { - return -} - -~ blockNoAddr3 { - return -} - +%import mathlib ~ main { @@ -33,10 +9,29 @@ sub start() { const ubyte border_color = 2 const ubyte cursor_color = 7 - c64.BGCOL0 = screen_color - c64.EXTCOL = border_color - c64.COLOR = cursor_color + ubyte ubb + uword uww + byte color + byte color2 + + AX=XY + uww=XY + AY=uww + + A++ + X++ + ;AY++ + + A = ~X + A = not Y + ubb = ~ubb + uww = ~uww + color2 = ~color + uww = not uww + return + + } } diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 2b1963953..e3790a5f4 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -544,6 +544,16 @@ class AstChecker(private val namespace: INameScope, return lv } + override fun process(expr: PrefixExpression): IExpression { + if(expr.operator=="-") { + val dt = expr.resultingDatatype(namespace, heap) + if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) { + checkResult.add(ExpressionError("can only take negative of a signed number type", expr.position)) + } + } + return super.process(expr) + } + override fun process(expr: BinaryExpression): IExpression { when(expr.operator){ "/", "//", "%" -> { diff --git a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt index 00a9fd912..26566c1dc 100644 --- a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt +++ b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt @@ -39,6 +39,11 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap fun optimize() { println("Optimizing stackVM code...") + // remove nops (that are not a label) + for (blk in blocks) { + blk.instructions.removeIf { it.opcode== Opcode.NOP && it !is LabelInstr } + } + optimizeDataConversionAndUselessDiscards() optimizeVariableCopying() optimizeMultipleSequentialLineInstrs() diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index eda41b185..49b83a0aa 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -143,21 +143,11 @@ enum class Opcode { NOT_WORD, // increment, decrement - INC_B, - INC_UB, - INC_W, - INC_UW, - INC_F, INC_VAR_B, INC_VAR_UB, INC_VAR_W, INC_VAR_UW, INC_VAR_F, - DEC_B, - DEC_UB, - DEC_W, - DEC_UW, - DEC_F, DEC_VAR_B, DEC_VAR_UB, DEC_VAR_W, diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 69c447e7a..1fc60c31b 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -17,16 +17,21 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, private lateinit var output: PrintWriter init { - // because 64tass understands scoped names via .proc / .block, + // Because 64tass understands scoped names via .proc / .block, // we'll strip the block prefix from all scoped names in the program. + // Also, convert invalid label names (such as "<<>>") to something that's allowed. val newblocks = mutableListOf() for(block in program.blocks) { val newvars = block.variables.map { symname(it.key, block) to it.value }.toMap().toMutableMap() val newlabels = block.labels.map { symname(it.key, block) to it.value}.toMap().toMutableMap() val newinstructions = block.instructions.asSequence().map { - it as? LabelInstr ?: 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) + 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) + } }.toMutableList() val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap() newblocks.add(IntermediateProgram.ProgramBlock( @@ -67,8 +72,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, return AssemblyProgram(program.name) } - private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock) = - if (scoped.startsWith("${block.shortname}.")) scoped.substring(block.shortname.length+1) else scoped + private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock): String { + val name = if (scoped.startsWith("${block.shortname}.")) scoped.substring(block.shortname.length+1) else scoped + val validName = name.replace("<<<", "prog8_").replace(">>>", "") + if(validName=="-") + return "-" + return validName.replace("-", "").replace(".", "_") + } + private fun copyFloat(source: String, target: String) { // todo: optimize this to bulk copy all floats in the same loop @@ -292,6 +303,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, private fun pushByte(byte: Int) { out("\tlda #${byte.toHex()}") + pushByteA() + } + + private fun pushByteA() { out("\tsta ${ESTACK_LO.toHex()},x") out("\tdex") } @@ -311,7 +326,14 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, private fun pushWord(word: Int) { out("\tlda #<${word.toHex()}") out("\tsta ${ESTACK_LO.toHex()},x") - out("\tlda #>${word.toHex()}") + out("\tlda #<${word.toHex()}") + out("\tsta ${ESTACK_HI.toHex()},x") + out("\tdex") + } + + private fun pushWordAY() { + out("\tsta ${ESTACK_LO.toHex()},x") + out("\ttya") out("\tsta ${ESTACK_HI.toHex()},x") out("\tdex") } @@ -350,6 +372,17 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, out("\tdex") } + private fun popByteA() { + out("\tinx") + out("\tlda ${ESTACK_LO.toHex()},x") + } + + private fun popWordAY() { + out("\ninx") + out("\tlda ${ESTACK_LO.toHex()},x") + out("\tldy ${ESTACK_HI.toHex()},x") + } + private fun instr2asm(insIdx: Int, ins: Instruction, block: IntermediateProgram.ProgramBlock): Int { if(ins is LabelInstr) { if(ins.name==block.shortname) @@ -369,6 +402,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.SEI -> out("\tsei") Opcode.CLI -> out("\tcli") Opcode.RETURN -> out("\trts") // todo is return really this simple? + Opcode.JUMP -> out("\tjmp ${ins.callLabel}") 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.RSAVE -> out("\tphp\n\tpha\n\ttxa\n\tpha\n\ttya\n\tpha") @@ -376,6 +410,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.DISCARD_BYTE -> out("\tinx") // remove 1 (2) bytes from stack Opcode.DISCARD_WORD -> out("\tinx") // remove 2 bytes from stack Opcode.DISCARD_FLOAT -> out("\tinx\n\tinx\n\tinx") // remove 5 (6) bytes from stack + Opcode.INLINE_ASSEMBLY -> out(ins.callLabel) // All of the inline assembly is stored in the calllabel property. Opcode.COPY_VAR_BYTE -> { when { ins.callLabel2 in registerStrings -> { @@ -504,6 +539,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, return 1 // skip 1 } // byte from variable onto stack + TODO("can be register") pushVarByte(ins.callLabel!!) } Opcode.PUSH_WORD -> { @@ -579,6 +615,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, return 1 // skip 1 } // word from memory onto stack + TODO("can be register") pushVarWord(ins.callLabel!!) } Opcode.PUSH_FLOAT -> { @@ -630,44 +667,79 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, } pushFloat(ins.arg!!.integerValue().toHex()) } - Opcode.INLINE_ASSEMBLY -> out(ins.callLabel) // All of the inline assembly is stored in the calllabel property. + Opcode.INC_VAR_UB, Opcode.INC_VAR_B -> { + TODO("can be register") + out("\tinc ${ins.callLabel}") + } + Opcode.DEC_VAR_UB, Opcode.DEC_VAR_B -> { + TODO("can be register") + out("\tdec ${ins.callLabel}") + } + Opcode.ADD_UB, Opcode.ADD_B -> { + out("\tlda ${(ESTACK_LO+2).toHex()},x") + out("\tclc\n\tadc ${(ESTACK_LO+1).toHex()},x") + out("\tsta ${(ESTACK_LO+2).toHex()},x") + out("\tinx") + } + Opcode.SUB_UB, Opcode.SUB_B -> { + out("\tlda ${(ESTACK_LO+2).toHex()},x") + out("\tsec\n\tsbc ${(ESTACK_LO+1).toHex()},x") + out("\tsta ${(ESTACK_LO+2).toHex()},x") + out("\tinx") + } + Opcode.POP_MEM_UB, Opcode.POP_MEM_B -> { + popByteA() + out("\tsta ${ins.arg!!.integerValue().toHex()}") + } + Opcode.POP_VAR_BYTE -> { + popByteA() + TODO("can be register") + out("\tsta ${ins.callLabel}") + } + Opcode.POP_VAR_WORD -> { + popWordAY() + TODO("can be register") + out("\tsta ${ins.callLabel}") + out("\tsty ${ins.callLabel}+1") + } + Opcode.NEG_B -> { + popByteA() + out("\teor #\$ff") + out("\tsec\n\tadc #0") + pushByteA() + } + Opcode.INV_BYTE, Opcode.NOT_BYTE -> { + popByteA() + out("\teor #\$ff") + pushByteA() + } + Opcode.INV_WORD, Opcode.NOT_WORD -> { + popWordAY() + out("\teor #\$ff") + out("\tpha") + out("\ttya") + out("\teor #\$ff") + out("\ttay") + out("\tpla") + pushWordAY() + } + else-> TODO("asm for $ins") -// 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_FLOAT -> 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.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() @@ -696,7 +768,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // 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() @@ -741,8 +812,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // 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() @@ -758,8 +827,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // Opcode.OR_WORD -> TODO() // Opcode.XOR_BYTE -> TODO() // Opcode.XOR_WORD -> TODO() -// Opcode.NOT_BYTE -> TODO() -// Opcode.NOT_WORD -> TODO() // Opcode.LESS_B -> TODO() // Opcode.LESS_UB -> TODO() // Opcode.LESS_W -> TODO() @@ -792,7 +859,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // 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() diff --git a/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt index 1322edd9c..4f949cb81 100644 --- a/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt +++ b/compiler/src/prog8/compiler/target/c64/AssemblyProgram.kt @@ -13,7 +13,7 @@ class AssemblyProgram(val name: String) { println("Generating machine code program...") val command = mutableListOf("64tass", "--ascii", "--case-sensitive", "-Wall", "-Wno-strict-bool", - "--dump-labels", "--vice-labels", "-l", viceMonListFile, "--no-monitor") + "-Werror", "--dump-labels", "--vice-labels", "-l", viceMonListFile, "--no-monitor") val outFile = when(options.output) { OutputType.PRG -> { diff --git a/compiler/src/prog8/optimizing/StatementOptimizer.kt b/compiler/src/prog8/optimizing/StatementOptimizer.kt index b754ea90a..1dd4f4fab 100644 --- a/compiler/src/prog8/optimizing/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizing/StatementOptimizer.kt @@ -13,7 +13,7 @@ import prog8.functions.BuiltinFunctions todo remove if statements with empty statement blocks todo replace if statements with only else block todo statement optimization: create augmented assignment from assignment that only refers to its lvalue (A=A+10, A=4*A, ...) - todo statement optimization: X+=1, X-=1 --> X++/X-- , + todo statement optimization: X+=1, X-=1 --> X++/X-- (to 3? 4? incs/decs in a row after that use arithmetic) todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc todo optimize addition with self into shift 1 (A+=A -> A<<=1) todo assignment optimization: optimize some simple multiplications and divisions into shifts (A*=2 -> lsl(A), X=X/2 -> lsr(X) ) diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index bca29e8d5..d6976e7ee 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -633,56 +633,6 @@ class StackVm(private var traceOutputFile: String?) { checkDt(v, DataType.UWORD) evalstack.push(v.inv()) } - Opcode.INC_B -> { - val v = evalstack.pop() - checkDt(v, DataType.BYTE) - evalstack.push(v.inc()) - } - Opcode.INC_UB -> { - val v = evalstack.pop() - checkDt(v, DataType.UBYTE) - evalstack.push(v.inc()) - } - Opcode.INC_W -> { - val v = evalstack.pop() - checkDt(v, DataType.WORD) - evalstack.push(v.inc()) - } - Opcode.INC_UW -> { - val v = evalstack.pop() - checkDt(v, DataType.UWORD) - evalstack.push(v.inc()) - } - Opcode.INC_F -> { - val v = evalstack.pop() - checkDt(v, DataType.FLOAT) - evalstack.push(v.inc()) - } - Opcode.DEC_UB -> { - val v = evalstack.pop() - checkDt(v, DataType.UBYTE) - evalstack.push(v.dec()) - } - Opcode.DEC_B -> { - val v = evalstack.pop() - checkDt(v, DataType.BYTE) - evalstack.push(v.dec()) - } - Opcode.DEC_UW -> { - val v = evalstack.pop() - checkDt(v, DataType.UWORD) - evalstack.push(v.dec()) - } - Opcode.DEC_W -> { - val v = evalstack.pop() - checkDt(v, DataType.WORD) - evalstack.push(v.dec()) - } - Opcode.DEC_F -> { - val v = evalstack.pop() - checkDt(v, DataType.FLOAT) - evalstack.push(v.dec()) - } Opcode.SYSCALL -> dispatchSyscall(ins) Opcode.SEC -> P_carry = true Opcode.CLC -> P_carry = false diff --git a/compiler/test/StackVMOpcodeTests.kt b/compiler/test/StackVMOpcodeTests.kt index 9bce56d1a..24a7edfef 100644 --- a/compiler/test/StackVMOpcodeTests.kt +++ b/compiler/test/StackVMOpcodeTests.kt @@ -424,26 +424,6 @@ class TestStackVmOpcodes { testUnaryOperator(Value(DataType.UWORD, 5000), Opcode.NOT_WORD, Value(DataType.UBYTE, 0)) } - @Test - fun testInc() { - testUnaryOperator(Value(DataType.UBYTE, 255), Opcode.INC_UB, Value(DataType.UBYTE, 0)) - testUnaryOperator(Value(DataType.UBYTE, 99), Opcode.INC_UB, Value(DataType.UBYTE, 100)) - testUnaryOperator(Value(DataType.UWORD, 65535), Opcode.INC_UW, Value(DataType.UWORD, 0)) - testUnaryOperator(Value(DataType.UWORD, 999), Opcode.INC_UW, Value(DataType.UWORD, 1000)) - testUnaryOperator(Value(DataType.FLOAT, -1.0), Opcode.INC_F, Value(DataType.FLOAT, 0.0)) - testUnaryOperator(Value(DataType.FLOAT, 2022.5), Opcode.INC_F, Value(DataType.FLOAT, 2023.5)) - } - - @Test - fun testDec() { - testUnaryOperator(Value(DataType.UBYTE, 100), Opcode.DEC_UB, Value(DataType.UBYTE, 99)) - testUnaryOperator(Value(DataType.UBYTE, 0), Opcode.DEC_UB, Value(DataType.UBYTE, 255)) - testUnaryOperator(Value(DataType.UWORD, 1000), Opcode.DEC_UW, Value(DataType.UWORD, 999)) - testUnaryOperator(Value(DataType.UWORD, 0), Opcode.DEC_UW, Value(DataType.UWORD, 65535)) - testUnaryOperator(Value(DataType.FLOAT, 0.5), Opcode.DEC_F, Value(DataType.FLOAT, -0.5)) - testUnaryOperator(Value(DataType.FLOAT, 2022.5), Opcode.DEC_F, Value(DataType.FLOAT, 2021.5)) - } - @Test fun testNeg() { testUnaryOperator(Value(DataType.BYTE, 12), Opcode.NEG_B, Value(DataType.BYTE, -12)) diff --git a/prog8lib/c64lib.p8 b/prog8lib/c64lib.p8 index 187546198..e2282b86d 100644 --- a/prog8lib/c64lib.p8 +++ b/prog8lib/c64lib.p8 @@ -7,80 +7,80 @@ ~ c64 { - memory byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP - memory byte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP - memory word SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) - memory word SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) + memory ubyte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP + memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP + memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) + memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) - memory byte TIME_HI = $a0 ; software jiffy clock, hi byte - memory byte TIME_MID = $a1 ; .. mid byte - memory byte TIME_LO = $a2 ; .. lo byte. Updated by IRQ every 1/60 sec - memory byte STKEY = $91 ; various keyboard statuses (updated by IRQ) - memory byte SFDX = $cb ; current key pressed (matrix value) (updated by IRQ) + memory ubyte TIME_HI = $a0 ; software jiffy clock, hi byte + memory ubyte TIME_MID = $a1 ; .. mid byte + memory ubyte TIME_LO = $a2 ; .. lo byte. Updated by IRQ every 1/60 sec + memory ubyte STKEY = $91 ; various keyboard statuses (updated by IRQ) + memory ubyte SFDX = $cb ; current key pressed (matrix value) (updated by IRQ) - memory byte COLOR = $0286 ; cursor color - memory byte HIBASE = $0288 ; screen base address / 256 (hi-byte of screen memory address) - memory word CINV = $0314 ; IRQ vector - memory word NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in - memory word RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in - memory word IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in + memory ubyte COLOR = $0286 ; cursor color + memory ubyte HIBASE = $0288 ; screen base address / 256 (hi-byte of screen memory address) + memory uword CINV = $0314 ; IRQ vector + memory uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in + memory uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in + memory uword IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in - memory byte[40, 25] Screen = $0400 ; default character screen matrix - memory byte[40, 25] Colors = $d800 ; character screen colors + memory ubyte[40, 25] Screen = $0400 ; default character screen matrix + memory ubyte[40, 25] Colors = $d800 ; character screen colors ; ---- VIC-II registers ---- - memory byte SP0X = $d000 - memory byte SP0Y = $d001 - memory byte SP1X = $d002 - memory byte SP1Y = $d003 - memory byte SP2X = $d004 - memory byte SP2Y = $d005 - memory byte SP3X = $d006 - memory byte SP3Y = $d007 - memory byte SP4X = $d008 - memory byte SP4Y = $d009 - memory byte SP5X = $d00a - memory byte SP5Y = $d00b - memory byte SP6X = $d00c - memory byte SP6Y = $d00d - memory byte SP7X = $d00e - memory byte SP7Y = $d00f + memory ubyte SP0X = $d000 + memory ubyte SP0Y = $d001 + memory ubyte SP1X = $d002 + memory ubyte SP1Y = $d003 + memory ubyte SP2X = $d004 + memory ubyte SP2Y = $d005 + memory ubyte SP3X = $d006 + memory ubyte SP3Y = $d007 + memory ubyte SP4X = $d008 + memory ubyte SP4Y = $d009 + memory ubyte SP5X = $d00a + memory ubyte SP5Y = $d00b + memory ubyte SP6X = $d00c + memory ubyte SP6Y = $d00d + memory ubyte SP7X = $d00e + memory ubyte SP7Y = $d00f - memory byte MSIGX = $d010 - memory byte SCROLY = $d011 - memory byte RASTER = $d012 - memory byte LPENX = $d013 - memory byte LPENY = $d014 - memory byte SPENA = $d015 - memory byte SCROLX = $d016 - memory byte YXPAND = $d017 - memory byte VMCSB = $d018 - memory byte VICIRQ = $d019 - memory byte IREQMASK = $d01a - memory byte SPBGPR = $d01b - memory byte SPMC = $d01c - memory byte XXPAND = $d01d - memory byte SPSPCL = $d01e - memory byte SPBGCL = $d01f + memory ubyte MSIGX = $d010 + memory ubyte SCROLY = $d011 + memory ubyte RASTER = $d012 + memory ubyte LPENX = $d013 + memory ubyte LPENY = $d014 + memory ubyte SPENA = $d015 + memory ubyte SCROLX = $d016 + memory ubyte YXPAND = $d017 + memory ubyte VMCSB = $d018 + memory ubyte VICIRQ = $d019 + memory ubyte IREQMASK = $d01a + memory ubyte SPBGPR = $d01b + memory ubyte SPMC = $d01c + memory ubyte XXPAND = $d01d + memory ubyte SPSPCL = $d01e + memory ubyte SPBGCL = $d01f - memory byte EXTCOL = $d020 ; border color - memory byte BGCOL0 = $d021 ; screen color - memory byte BGCOL1 = $d022 - memory byte BGCOL2 = $d023 - memory byte BGCOL4 = $d024 - memory byte SPMC0 = $d025 - memory byte SPMC1 = $d026 - memory byte SP0COL = $d027 - memory byte SP1COL = $d028 - memory byte SP2COL = $d029 - memory byte SP3COL = $d02a - memory byte SP4COL = $d02b - memory byte SP5COL = $d02c - memory byte SP6COL = $d02d - memory byte SP7COL = $d02e + memory ubyte EXTCOL = $d020 ; border color + memory ubyte BGCOL0 = $d021 ; screen color + memory ubyte BGCOL1 = $d022 + memory ubyte BGCOL2 = $d023 + memory ubyte BGCOL4 = $d024 + memory ubyte SPMC0 = $d025 + memory ubyte SPMC1 = $d026 + memory ubyte SP0COL = $d027 + memory ubyte SP1COL = $d028 + memory ubyte SP2COL = $d029 + memory ubyte SP3COL = $d02a + memory ubyte SP4COL = $d02b + memory ubyte SP5COL = $d02c + memory ubyte SP6COL = $d02d + memory ubyte SP7COL = $d02e ; ---- end of VIC-II registers ---- diff --git a/prog8lib/mathlib.p8 b/prog8lib/mathlib.p8 index b4a321f84..2cb1ba6b1 100644 --- a/prog8lib/mathlib.p8 +++ b/prog8lib/mathlib.p8 @@ -12,14 +12,14 @@ ~ math { ; note: the following ZP scratch registers must be the same as in c64lib - memory byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP - memory byte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP - memory word SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) - memory word SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) + memory ubyte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP + memory ubyte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP + memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) + memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) -sub multiply_bytes (byte1: X, byte2: Y) -> (A, X?) { +asmsub multiply_bytes (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(X) -> (ubyte @ A) { ; ---- multiply 2 bytes, result as byte in A (signed or unsigned) %asm {{ stx SCRATCH_ZP1 @@ -37,7 +37,7 @@ sub multiply_bytes (byte1: X, byte2: Y) -> (A, X?) { } -sub multiply_bytes_16 (byte1: X, byte2: Y) -> (A?, XY) { +asmsub multiply_bytes_16 (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(A) -> (uword @ XY) { ; ---- multiply 2 bytes, result as word in X/Y (unsigned) %asm {{ lda #0 @@ -58,7 +58,7 @@ _m_with_add stx SCRATCH_ZP1 }} } -sub multiply_bytes_addA_16 (byte1: X, byte2: Y, add: A) -> (A?, XY) { +asmsub multiply_bytes_addA_16 (byte1: ubyte @ X, byte2: ubyte @ Y, add: ubyte @ A) -> clobbers(A) -> (uword @ XY) { ; ---- multiply 2 bytes and add A, result as word in X/Y (unsigned) %asm {{ jmp multiply_bytes_16._m_with_add @@ -66,7 +66,7 @@ sub multiply_bytes_addA_16 (byte1: X, byte2: Y, add: A) -> (A?, XY) { } word[2] multiply_words_product = 0 -sub multiply_words (number: XY) -> (?) { +asmsub multiply_words (number: uword @ XY) -> clobbers(A,X) -> () { ; ---- multiply two 16-bit words into a 32-bit result ; input: X/Y = first 16-bit number, SCRATCH_ZPWORD1 in ZP = second 16-bit number ; output: multiply_words_product 32-bits product, LSB order (low-to-high) @@ -100,7 +100,7 @@ mult16 lda #$00 } -sub divmod_bytes (number: X, divisor: Y) -> (X, A) { +asmsub divmod_bytes (number: ubyte @ X, divisor: ubyte @ Y) -> clobbers() -> (ubyte @ X, ubyte @ A) { ; ---- divide X by Y, result quotient in X, remainder in A (unsigned) ; division by zero will result in quotient = 255 and remainder = original number %asm {{ @@ -123,7 +123,7 @@ sub divmod_bytes (number: X, divisor: Y) -> (X, A) { }} } -sub divmod_words (divisor: XY) -> (A?, XY) { +asmsub divmod_words (divisor: uword @ XY) -> clobbers(A) -> (uword @ XY) { ; ---- divide two words (16 bit each) into 16 bit results ; input: SCRATCH_ZPWORD1 in ZP: 16 bit number, X/Y: 16 bit divisor ; output: SCRATCH_ZPWORD1 in ZP: 16 bit result, X/Y: 16 bit remainder @@ -172,7 +172,7 @@ remainder = SCRATCH_ZP1 } -sub randbyte () -> (A) { +asmsub randbyte () -> clobbers() -> (ubyte @ A) { ; ---- 8-bit pseudo random number generator into A %asm {{ @@ -194,7 +194,7 @@ _magiceors .byte $1d, $2b, $2d, $4d, $5f, $63, $65, $69 }} } -sub randword () -> (XY) { +asmsub randword () -> clobbers() -> (uword @ XY) { ; ---- 16 bit pseudo random number generator into XY %asm {{