mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +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>
|
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()} }
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 -> {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user