mirror of
https://github.com/irmen/prog8.git
synced 2025-02-04 02:30:19 +00:00
improved parsing of cpu registers (no more crash when invalid register) also adding CommanderX16 virtual registers language support
This commit is contained in:
parent
b7c1450121
commit
daaa83ee7d
@ -272,13 +272,13 @@ private class AsmSubroutineReturn(val type: DataType,
|
||||
|
||||
private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn>
|
||||
= asmsub_return().map {
|
||||
val register = it.identifier()?.toAst()
|
||||
val register = it.register().text
|
||||
var registerorpair: RegisterOrPair? = null
|
||||
var statusregister: Statusflag? = null
|
||||
if(register!=null) {
|
||||
when (val name = register.nameInSource.single()) {
|
||||
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(name)
|
||||
in Statusflag.names -> statusregister = Statusflag.valueOf(name)
|
||||
when (register) {
|
||||
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(register)
|
||||
in Statusflag.names -> statusregister = Statusflag.valueOf(register)
|
||||
else -> throw FatalAstException("invalid register or status flag in $it")
|
||||
}
|
||||
}
|
||||
@ -293,14 +293,14 @@ private fun prog8Parser.Asmsub_paramsContext.toAst(): List<AsmSubroutineParamete
|
||||
= asmsub_param().map {
|
||||
val vardecl = it.vardecl()
|
||||
val datatype = vardecl.datatype()?.toAst() ?: DataType.STRUCT
|
||||
val register = it.identifier()?.toAst()
|
||||
val register = it.register().text
|
||||
var registerorpair: RegisterOrPair? = null
|
||||
var statusregister: Statusflag? = null
|
||||
if(register!=null) {
|
||||
when (val name = register.nameInSource.single()) {
|
||||
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(name)
|
||||
in Statusflag.names -> statusregister = Statusflag.valueOf(name)
|
||||
else -> throw FatalAstException("invalid register or status flag '$name'")
|
||||
when (register) {
|
||||
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(register)
|
||||
in Statusflag.names -> statusregister = Statusflag.valueOf(register)
|
||||
else -> throw FatalAstException("invalid register or status flag '$register'")
|
||||
}
|
||||
}
|
||||
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister, toPosition())
|
||||
@ -371,7 +371,7 @@ private fun prog8Parser.Assign_targetContext.toAst() : AssignTarget {
|
||||
}
|
||||
|
||||
private fun prog8Parser.ClobberContext.toAst() : Set<CpuRegister> {
|
||||
val names = this.identifier().map { it.toAst().nameInSource.single() }
|
||||
val names = this.cpuregister().map { it.text }
|
||||
return names.map { CpuRegister.valueOf(it) }.toSet()
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,10 @@ enum class RegisterOrPair {
|
||||
AY,
|
||||
XY,
|
||||
FAC1,
|
||||
FAC2;
|
||||
FAC2,
|
||||
// cx16 virtual registers:
|
||||
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||
R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
|
||||
companion object {
|
||||
val names by lazy { values().map { it.toString()} }
|
||||
|
@ -77,6 +77,22 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
||||
RegisterOrPair.XY -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.UWORD, scope, register = registers)
|
||||
RegisterOrPair.FAC1,
|
||||
RegisterOrPair.FAC2 -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.FLOAT, scope, register = registers)
|
||||
RegisterOrPair.R0,
|
||||
RegisterOrPair.R1,
|
||||
RegisterOrPair.R2,
|
||||
RegisterOrPair.R3,
|
||||
RegisterOrPair.R4,
|
||||
RegisterOrPair.R5,
|
||||
RegisterOrPair.R6,
|
||||
RegisterOrPair.R7,
|
||||
RegisterOrPair.R8,
|
||||
RegisterOrPair.R9,
|
||||
RegisterOrPair.R10,
|
||||
RegisterOrPair.R11,
|
||||
RegisterOrPair.R12,
|
||||
RegisterOrPair.R13,
|
||||
RegisterOrPair.R14,
|
||||
RegisterOrPair.R15 -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.UWORD, scope, register = registers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1331,7 +1331,18 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
RegisterOrPair.AX -> asmgen.out(" lda #<${word.toHex()} | ldx #>${word.toHex()}")
|
||||
RegisterOrPair.AY -> asmgen.out(" lda #<${word.toHex()} | ldy #>${word.toHex()}")
|
||||
RegisterOrPair.XY -> asmgen.out(" ldx #<${word.toHex()} | ldy #>${word.toHex()}")
|
||||
else -> throw AssemblyError("can't assign word to single byte register")
|
||||
RegisterOrPair.R0, RegisterOrPair.R1, RegisterOrPair.R2, RegisterOrPair.R3,
|
||||
RegisterOrPair.R4, RegisterOrPair.R5, RegisterOrPair.R6, RegisterOrPair.R7,
|
||||
RegisterOrPair.R8, RegisterOrPair.R9, RegisterOrPair.R10, RegisterOrPair.R11,
|
||||
RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15 -> {
|
||||
asmgen.out("""
|
||||
lda #<${word.toHex()}
|
||||
sta cx16.${target.register.toString().toLowerCase()}
|
||||
lda #>${word.toHex()}
|
||||
sta cx16.${target.register.toString().toLowerCase()}+1
|
||||
""")
|
||||
}
|
||||
else -> throw AssemblyError("invalid register for word value")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.STACK -> {
|
||||
|
@ -7,15 +7,10 @@
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub start () {
|
||||
float x = floo()
|
||||
floats.print_f(x2)
|
||||
test_stack.test2()
|
||||
blerp=foobar+xxx
|
||||
}
|
||||
|
||||
sub floo() -> float {
|
||||
float fl = 1.1
|
||||
return flxxx * 2
|
||||
romsub $ff2c = GRAPH_draw_line(uword x1 @R0, uword y1 @R1, uword x2 @R2, uword y2 @R3) clobbers(A,X,Y) ; uses x1=r0, y1=r1, x2=r2, y2=r3
|
||||
|
||||
sub start () {
|
||||
GRAPH_draw_line(1,2,3,4)
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,9 @@ ARRAYSIG :
|
||||
;
|
||||
|
||||
|
||||
cpuregister: 'A' | 'X' | 'Y';
|
||||
register: 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' | 'Pc' | 'Pz' | 'Pn' | 'Pv' | 'R0' | 'R1' | 'R2' | 'R3' | 'R4' | 'R5' | 'R6' | 'R7' | 'R8' | 'R9' | 'R10' | 'R11' | 'R12' | 'R13' | 'R14' | 'R15';
|
||||
|
||||
module : (directive | block | EOL)* EOF ;
|
||||
|
||||
block: identifier integerliteral? '{' EOL (block_statement | EOL) * '}' EOL ;
|
||||
@ -271,15 +274,15 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns?
|
||||
|
||||
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
||||
|
||||
asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed.
|
||||
asmsub_param : vardecl '@' register ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed.
|
||||
|
||||
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
||||
|
||||
clobber : identifier (',' identifier)* ; // A,X,Y allowed
|
||||
clobber : cpuregister (',' cpuregister)* ; // A,X,Y allowed
|
||||
|
||||
asmsub_returns : '->' asmsub_return (',' EOL? asmsub_return)* ;
|
||||
|
||||
asmsub_return : datatype '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||
asmsub_return : datatype '@' register ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||
|
||||
|
||||
if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later
|
||||
|
Loading…
x
Reference in New Issue
Block a user