improved parsing of cpu registers (no more crash when invalid register) also adding CommanderX16 virtual registers language support

This commit is contained in:
Irmen de Jong 2020-12-21 19:19:53 +01:00
parent b7c1450121
commit daaa83ee7d
6 changed files with 52 additions and 24 deletions

View File

@ -272,13 +272,13 @@ private class AsmSubroutineReturn(val type: DataType,
private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn> private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn>
= asmsub_return().map { = asmsub_return().map {
val register = it.identifier()?.toAst() val register = it.register().text
var registerorpair: RegisterOrPair? = null var registerorpair: RegisterOrPair? = null
var statusregister: Statusflag? = null var statusregister: Statusflag? = null
if(register!=null) { if(register!=null) {
when (val name = register.nameInSource.single()) { when (register) {
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(name) in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(register)
in Statusflag.names -> statusregister = Statusflag.valueOf(name) in Statusflag.names -> statusregister = Statusflag.valueOf(register)
else -> throw FatalAstException("invalid register or status flag in $it") 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 { = asmsub_param().map {
val vardecl = it.vardecl() val vardecl = it.vardecl()
val datatype = vardecl.datatype()?.toAst() ?: DataType.STRUCT val datatype = vardecl.datatype()?.toAst() ?: DataType.STRUCT
val register = it.identifier()?.toAst() val register = it.register().text
var registerorpair: RegisterOrPair? = null var registerorpair: RegisterOrPair? = null
var statusregister: Statusflag? = null var statusregister: Statusflag? = null
if(register!=null) { if(register!=null) {
when (val name = register.nameInSource.single()) { when (register) {
in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(name) in RegisterOrPair.names -> registerorpair = RegisterOrPair.valueOf(register)
in Statusflag.names -> statusregister = Statusflag.valueOf(name) in Statusflag.names -> statusregister = Statusflag.valueOf(register)
else -> throw FatalAstException("invalid register or status flag '$name'") else -> throw FatalAstException("invalid register or status flag '$register'")
} }
} }
AsmSubroutineParameter(vardecl.varname.text, datatype, registerorpair, statusregister, toPosition()) 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> { 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() return names.map { CpuRegister.valueOf(it) }.toSet()
} }

View File

@ -82,7 +82,10 @@ enum class RegisterOrPair {
AY, AY,
XY, XY,
FAC1, FAC1,
FAC2; FAC2,
// cx16 virtual registers:
R0, R1, R2, R3, R4, R5, R6, R7,
R8, R9, R10, R11, R12, R13, R14, R15;
companion object { companion object {
val names by lazy { values().map { it.toString()} } val names by lazy { values().map { it.toString()} }

View File

@ -77,6 +77,22 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
RegisterOrPair.XY -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.UWORD, scope, register = registers) RegisterOrPair.XY -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.UWORD, scope, register = registers)
RegisterOrPair.FAC1, RegisterOrPair.FAC1,
RegisterOrPair.FAC2 -> AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, DataType.FLOAT, scope, register = registers) 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)
} }
} }
} }

View File

@ -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.AX -> asmgen.out(" lda #<${word.toHex()} | ldx #>${word.toHex()}")
RegisterOrPair.AY -> asmgen.out(" lda #<${word.toHex()} | ldy #>${word.toHex()}") RegisterOrPair.AY -> asmgen.out(" lda #<${word.toHex()} | ldy #>${word.toHex()}")
RegisterOrPair.XY -> asmgen.out(" ldx #<${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 -> { TargetStorageKind.STACK -> {

View File

@ -7,15 +7,10 @@
%option no_sysinit %option no_sysinit
main { main {
sub start () {
float x = floo()
floats.print_f(x2)
test_stack.test2()
blerp=foobar+xxx
}
sub floo() -> float { 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
float fl = 1.1
return flxxx * 2 sub start () {
GRAPH_draw_line(1,2,3,4)
} }
} }

View File

@ -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 ; module : (directive | block | EOL)* EOF ;
block: identifier integerliteral? '{' EOL (block_statement | EOL) * '}' EOL ; 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_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? ')' ; 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_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 if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later