mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
fix several FP rom routine addresses on cx16.
This commit is contained in:
parent
17bedac96c
commit
f2273c0acc
@ -375,7 +375,7 @@ class AsmGen(internal val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
require(options.compTarget.memorySize(DataType.FLOAT) == 5)
|
require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"}
|
||||||
out(
|
out(
|
||||||
"""
|
"""
|
||||||
lda $indexName
|
lda $indexName
|
||||||
@ -406,7 +406,7 @@ class AsmGen(internal val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
require(options.compTarget.memorySize(DataType.FLOAT) == 5)
|
require(options.compTarget.memorySize(DataType.FLOAT) == 5) {"invalid float size ${expr.position}"}
|
||||||
out(
|
out(
|
||||||
"""
|
"""
|
||||||
lda $indexName
|
lda $indexName
|
||||||
@ -605,7 +605,7 @@ class AsmGen(internal val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun repeatWordCount(count: Int, stmt: RepeatLoop) {
|
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")
|
val repeatLabel = program.makeLabel("repeat")
|
||||||
if(isTargetCpu(CpuType.CPU65c02)) {
|
if(isTargetCpu(CpuType.CPU65c02)) {
|
||||||
val counterVar = createRepeatCounterVar(DataType.UWORD, true, stmt)
|
val counterVar = createRepeatCounterVar(DataType.UWORD, true, stmt)
|
||||||
@ -667,7 +667,7 @@ $repeatLabel lda $counterVar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun repeatByteCount(count: Int, stmt: RepeatLoop) {
|
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")
|
val repeatLabel = program.makeLabel("repeat")
|
||||||
if(isTargetCpu(CpuType.CPU65c02)) {
|
if(isTargetCpu(CpuType.CPU65c02)) {
|
||||||
val counterVar = createRepeatCounterVar(DataType.UBYTE, true, stmt)
|
val counterVar = createRepeatCounterVar(DataType.UBYTE, true, stmt)
|
||||||
@ -2940,7 +2940,7 @@ $repeatLabel lda $counterVar
|
|||||||
val parameter = target.subroutineParameter
|
val parameter = target.subroutineParameter
|
||||||
if(parameter!=null) {
|
if(parameter!=null) {
|
||||||
val sub = parameter.definingSubroutine!!
|
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 shouldKeepA = sub.asmParameterRegisters.any { it.registerOrPair==RegisterOrPair.AX || it.registerOrPair==RegisterOrPair.AY }
|
||||||
val reg = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)]
|
val reg = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)]
|
||||||
if(reg.statusflag!=null) {
|
if(reg.statusflag!=null) {
|
||||||
|
@ -330,7 +330,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
|||||||
if(discardResult || fcall !is BuiltinFunctionCall)
|
if(discardResult || fcall !is BuiltinFunctionCall)
|
||||||
throw AssemblyError("should not discard result of memory allocation at $fcall")
|
throw AssemblyError("should not discard result of memory allocation at $fcall")
|
||||||
val name = (fcall.args[0] as StringLiteral).value
|
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)
|
val slabname = IdentifierReference(listOf("prog8_slabs", "prog8_memoryslab_$name"), fcall.position)
|
||||||
slabname.linkParents(fcall)
|
slabname.linkParents(fcall)
|
||||||
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = AddressOf(slabname, fcall.position))
|
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = AddressOf(slabname, fcall.position))
|
||||||
|
@ -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
|
// 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.
|
// 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())
|
if(callee.parameters.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ internal class AsmAssignment(val source: AsmAssignSource,
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
if(target.register !in arrayOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY))
|
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)) {
|
require(memsizer.memorySize(source.datatype) <= memsizer.memorySize(target.datatype)) {
|
||||||
"source dt size must be less or equal to target dt size at $position"
|
"source dt size must be less or equal to target dt size at $position"
|
||||||
}
|
}
|
||||||
|
@ -809,7 +809,7 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
if(variable.origin!=VarDeclOrigin.USERCODE) {
|
if(variable.origin!=VarDeclOrigin.USERCODE) {
|
||||||
when(variable.datatype) {
|
when(variable.datatype) {
|
||||||
DataType.STR -> {
|
DataType.STR -> {
|
||||||
require(elementDt.isBytes)
|
require(elementDt.isBytes) { "must be byte string ${variable.position}" }
|
||||||
val stringVal = variable.value as StringLiteral
|
val stringVal = variable.value as StringLiteral
|
||||||
val varname = asmgen.asmVariableName(containment.iterable as IdentifierReference)
|
val varname = asmgen.asmVariableName(containment.iterable as IdentifierReference)
|
||||||
assignExpressionToRegister(containment.element, RegisterOrPair.A, elementDt istype DataType.BYTE)
|
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")
|
throw AssemblyError("containment check of floats not supported")
|
||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
require(elementDt.isInteger)
|
require(elementDt.isInteger) { "must be integer array ${variable.position}" }
|
||||||
val arrayVal = variable.value as ArrayLiteral
|
val arrayVal = variable.value as ArrayLiteral
|
||||||
val dt = elementDt.getOr(DataType.UNDEFINED)
|
val dt = elementDt.getOr(DataType.UNDEFINED)
|
||||||
val varname = asmgen.asmVariableName(containment.iterable as IdentifierReference)
|
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
|
// 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
|
// these will be correctly typecasted from a byte to a word value here
|
||||||
if(target.register !in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY))
|
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) {
|
when(target.kind) {
|
||||||
TargetStorageKind.VARIABLE -> {
|
TargetStorageKind.VARIABLE -> {
|
||||||
@ -2145,7 +2145,9 @@ internal class AssignmentAsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
|
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)
|
if(target.datatype==DataType.FLOAT)
|
||||||
throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer")
|
throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer")
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
) {
|
) {
|
||||||
fun translate(assign: AsmAssignment) {
|
fun translate(assign: AsmAssignment) {
|
||||||
require(assign.isAugmentable)
|
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!!) {
|
when (val value = assign.source.expression!!) {
|
||||||
is PrefixExpression -> {
|
is PrefixExpression -> {
|
||||||
|
@ -258,7 +258,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
else if(memory!=null) {
|
else if(memory!=null) {
|
||||||
require(vmDt== IRDataType.BYTE)
|
require(vmDt== IRDataType.BYTE) { "must be byte type ${memory.position}"}
|
||||||
if(zero) {
|
if(zero) {
|
||||||
if(memory.address is PtNumber) {
|
if(memory.address is PtNumber) {
|
||||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt()) }
|
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt()) }
|
||||||
|
@ -13,7 +13,9 @@ import prog8.intermediate.*
|
|||||||
|
|
||||||
internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||||
fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): IRCodeChunks {
|
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) {
|
return when (expr) {
|
||||||
is PtMachineRegister -> {
|
is PtMachineRegister -> {
|
||||||
@ -589,7 +591,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: IRDataType, resultRegister: Int): IRCodeChunks {
|
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<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val rightResultReg = codeGen.registers.nextFree()
|
val rightResultReg = codeGen.registers.nextFree()
|
||||||
if(binExpr.right is PtNumber) {
|
if(binExpr.right is PtNumber) {
|
||||||
|
@ -1086,7 +1086,9 @@ class IRCodeGen(
|
|||||||
is PtAsmSub -> {
|
is PtAsmSub -> {
|
||||||
if(child.address!=null) {
|
if(child.address!=null) {
|
||||||
// romsub. No codegen needed: calls to this are jumping straight to the address.
|
// 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 {
|
} else {
|
||||||
// regular asmsub
|
// regular asmsub
|
||||||
val assemblyChild = child.children.single() as PtInlineAssembly
|
val assemblyChild = child.children.single() as PtInlineAssembly
|
||||||
|
@ -174,7 +174,9 @@ class Inliner(val program: Program): AstWalker() {
|
|||||||
|
|
||||||
private fun possibleInlineFcallStmt(sub: Subroutine, origNode: Node, parent: Node): Iterable<IAstModification> {
|
private fun possibleInlineFcallStmt(sub: Subroutine, origNode: Node, parent: Node): Iterable<IAstModification> {
|
||||||
if(sub.inline && sub.parameters.isEmpty()) {
|
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) {
|
return if(sub.isAsmSubroutine) {
|
||||||
// simply insert the asm for the argument-less routine
|
// simply insert the asm for the argument-less routine
|
||||||
listOf(IAstModification.ReplaceNode(origNode, sub.statements.single().copy(), parent))
|
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<IAstModification> {
|
override fun before(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
||||||
val sub = functionCallExpr.target.targetStatement(program) as? Subroutine
|
val sub = functionCallExpr.target.targetStatement(program) as? Subroutine
|
||||||
if(sub!=null && sub.inline && sub.parameters.isEmpty()) {
|
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) {
|
return if(sub.isAsmSubroutine) {
|
||||||
// cannot inline assembly directly in the Ast here as an Asm node is not an expression....
|
// cannot inline assembly directly in the Ast here as an Asm node is not an expression....
|
||||||
noModifications
|
noModifications
|
||||||
|
@ -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 $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!!!]
|
; 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)
|
; (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 $fe0c = GETADR() clobbers(X) -> ubyte @ Y, ubyte @ A
|
||||||
romsub $fe0f = FLOATC() clobbers(A,X,Y) ; convert address to floating point
|
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)
|
romsub $fe6c = MOVAF() clobbers(A,X) ; copy fac1 to fac2 (rounded)
|
||||||
|
|
||||||
; X16 additions
|
; X16 additions
|
||||||
romsub $fe81 = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT
|
romsub $fe6f = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT
|
||||||
romsub $fe84 = ZEROFC() clobbers(A,X,Y) ; fac1 = 0
|
romsub $fe72 = ZEROFC() clobbers(A,X,Y) ; fac1 = 0
|
||||||
romsub $fe87 = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?)
|
romsub $fe75 = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?)
|
||||||
romsub $fe8a = NEGFAC() clobbers(A) ; switch the sign of fac1 (fac1 = -fac1) (juse use NEGOP() instead!)
|
romsub $fe78 = NEGFAC() clobbers(A) ; switch the sign of fac1 (fac1 = -fac1) (juse use NEGOP() instead!)
|
||||||
romsub $fe8d = MUL10() clobbers(A,X,Y) ; fac1 *= 10
|
romsub $fe7b = MUL10() clobbers(A,X,Y) ; fac1 *= 10
|
||||||
romsub $fe90 = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive!
|
romsub $fe7e = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive!
|
||||||
romsub $fe93 = MOVEF() clobbers(A,X) ; copy fac1 to fac2
|
romsub $fe81 = 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 $fe84 = 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 $fe87 = FLOAT() clobbers(A,X,Y) ; FAC = (u8).A
|
||||||
romsub $fe9c = FLOATS() clobbers(A,X,Y) ; FAC = (s16)facho+1:facho
|
romsub $fe8a = 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 $fe8d = 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 $fe90 = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
asmsub FREADSA (byte value @A) clobbers(A,X,Y) {
|
asmsub FREADSA (byte value @A) clobbers(A,X,Y) {
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
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.
|
- 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.
|
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
|
Note that bss can still contain variables that have @zp tag and those are already dealt with differently
|
||||||
|
Loading…
Reference in New Issue
Block a user