From f2273c0acc2cb98893d92a104ac9016eaf1a919b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 3 Dec 2022 19:56:54 +0100 Subject: [PATCH] fix several FP rom routine addresses on cx16. --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 10 +++---- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 2 +- .../codegen/cpu6502/FunctionCallAsmGen.kt | 2 +- .../cpu6502/assignment/AsmAssignment.kt | 2 +- .../cpu6502/assignment/AssignmentAsmGen.kt | 10 ++++--- .../assignment/AugmentableAssignmentAsmGen.kt | 4 ++- .../codegen/intermediate/AssignmentGen.kt | 2 +- .../codegen/intermediate/ExpressionGen.kt | 6 +++-- .../prog8/codegen/intermediate/IRCodeGen.kt | 4 ++- codeOptimizers/src/prog8/optimizer/Inliner.kt | 8 ++++-- compiler/res/prog8lib/cx16/floats.p8 | 27 ++++++++++--------- docs/source/todo.rst | 1 - 12 files changed, 45 insertions(+), 33 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 30a3aeaee..35adfaa5c 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -375,7 +375,7 @@ class AsmGen(internal val program: Program, } } DataType.FLOAT -> { - require(options.compTarget.memorySize(DataType.FLOAT) == 5) + require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"} out( """ lda $indexName @@ -406,7 +406,7 @@ class AsmGen(internal val program: Program, } } DataType.FLOAT -> { - require(options.compTarget.memorySize(DataType.FLOAT) == 5) + require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"} out( """ lda $indexName @@ -605,7 +605,7 @@ class AsmGen(internal val program: Program, } private fun repeatWordCount(count: Int, stmt: RepeatLoop) { - require(count in 257..65535) + require(count in 257..65535) { "invalid repeat count ${stmt.position}" } val repeatLabel = program.makeLabel("repeat") if(isTargetCpu(CpuType.CPU65c02)) { val counterVar = createRepeatCounterVar(DataType.UWORD, true, stmt) @@ -667,7 +667,7 @@ $repeatLabel lda $counterVar } private fun repeatByteCount(count: Int, stmt: RepeatLoop) { - require(count in 2..256) + require(count in 2..256) { "invalid repeat count ${stmt.position}" } val repeatLabel = program.makeLabel("repeat") if(isTargetCpu(CpuType.CPU65c02)) { val counterVar = createRepeatCounterVar(DataType.UBYTE, true, stmt) @@ -2940,7 +2940,7 @@ $repeatLabel lda $counterVar val parameter = target.subroutineParameter if(parameter!=null) { val sub = parameter.definingSubroutine!! - require(sub.isAsmSubroutine) { "push/pop arg passing only supported on asmsubs" } + require(sub.isAsmSubroutine) { "push/pop arg passing only supported on asmsubs ${sub.position}" } val shouldKeepA = sub.asmParameterRegisters.any { it.registerOrPair==RegisterOrPair.AX || it.registerOrPair==RegisterOrPair.AY } val reg = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)] if(reg.statusflag!=null) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 7ee7ef7df..12ab41db1 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -330,7 +330,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, if(discardResult || fcall !is BuiltinFunctionCall) throw AssemblyError("should not discard result of memory allocation at $fcall") val name = (fcall.args[0] as StringLiteral).value - require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name"} + require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"} val slabname = IdentifierReference(listOf("prog8_slabs", "prog8_memoryslab_$name"), fcall.position) slabname.linkParents(fcall) val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = AddressOf(slabname, fcall.position)) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 03ffa4efb..101b13d76 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -124,7 +124,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg // this is called when one or more of the arguments are 'complex' and // cannot be assigned to a register easily or risk clobbering other registers. - require(callee.isAsmSubroutine) + require(callee.isAsmSubroutine) { "register args only for asm subroutine ${callee.position}" } if(callee.parameters.isEmpty()) return diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt index 627a1db3a..8f01d7611 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AsmAssignment.kt @@ -207,7 +207,7 @@ internal class AsmAssignment(val source: AsmAssignSource, init { if(target.register !in arrayOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY)) - require(source.datatype != DataType.UNDEFINED) { "must not be placeholder/undefined datatype" } + require(source.datatype != DataType.UNDEFINED) { "must not be placeholder/undefined datatype at $position" } require(memsizer.memorySize(source.datatype) <= memsizer.memorySize(target.datatype)) { "source dt size must be less or equal to target dt size at $position" } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 90c7ae4bb..6fb15f63a 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -809,7 +809,7 @@ internal class AssignmentAsmGen(private val program: Program, if(variable.origin!=VarDeclOrigin.USERCODE) { when(variable.datatype) { DataType.STR -> { - require(elementDt.isBytes) + require(elementDt.isBytes) { "must be byte string ${variable.position}" } val stringVal = variable.value as StringLiteral val varname = asmgen.asmVariableName(containment.iterable as IdentifierReference) assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt istype DataType.BYTE) @@ -825,7 +825,7 @@ internal class AssignmentAsmGen(private val program: Program, throw AssemblyError("containment check of floats not supported") } in ArrayDatatypes -> { - require(elementDt.isInteger) + require(elementDt.isInteger) { "must be integer array ${variable.position}" } val arrayVal = variable.value as ArrayLiteral val dt = elementDt.getOr(DataType.UNDEFINED) val varname = asmgen.asmVariableName(containment.iterable as IdentifierReference) @@ -2056,7 +2056,7 @@ internal class AssignmentAsmGen(private val program: Program, // we make an exception in the type check for assigning something to a register pair AX, AY or XY // these will be correctly typecasted from a byte to a word value here if(target.register !in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) - require(target.datatype in ByteDatatypes) + require(target.datatype in ByteDatatypes) { "assign target must be byte type ${target.origAstTarget?.position ?: ""}"} when(target.kind) { TargetStorageKind.VARIABLE -> { @@ -2145,7 +2145,9 @@ internal class AssignmentAsmGen(private val program: Program, } internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { - require(target.datatype in NumericDatatypes || target.datatype in PassByReferenceDatatypes) + require(target.datatype in NumericDatatypes || target.datatype in PassByReferenceDatatypes) { + "assign target must be word type ${target.origAstTarget?.position ?: ""}" + } if(target.datatype==DataType.FLOAT) throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer") diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index d0b3abc2e..e185bf326 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -16,7 +16,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, ) { fun translate(assign: AsmAssignment) { require(assign.isAugmentable) - require(assign.source.kind== SourceStorageKind.EXPRESSION) + require(assign.source.kind == SourceStorageKind.EXPRESSION) { + "non-expression assign value should be handled elsewhere ${assign.position}" + } when (val value = assign.source.expression!!) { is PrefixExpression -> { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 9b53aacee..302427406 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -258,7 +258,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express return result } else if(memory!=null) { - require(vmDt== IRDataType.BYTE) + require(vmDt== IRDataType.BYTE) { "must be byte type ${memory.position}"} if(zero) { if(memory.address is PtNumber) { val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt()) } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 4527cdbe8..53a4196ac 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -13,7 +13,9 @@ import prog8.intermediate.* internal class ExpressionGen(private val codeGen: IRCodeGen) { fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks { - require(codeGen.registers.peekNext() > resultRegister || resultRegister >= SyscallRegisterBase) + require(codeGen.registers.peekNext() > resultRegister || resultRegister >= SyscallRegisterBase) { + "no more registers for expression ${expr.position}" + } return when (expr) { is PtMachineRegister -> { @@ -589,7 +591,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { } private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks { - require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported"} + require(vmDt!=IRDataType.FLOAT) {"floating-point modulo not supported ${binExpr.position}"} val result = mutableListOf() val rightResultReg = codeGen.registers.nextFree() if(binExpr.right is PtNumber) { diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 56463e496..8c5f6a1f8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1086,7 +1086,9 @@ class IRCodeGen( is PtAsmSub -> { if(child.address!=null) { // romsub. No codegen needed: calls to this are jumping straight to the address. - require(child.children.isEmpty()) + require(child.children.isEmpty()) { + "romsub should be empty at ${child.position}" + } } else { // regular asmsub val assemblyChild = child.children.single() as PtInlineAssembly diff --git a/codeOptimizers/src/prog8/optimizer/Inliner.kt b/codeOptimizers/src/prog8/optimizer/Inliner.kt index 7ab2a7558..122444345 100644 --- a/codeOptimizers/src/prog8/optimizer/Inliner.kt +++ b/codeOptimizers/src/prog8/optimizer/Inliner.kt @@ -174,7 +174,9 @@ class Inliner(val program: Program): AstWalker() { private fun possibleInlineFcallStmt(sub: Subroutine, origNode: Node, parent: Node): Iterable { if(sub.inline && sub.parameters.isEmpty()) { - require(sub.statements.size == 1 || (sub.statements.size == 2 && isEmptyReturn(sub.statements[1]))) + require(sub.statements.size == 1 || (sub.statements.size == 2 && isEmptyReturn(sub.statements[1]))) { + "invalid inline sub at ${sub.position}" + } return if(sub.isAsmSubroutine) { // simply insert the asm for the argument-less routine listOf(IAstModification.ReplaceNode(origNode, sub.statements.single().copy(), parent)) @@ -208,7 +210,9 @@ class Inliner(val program: Program): AstWalker() { override fun before(functionCallExpr: FunctionCallExpression, parent: Node): Iterable { val sub = functionCallExpr.target.targetStatement(program) as? Subroutine if(sub!=null && sub.inline && sub.parameters.isEmpty()) { - require(sub.statements.size==1 || (sub.statements.size==2 && isEmptyReturn(sub.statements[1]))) + require(sub.statements.size == 1 || (sub.statements.size == 2 && isEmptyReturn(sub.statements[1]))) { + "invalid inline sub at ${sub.position}" + } return if(sub.isAsmSubroutine) { // cannot inline assembly directly in the Ast here as an Asm node is not an expression.... noModifications diff --git a/compiler/res/prog8lib/cx16/floats.p8 b/compiler/res/prog8lib/cx16/floats.p8 index 35f3721ab..46431389d 100644 --- a/compiler/res/prog8lib/cx16/floats.p8 +++ b/compiler/res/prog8lib/cx16/floats.p8 @@ -29,7 +29,7 @@ romsub $fe03 = GIVAYF(ubyte lo @ Y, ubyte hi @ A) clobbers(A,X,Y) romsub $fe06 = FOUT() clobbers(X) -> uword @ AY ; fac1 -> string, address returned in AY ; romsub $fe09 = VAL_1() clobbers(A,X,Y) ; convert ASCII string to floating point [not yet implemented!!!] -; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) +; GETADR: fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) ; (tip: use GETADRAY to get A/Y output; lo/hi switched to normal little endian order) romsub $fe0c = GETADR() clobbers(X) -> ubyte @ Y, ubyte @ A romsub $fe0f = FLOATC() clobbers(A,X,Y) ; convert address to floating point @@ -68,18 +68,19 @@ romsub $fe69 = MOVFA() clobbers(A,X) ; copy fac2 to fac1 romsub $fe6c = MOVAF() clobbers(A,X) ; copy fac1 to fac2 (rounded) ; X16 additions -romsub $fe81 = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT -romsub $fe84 = ZEROFC() clobbers(A,X,Y) ; fac1 = 0 -romsub $fe87 = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?) -romsub $fe8a = NEGFAC() clobbers(A) ; switch the sign of fac1 (fac1 = -fac1) (juse use NEGOP() instead!) -romsub $fe8d = MUL10() clobbers(A,X,Y) ; fac1 *= 10 -romsub $fe90 = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive! -romsub $fe93 = MOVEF() clobbers(A,X) ; copy fac1 to fac2 -romsub $fe96 = SGN() clobbers(A,X,Y) ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) -romsub $fe99 = FLOAT() clobbers(A,X,Y) ; FAC = (u8).A -romsub $fe9c = FLOATS() clobbers(A,X,Y) ; FAC = (s16)facho+1:facho -romsub $fe9f = QINT() clobbers(A,X,Y) ; facho:facho+1:facho+2:facho+3 = u32(FAC) -romsub $fea2 = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A +romsub $fe6f = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT +romsub $fe72 = ZEROFC() clobbers(A,X,Y) ; fac1 = 0 +romsub $fe75 = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?) +romsub $fe78 = NEGFAC() clobbers(A) ; switch the sign of fac1 (fac1 = -fac1) (juse use NEGOP() instead!) +romsub $fe7b = MUL10() clobbers(A,X,Y) ; fac1 *= 10 +romsub $fe7e = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive! +romsub $fe81 = MOVEF() clobbers(A,X) ; copy fac1 to fac2 +romsub $fe84 = SGN() clobbers(A,X,Y) ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +romsub $fe87 = FLOAT() clobbers(A,X,Y) ; FAC = (u8).A +romsub $fe8a = FLOATS() clobbers(A,X,Y) ; FAC = (s16)facho+1:facho +romsub $fe8d = QINT() clobbers(A,X,Y) ; facho:facho+1:facho+2:facho+3 = u32(FAC) +romsub $fe90 = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A + asmsub FREADSA (byte value @A) clobbers(A,X,Y) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b929a10c8..27e4cb391 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- add more descriptions to require() calls (at least line number?) - 6502 codegen: create BSS section in output assembly code and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE if possible. Note that bss can still contain variables that have @zp tag and those are already dealt with differently