diff --git a/compiler/antlr/prog8.g4 b/compiler/antlr/prog8.g4 index ba3ae8f02..488e5e364 100644 --- a/compiler/antlr/prog8.g4 +++ b/compiler/antlr/prog8.g4 @@ -71,6 +71,7 @@ statement : | if_stmt | branch_stmt | subroutine + | asmsubroutine | inlineasm | returnstmt | forloop @@ -171,6 +172,8 @@ scoped_identifier : NAME ('.' NAME)+ ; register : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ; +statusregister : 'Pc' | 'Pz' | 'Pn' | 'Pv' ; + integerliteral : intpart=(DEC_INTEGER | HEX_INTEGER | BIN_INTEGER) wordsuffix? ; wordsuffix : '.w' ; @@ -198,7 +201,7 @@ inlineasm : '%asm' INLINEASMBLOCK; subroutine : - 'sub' identifier '(' sub_params? ')' sub_return_part? (sub_address | (statement_block EOL)) + 'sub' identifier '(' sub_params? ')' sub_return_part? (statement_block EOL) ; sub_return_part : '->' sub_returns ; @@ -209,13 +212,29 @@ statement_block : '}' ; -sub_address : '=' integerliteral ; -sub_params : sub_param (',' sub_param)* ; +sub_params : sub_param (',' sub_param)* ; -sub_param: identifier ':' datatype; +sub_param : identifier ':' datatype; -sub_returns : datatype (',' datatype)* ; +sub_returns : datatype (',' datatype)* ; + +asmsubroutine : + 'asmsub' identifier '(' asmsub_params? ')' + '->' 'clobbers' '(' clobber? ')' '->' '(' asmsub_returns? ')' (asmsub_address | statement_block ) + ; + +asmsub_address : '=' address=integerliteral ; + +asmsub_params : asmsub_param (',' asmsub_param)* ; + +asmsub_param : identifier ':' datatype '@' (register | statusregister); + +clobber : register (',' register)* ; + +asmsub_returns : asmsub_return (',' asmsub_return)* ; + +asmsub_return : datatype '@' (register | statusregister) ; if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? EOL ; // statement is constrained later diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 1d1898e50..9da640980 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,32 +1,16 @@ -%option enable_floats ~ main { + +; sub VECTOR (dir: Pc, userptr: XY) -> (X, A?, Y?) = $FF8D ; read/set I/O vector table + + +asmsub VECTOR (dir: byte @ A, userptr: word @ XY) -> clobbers(A,X,Y) -> (byte @ X) = $ff8d +; asmsub VECTOR (dir: byte @ Pc, userptr: word @ XY) -> byte @ X, clobbers @ A, clobbers @ Y = $ff8d + + + sub start() { - byte bvar - word wvar - float fvar - str svar = "svar" - str_p spvar = "spvar" - str_s ssvar = "ssvar" - str_ps spsvar = "spsvar" - byte[2,3] matrixvar - byte[5] barrayvar - word[5] warrayvar - float eol = '\n' - - - _vm_write_char('\n') - fvar=test(15, 222.22) - _vm_write_num(fvar) - _vm_write_char('\n') - fvar=test(17, 333.33) - _vm_write_num(fvar) - _vm_write_char('\n') return -sub test(arg: byte, f: float) -> float { - return f/arg -} - } } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index b146be0b0..efd75a77e 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -38,6 +38,13 @@ enum class Register { XY } +enum class Statusflag { + Pc, + Pz, + Pv, + Pn +} + enum class BranchCondition { CS, CC, @@ -205,6 +212,10 @@ interface IAstProcessor { returnStmt.values = returnStmt.values.map { it.process(this) } return returnStmt } + + fun process(asmSubroutine: AsmSubroutine): IStatement { + return asmSubroutine + } } @@ -1237,7 +1248,6 @@ class InlineAssembly(val assembly: String, override val position: Position) : IS class Subroutine(override val name: String, val parameters: List, val returnvalues: List, - val address: Int?, override var statements: MutableList, override val position: Position) : IStatement, INameScope { override lateinit var parent: Node @@ -1253,14 +1263,14 @@ class Subroutine(override val name: String, override fun process(processor: IAstProcessor) = processor.process(this) override fun toString(): String { - return "Subroutine(name=$name, address=$address, parameters=$parameters, returnvalues=$returnvalues, ${statements.size} statements)" + return "Subroutine(name=$name, parameters=$parameters, returnvalues=$returnvalues, ${statements.size} statements)" } override fun registerUsedName(name: String) = throw NotImplementedError("not implemented on sub-scopes") } -data class SubroutineParameter(val name: String, +open class SubroutineParameter(val name: String, val type: DataType, override val position: Position) : Node { override lateinit var parent: Node @@ -1271,6 +1281,44 @@ data class SubroutineParameter(val name: String, } +// @todo merge this with normal Subroutine? +class AsmSubroutine(val name: String, + val address: Int?, + val params: List, + val returns: List, + val clobbers: Set, + val statements: MutableList, + override val position: Position) : IStatement { + override lateinit var parent: Node + + override fun linkParents(parent: Node) { + this.parent = parent + params.forEach { it.linkParents(this) } + returns.forEach { it.linkParents(this) } + statements.forEach { it.linkParents(this) } + } + + override fun process(processor: IAstProcessor) = processor.process(this) +} + +class AsmSubroutineParameter(name: String, + type: DataType, + val register: Register?, + val statusflag: Statusflag?, + position: Position) : SubroutineParameter(name, type, position) + + +class AsmSubroutineReturn(val type: DataType, + val register: Register?, + val statusflag: Statusflag?, + override val position: Position): Node { + override lateinit var parent: Node + override fun linkParents(parent: Node) { + this.parent = parent + } +} + + class IfStatement(var condition: IExpression, var statements: List, var elsepart: List, @@ -1490,10 +1538,39 @@ private fun prog8Parser.StatementContext.toAst() : IStatement { val continuestmt = continuestmt()?.toAst() if(continuestmt!=null) return continuestmt + val asmsubstmt = asmsubroutine()?.toAst() + if(asmsubstmt!=null) return asmsubstmt + throw FatalAstException("unprocessed source text (are we missing ast conversion rules for parser elements?): $text") } +private fun prog8Parser.AsmsubroutineContext.toAst(): IStatement { + val name = identifier().text + val address = asmsub_address()?.address?.toAst()?.number?.toInt() + val params = asmsub_params()?.toAst() ?: emptyList() + val returns = asmsub_returns()?.toAst() ?: emptyList() + val clobbers = clobber()?.toAst() ?: emptySet() + val statements = statement_block()?.toAst() ?: mutableListOf() + return AsmSubroutine(name, address, params, returns, clobbers, statements, toPosition()) +} + + +private fun prog8Parser.ClobberContext.toAst(): Set + = this.register().asSequence().map { it.toAst() }.toSet() + + +private fun prog8Parser.Asmsub_returnsContext.toAst(): List + = asmsub_return().map { AsmSubroutineReturn(it.datatype().toAst(), it.register()?.toAst(), it.statusregister()?.toAst(), toPosition()) } + + +private fun prog8Parser.Asmsub_paramsContext.toAst(): List + = asmsub_param().map { AsmSubroutineParameter(it.identifier().text, it.datatype().toAst(), it.register()?.toAst(), it.statusregister()?.toAst(), toPosition()) } + + +private fun prog8Parser.StatusregisterContext.toAst() = Statusflag.valueOf(text) + + private fun prog8Parser.Functioncall_stmtContext.toAst(): IStatement { val location = if(identifier()!=null) identifier()?.toAst() @@ -1526,12 +1603,8 @@ private fun prog8Parser.ReturnstmtContext.toAst() : Return { } private fun prog8Parser.UnconditionaljumpContext.toAst(): Jump { - val address = integerliteral()?.toAst()?.number?.toInt() - val identifier = - if(identifier()!=null) identifier()?.toAst() - else scoped_identifier()?.toAst() - + val identifier = identifier()?.toAst() ?: scoped_identifier()?.toAst() return Jump(address, identifier, null, toPosition()) } @@ -1542,10 +1615,9 @@ private fun prog8Parser.LabeldefContext.toAst(): IStatement = private fun prog8Parser.SubroutineContext.toAst() : Subroutine { return Subroutine(identifier().text, - if(sub_params() ==null) emptyList() else sub_params().toAst(), - if(sub_return_part() == null) emptyList() else sub_return_part().toAst(), - sub_address()?.integerliteral()?.toAst()?.number?.toInt(), - if(statement_block() ==null) mutableListOf() else statement_block().toAst(), + sub_params()?.toAst() ?: emptyList(), + sub_return_part()?.toAst() ?: emptyList(), + statement_block()?.toAst() ?: mutableListOf(), toPosition()) } diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 0eda440c7..0c26dedf5 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -195,18 +195,16 @@ class AstChecker(private val namespace: INameScope, // subroutine must contain at least one 'return' or 'goto' // (or if it has an asm block, that must contain a 'rts' or 'jmp') if(subroutine.statements.count { it is Return || it is Jump } == 0) { - if(subroutine.address==null) { - val amount = subroutine.statements - .asSequence() - .filter { it is InlineAssembly } - .map { (it as InlineAssembly).assembly } - .count { "rts" in it || "\trts" in it || "jmp" in it || "\tjmp" in it } - if (amount == 0) { - if(subroutine.returnvalues.isNotEmpty()) - err("subroutine has result value(s) and thus must have at least one 'return' or 'goto' in it (or 'rts' / 'jmp' in case of %asm)") - // if there's no return statement, we add the implicit one at the end. - subroutine.statements.add(Return(emptyList(), subroutine.position)) - } + val amount = subroutine.statements + .asSequence() + .filter { it is InlineAssembly } + .map { (it as InlineAssembly).assembly } + .count { "rts" in it || "\trts" in it || "jmp" in it || "\tjmp" in it } + if (amount == 0) { + if(subroutine.returnvalues.isNotEmpty()) + err("subroutine has result value(s) and thus must have at least one 'return' or 'goto' in it (or 'rts' / 'jmp' in case of %asm)") + // if there's no return statement, we add the implicit one at the end. + subroutine.statements.add(Return(emptyList(), subroutine.position)) } } @@ -224,7 +222,7 @@ class AstChecker(private val namespace: INameScope, var checkNext = false for (stmt in statements) { if(checkNext) { - if(stmt !is Label && stmt !is Subroutine) + if(stmt !is Label && stmt !is Subroutine && stmt !is AsmSubroutine) checkResult.add(SyntaxError("preceding subroutine definition at line ${preceding.position.line} must be followed here by a label, another subroutine statement, or nothing", stmt.position)) return } @@ -232,6 +230,7 @@ class AstChecker(private val namespace: INameScope, if(preceding !is Return && preceding !is Jump && preceding !is Subroutine + && preceding !is AsmSubroutine && preceding !is VarDecl && preceding !is BuiltinFunctionStatementPlaceholder) { checkResult.add(SyntaxError("subroutine definition must be preceded by a return, jump, vardecl, or another subroutine statement", stmt.position)) @@ -317,10 +316,6 @@ class AstChecker(private val namespace: INameScope, err("recursive var declaration") } - if(!compilerOptions.floats && decl.datatype==DataType.FLOAT) { - err("float var/const declaration, but floating point is not enabled via options") - } - // for now, variables can only be declared in a block or subroutine (not in a loop statement block) @todo fix this if(decl.parent !is Block && decl.parent !is Subroutine) { err ("variables must be declared at block or subroutine level") diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 62dc6a720..02c359263 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -251,6 +251,14 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, return super.process(subroutine) } + override fun process(asmSubroutine: AsmSubroutine): IStatement { + if(asmSubroutine.statements.isNotEmpty()) { + stackvmProg.label(asmSubroutine.makeScopedName(asmSubroutine.name).joinToString(".")) + translate(asmSubroutine.statements) + } + return super.process(asmSubroutine) + } + override fun process(block: Block): IStatement { stackvmProg.label(block.scopedname) translate(block.statements) @@ -288,6 +296,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, is WhileLoop -> translate(stmt) is RepeatLoop -> translate(stmt) is Directive, is VarDecl, is Subroutine -> {} // skip this, already processed these. + is AsmSubroutine -> {} is InlineAssembly -> throw CompilerException("inline assembly is not supported by the StackVM") else -> TODO("translate statement $stmt to stackvm") } diff --git a/compiler/src/prog8/parser/prog8Lexer.java b/compiler/src/prog8/parser/prog8Lexer.java index c123ba1d4..2df8649ff 100644 --- a/compiler/src/prog8/parser/prog8Lexer.java +++ b/compiler/src/prog8/parser/prog8Lexer.java @@ -30,9 +30,10 @@ public class prog8Lexer extends Lexer { T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, - T__94=95, T__95=96, T__96=97, LINECOMMENT=98, COMMENT=99, WS=100, EOL=101, - NAME=102, DEC_INTEGER=103, HEX_INTEGER=104, BIN_INTEGER=105, FLOAT_NUMBER=106, - STRING=107, INLINEASMBLOCK=108, SINGLECHAR=109; + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, LINECOMMENT=105, COMMENT=106, WS=107, + EOL=108, NAME=109, DEC_INTEGER=110, HEX_INTEGER=111, BIN_INTEGER=112, + FLOAT_NUMBER=113, STRING=114, INLINEASMBLOCK=115, SINGLECHAR=116; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -54,9 +55,10 @@ public class prog8Lexer extends Lexer { "T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80", "T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88", "T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96", - "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", - "BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING", - "INLINEASMBLOCK", "SINGLECHAR" + "T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "LINECOMMENT", + "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", + "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK", + "SINGLECHAR" }; private static final String[] _LITERAL_NAMES = { @@ -68,11 +70,12 @@ public class prog8Lexer extends Lexer { "'--'", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", "'return'", "'break'", "'continue'", - "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'.w'", "'true'", - "'false'", "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'if'", "'else'", - "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", "'if_nz'", "'if_pl'", - "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", - "'while'", "'repeat'", "'until'" + "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", + "'Pv'", "'.w'", "'true'", "'false'", "'%asm'", "'sub'", "'->'", "'{'", + "'}'", "'asmsub'", "'clobbers'", "'@'", "'if'", "'else'", "'if_cs'", "'if_cc'", + "'if_eq'", "'if_z'", "'if_ne'", "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", + "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", "'while'", "'repeat'", + "'until'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -83,9 +86,9 @@ public class prog8Lexer extends Lexer { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", - "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK", - "SINGLECHAR" + null, null, null, null, null, null, null, null, null, "LINECOMMENT", "COMMENT", + "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", + "STRING", "INLINEASMBLOCK", "SINGLECHAR" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -147,13 +150,13 @@ public class prog8Lexer extends Lexer { @Override public void action(RuleContext _localctx, int ruleIndex, int actionIndex) { switch (ruleIndex) { - case 108: + case 115: STRING_action((RuleContext)_localctx, actionIndex); break; - case 109: + case 116: INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex); break; - case 110: + case 117: SINGLECHAR_action((RuleContext)_localctx, actionIndex); break; } @@ -193,7 +196,7 @@ public class prog8Lexer extends Lexer { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2o\u0306\b\1\4\2\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2v\u0332\b\1\4\2\t"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -205,251 +208,265 @@ public class prog8Lexer extends Lexer { "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k\t"+ - "k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3"+ - "\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6"+ - "\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ - "\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+ - "\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r"+ - "\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3"+ - "\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3"+ - "\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3"+ - "\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3"+ - "\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3"+ - "\35\3\35\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3 \3 \3 \3 \3!\3!\3!\3\"\3"+ - "\"\3\"\3#\3#\3#\3$\3$\3$\3%\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3*\3"+ - "+\3+\3,\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62"+ - "\3\63\3\63\3\63\3\64\3\64\3\64\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38"+ - "\39\39\39\39\39\3:\3:\3:\3:\3;\3;\3;\3<\3<\3<\3<\3=\3=\3=\3=\3>\3>\3>"+ - "\3>\3>\3>\3>\3?\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3B\3B"+ - "\3C\3C\3D\3D\3E\3E\3E\3F\3F\3F\3G\3G\3G\3H\3H\3H\3I\3I\3I\3I\3I\3J\3J"+ - "\3J\3J\3J\3J\3K\3K\3K\3K\3K\3L\3L\3L\3L\3M\3M\3M\3N\3N\3O\3O\3P\3P\3P"+ - "\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T"+ - "\3U\3U\3U\3U\3U\3V\3V\3V\3V\3V\3V\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X"+ - "\3Y\3Y\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3[\3\\\3\\\3"+ - "\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^\3^\3^\3_\3_\3_\3`\3`\3`\3`\3`\3"+ - "`\3a\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3c\3c\7c\u0295\nc\fc\16c\u0298"+ - "\13c\3c\3c\3c\3c\3d\3d\7d\u02a0\nd\fd\16d\u02a3\13d\3d\3d\3e\3e\3e\3e"+ - "\3f\6f\u02ac\nf\rf\16f\u02ad\3g\3g\7g\u02b2\ng\fg\16g\u02b5\13g\3h\3h"+ - "\3h\6h\u02ba\nh\rh\16h\u02bb\5h\u02be\nh\3i\3i\6i\u02c2\ni\ri\16i\u02c3"+ - "\3j\3j\6j\u02c8\nj\rj\16j\u02c9\3k\3k\3k\5k\u02cf\nk\3k\5k\u02d2\nk\3"+ - "l\6l\u02d5\nl\rl\16l\u02d6\3l\3l\6l\u02db\nl\rl\16l\u02dc\5l\u02df\nl"+ - "\3m\3m\3m\3m\5m\u02e5\nm\3n\3n\3n\7n\u02ea\nn\fn\16n\u02ed\13n\3n\3n\3"+ - "n\3o\3o\3o\3o\6o\u02f6\no\ro\16o\u02f7\3o\3o\3o\3o\3o\3p\3p\3p\5p\u0302"+ - "\np\3p\3p\3p\3\u02f7\2q\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f"+ - "\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63"+ - "\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62"+ - "c\63e\64g\65i\66k\67m8o9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087"+ - "E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+ - "O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+ - "Y\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3"+ - "c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7"+ - "\2\u00d9\2\u00dbm\u00ddn\u00dfo\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2"+ - "C\\aac|\6\2\62;C\\aac|\5\2\62;CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2"+ - "\u0315\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2"+ - "\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3"+ - "\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2"+ - "\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2"+ - "/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2"+ - "\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2"+ - "G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3"+ - "\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2"+ - "\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2"+ - "m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3"+ - "\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2"+ - "\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2"+ - "\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095"+ - "\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2"+ - "\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7"+ - "\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2"+ - "\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9"+ - "\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2"+ - "\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+ - "\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2"+ - "\2\2\u00d5\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\3\u00e1"+ - "\3\2\2\2\5\u00e3\3\2\2\2\7\u00e5\3\2\2\2\t\u00ea\3\2\2\2\13\u00f2\3\2"+ - "\2\2\r\u00fc\3\2\2\2\17\u0106\3\2\2\2\21\u010f\3\2\2\2\23\u0117\3\2\2"+ - "\2\25\u0123\3\2\2\2\27\u012f\3\2\2\2\31\u013a\3\2\2\2\33\u0142\3\2\2\2"+ - "\35\u0144\3\2\2\2\37\u0146\3\2\2\2!\u014c\3\2\2\2#\u0153\3\2\2\2%\u0158"+ - "\3\2\2\2\'\u015d\3\2\2\2)\u0163\3\2\2\2+\u0167\3\2\2\2-\u016d\3\2\2\2"+ - "/\u0173\3\2\2\2\61\u017a\3\2\2\2\63\u017c\3\2\2\2\65\u017e\3\2\2\2\67"+ - "\u0181\3\2\2\29\u0184\3\2\2\2;\u0187\3\2\2\2=\u018b\3\2\2\2?\u018e\3\2"+ - "\2\2A\u0192\3\2\2\2C\u0195\3\2\2\2E\u0198\3\2\2\2G\u019b\3\2\2\2I\u019e"+ - "\3\2\2\2K\u01a1\3\2\2\2M\u01a3\3\2\2\2O\u01a5\3\2\2\2Q\u01a7\3\2\2\2S"+ - "\u01a9\3\2\2\2U\u01ac\3\2\2\2W\u01ae\3\2\2\2Y\u01b0\3\2\2\2[\u01b3\3\2"+ - "\2\2]\u01b5\3\2\2\2_\u01b7\3\2\2\2a\u01b9\3\2\2\2c\u01bc\3\2\2\2e\u01bf"+ - "\3\2\2\2g\u01c2\3\2\2\2i\u01c5\3\2\2\2k\u01c7\3\2\2\2m\u01c9\3\2\2\2o"+ - "\u01cb\3\2\2\2q\u01ce\3\2\2\2s\u01d3\3\2\2\2u\u01d7\3\2\2\2w\u01da\3\2"+ - "\2\2y\u01de\3\2\2\2{\u01e2\3\2\2\2}\u01e9\3\2\2\2\177\u01ef\3\2\2\2\u0081"+ - "\u01f8\3\2\2\2\u0083\u01fa\3\2\2\2\u0085\u01fc\3\2\2\2\u0087\u01fe\3\2"+ - "\2\2\u0089\u0200\3\2\2\2\u008b\u0203\3\2\2\2\u008d\u0206\3\2\2\2\u008f"+ - "\u0209\3\2\2\2\u0091\u020c\3\2\2\2\u0093\u0211\3\2\2\2\u0095\u0217\3\2"+ - "\2\2\u0097\u021c\3\2\2\2\u0099\u0220\3\2\2\2\u009b\u0223\3\2\2\2\u009d"+ - "\u0225\3\2\2\2\u009f\u0227\3\2\2\2\u00a1\u022a\3\2\2\2\u00a3\u022f\3\2"+ - "\2\2\u00a5\u0235\3\2\2\2\u00a7\u023b\3\2\2\2\u00a9\u0241\3\2\2\2\u00ab"+ - "\u0246\3\2\2\2\u00ad\u024c\3\2\2\2\u00af\u0252\3\2\2\2\u00b1\u0258\3\2"+ - "\2\2\u00b3\u025f\3\2\2\2\u00b5\u0265\3\2\2\2\u00b7\u026c\3\2\2\2\u00b9"+ - "\u0272\3\2\2\2\u00bb\u0278\3\2\2\2\u00bd\u027c\3\2\2\2\u00bf\u027f\3\2"+ - "\2\2\u00c1\u0285\3\2\2\2\u00c3\u028c\3\2\2\2\u00c5\u0292\3\2\2\2\u00c7"+ - "\u029d\3\2\2\2\u00c9\u02a6\3\2\2\2\u00cb\u02ab\3\2\2\2\u00cd\u02af\3\2"+ - "\2\2\u00cf\u02bd\3\2\2\2\u00d1\u02bf\3\2\2\2\u00d3\u02c5\3\2\2\2\u00d5"+ - "\u02cb\3\2\2\2\u00d7\u02d4\3\2\2\2\u00d9\u02e4\3\2\2\2\u00db\u02e6\3\2"+ - "\2\2\u00dd\u02f1\3\2\2\2\u00df\u02fe\3\2\2\2\u00e1\u00e2\7\u0080\2\2\u00e2"+ - "\4\3\2\2\2\u00e3\u00e4\7<\2\2\u00e4\6\3\2\2\2\u00e5\u00e6\7i\2\2\u00e6"+ - "\u00e7\7q\2\2\u00e7\u00e8\7v\2\2\u00e8\u00e9\7q\2\2\u00e9\b\3\2\2\2\u00ea"+ - "\u00eb\7\'\2\2\u00eb\u00ec\7q\2\2\u00ec\u00ed\7w\2\2\u00ed\u00ee\7v\2"+ - "\2\u00ee\u00ef\7r\2\2\u00ef\u00f0\7w\2\2\u00f0\u00f1\7v\2\2\u00f1\n\3"+ - "\2\2\2\u00f2\u00f3\7\'\2\2\u00f3\u00f4\7n\2\2\u00f4\u00f5\7c\2\2\u00f5"+ - "\u00f6\7w\2\2\u00f6\u00f7\7p\2\2\u00f7\u00f8\7e\2\2\u00f8\u00f9\7j\2\2"+ - "\u00f9\u00fa\7g\2\2\u00fa\u00fb\7t\2\2\u00fb\f\3\2\2\2\u00fc\u00fd\7\'"+ - "\2\2\u00fd\u00fe\7|\2\2\u00fe\u00ff\7g\2\2\u00ff\u0100\7t\2\2\u0100\u0101"+ - "\7q\2\2\u0101\u0102\7r\2\2\u0102\u0103\7c\2\2\u0103\u0104\7i\2\2\u0104"+ - "\u0105\7g\2\2\u0105\16\3\2\2\2\u0106\u0107\7\'\2\2\u0107\u0108\7c\2\2"+ - "\u0108\u0109\7f\2\2\u0109\u010a\7f\2\2\u010a\u010b\7t\2\2\u010b\u010c"+ - "\7g\2\2\u010c\u010d\7u\2\2\u010d\u010e\7u\2\2\u010e\20\3\2\2\2\u010f\u0110"+ - "\7\'\2\2\u0110\u0111\7k\2\2\u0111\u0112\7o\2\2\u0112\u0113\7r\2\2\u0113"+ - "\u0114\7q\2\2\u0114\u0115\7t\2\2\u0115\u0116\7v\2\2\u0116\22\3\2\2\2\u0117"+ - "\u0118\7\'\2\2\u0118\u0119\7d\2\2\u0119\u011a\7t\2\2\u011a\u011b\7g\2"+ - "\2\u011b\u011c\7c\2\2\u011c\u011d\7m\2\2\u011d\u011e\7r\2\2\u011e\u011f"+ - "\7q\2\2\u011f\u0120\7k\2\2\u0120\u0121\7p\2\2\u0121\u0122\7v\2\2\u0122"+ - "\24\3\2\2\2\u0123\u0124\7\'\2\2\u0124\u0125\7c\2\2\u0125\u0126\7u\2\2"+ - "\u0126\u0127\7o\2\2\u0127\u0128\7k\2\2\u0128\u0129\7p\2\2\u0129\u012a"+ - "\7e\2\2\u012a\u012b\7n\2\2\u012b\u012c\7w\2\2\u012c\u012d\7f\2\2\u012d"+ - "\u012e\7g\2\2\u012e\26\3\2\2\2\u012f\u0130\7\'\2\2\u0130\u0131\7c\2\2"+ - "\u0131\u0132\7u\2\2\u0132\u0133\7o\2\2\u0133\u0134\7d\2\2\u0134\u0135"+ - "\7k\2\2\u0135\u0136\7p\2\2\u0136\u0137\7c\2\2\u0137\u0138\7t\2\2\u0138"+ - "\u0139\7{\2\2\u0139\30\3\2\2\2\u013a\u013b\7\'\2\2\u013b\u013c\7q\2\2"+ - "\u013c\u013d\7r\2\2\u013d\u013e\7v\2\2\u013e\u013f\7k\2\2\u013f\u0140"+ - "\7q\2\2\u0140\u0141\7p\2\2\u0141\32\3\2\2\2\u0142\u0143\7.\2\2\u0143\34"+ - "\3\2\2\2\u0144\u0145\7?\2\2\u0145\36\3\2\2\2\u0146\u0147\7e\2\2\u0147"+ - "\u0148\7q\2\2\u0148\u0149\7p\2\2\u0149\u014a\7u\2\2\u014a\u014b\7v\2\2"+ - "\u014b \3\2\2\2\u014c\u014d\7o\2\2\u014d\u014e\7g\2\2\u014e\u014f\7o\2"+ - "\2\u014f\u0150\7q\2\2\u0150\u0151\7t\2\2\u0151\u0152\7{\2\2\u0152\"\3"+ - "\2\2\2\u0153\u0154\7d\2\2\u0154\u0155\7{\2\2\u0155\u0156\7v\2\2\u0156"+ - "\u0157\7g\2\2\u0157$\3\2\2\2\u0158\u0159\7y\2\2\u0159\u015a\7q\2\2\u015a"+ - "\u015b\7t\2\2\u015b\u015c\7f\2\2\u015c&\3\2\2\2\u015d\u015e\7h\2\2\u015e"+ - "\u015f\7n\2\2\u015f\u0160\7q\2\2\u0160\u0161\7c\2\2\u0161\u0162\7v\2\2"+ - "\u0162(\3\2\2\2\u0163\u0164\7u\2\2\u0164\u0165\7v\2\2\u0165\u0166\7t\2"+ - "\2\u0166*\3\2\2\2\u0167\u0168\7u\2\2\u0168\u0169\7v\2\2\u0169\u016a\7"+ - "t\2\2\u016a\u016b\7a\2\2\u016b\u016c\7r\2\2\u016c,\3\2\2\2\u016d\u016e"+ - "\7u\2\2\u016e\u016f\7v\2\2\u016f\u0170\7t\2\2\u0170\u0171\7a\2\2\u0171"+ - "\u0172\7u\2\2\u0172.\3\2\2\2\u0173\u0174\7u\2\2\u0174\u0175\7v\2\2\u0175"+ - "\u0176\7t\2\2\u0176\u0177\7a\2\2\u0177\u0178\7r\2\2\u0178\u0179\7u\2\2"+ - "\u0179\60\3\2\2\2\u017a\u017b\7]\2\2\u017b\62\3\2\2\2\u017c\u017d\7_\2"+ - "\2\u017d\64\3\2\2\2\u017e\u017f\7-\2\2\u017f\u0180\7?\2\2\u0180\66\3\2"+ - "\2\2\u0181\u0182\7/\2\2\u0182\u0183\7?\2\2\u01838\3\2\2\2\u0184\u0185"+ - "\7\61\2\2\u0185\u0186\7?\2\2\u0186:\3\2\2\2\u0187\u0188\7\61\2\2\u0188"+ - "\u0189\7\61\2\2\u0189\u018a\7?\2\2\u018a<\3\2\2\2\u018b\u018c\7,\2\2\u018c"+ - "\u018d\7?\2\2\u018d>\3\2\2\2\u018e\u018f\7,\2\2\u018f\u0190\7,\2\2\u0190"+ - "\u0191\7?\2\2\u0191@\3\2\2\2\u0192\u0193\7(\2\2\u0193\u0194\7?\2\2\u0194"+ - "B\3\2\2\2\u0195\u0196\7~\2\2\u0196\u0197\7?\2\2\u0197D\3\2\2\2\u0198\u0199"+ - "\7`\2\2\u0199\u019a\7?\2\2\u019aF\3\2\2\2\u019b\u019c\7-\2\2\u019c\u019d"+ - "\7-\2\2\u019dH\3\2\2\2\u019e\u019f\7/\2\2\u019f\u01a0\7/\2\2\u01a0J\3"+ - "\2\2\2\u01a1\u01a2\7*\2\2\u01a2L\3\2\2\2\u01a3\u01a4\7+\2\2\u01a4N\3\2"+ - "\2\2\u01a5\u01a6\7-\2\2\u01a6P\3\2\2\2\u01a7\u01a8\7/\2\2\u01a8R\3\2\2"+ - "\2\u01a9\u01aa\7,\2\2\u01aa\u01ab\7,\2\2\u01abT\3\2\2\2\u01ac\u01ad\7"+ - ",\2\2\u01adV\3\2\2\2\u01ae\u01af\7\61\2\2\u01afX\3\2\2\2\u01b0\u01b1\7"+ - "\61\2\2\u01b1\u01b2\7\61\2\2\u01b2Z\3\2\2\2\u01b3\u01b4\7\'\2\2\u01b4"+ - "\\\3\2\2\2\u01b5\u01b6\7>\2\2\u01b6^\3\2\2\2\u01b7\u01b8\7@\2\2\u01b8"+ - "`\3\2\2\2\u01b9\u01ba\7>\2\2\u01ba\u01bb\7?\2\2\u01bbb\3\2\2\2\u01bc\u01bd"+ - "\7@\2\2\u01bd\u01be\7?\2\2\u01bed\3\2\2\2\u01bf\u01c0\7?\2\2\u01c0\u01c1"+ - "\7?\2\2\u01c1f\3\2\2\2\u01c2\u01c3\7#\2\2\u01c3\u01c4\7?\2\2\u01c4h\3"+ - "\2\2\2\u01c5\u01c6\7(\2\2\u01c6j\3\2\2\2\u01c7\u01c8\7`\2\2\u01c8l\3\2"+ - "\2\2\u01c9\u01ca\7~\2\2\u01can\3\2\2\2\u01cb\u01cc\7v\2\2\u01cc\u01cd"+ - "\7q\2\2\u01cdp\3\2\2\2\u01ce\u01cf\7u\2\2\u01cf\u01d0\7v\2\2\u01d0\u01d1"+ - "\7g\2\2\u01d1\u01d2\7r\2\2\u01d2r\3\2\2\2\u01d3\u01d4\7c\2\2\u01d4\u01d5"+ - "\7p\2\2\u01d5\u01d6\7f\2\2\u01d6t\3\2\2\2\u01d7\u01d8\7q\2\2\u01d8\u01d9"+ - "\7t\2\2\u01d9v\3\2\2\2\u01da\u01db\7z\2\2\u01db\u01dc\7q\2\2\u01dc\u01dd"+ - "\7t\2\2\u01ddx\3\2\2\2\u01de\u01df\7p\2\2\u01df\u01e0\7q\2\2\u01e0\u01e1"+ - "\7v\2\2\u01e1z\3\2\2\2\u01e2\u01e3\7t\2\2\u01e3\u01e4\7g\2\2\u01e4\u01e5"+ - "\7v\2\2\u01e5\u01e6\7w\2\2\u01e6\u01e7\7t\2\2\u01e7\u01e8\7p\2\2\u01e8"+ - "|\3\2\2\2\u01e9\u01ea\7d\2\2\u01ea\u01eb\7t\2\2\u01eb\u01ec\7g\2\2\u01ec"+ - "\u01ed\7c\2\2\u01ed\u01ee\7m\2\2\u01ee~\3\2\2\2\u01ef\u01f0\7e\2\2\u01f0"+ - "\u01f1\7q\2\2\u01f1\u01f2\7p\2\2\u01f2\u01f3\7v\2\2\u01f3\u01f4\7k\2\2"+ - "\u01f4\u01f5\7p\2\2\u01f5\u01f6\7w\2\2\u01f6\u01f7\7g\2\2\u01f7\u0080"+ - "\3\2\2\2\u01f8\u01f9\7\60\2\2\u01f9\u0082\3\2\2\2\u01fa\u01fb\7C\2\2\u01fb"+ - "\u0084\3\2\2\2\u01fc\u01fd\7Z\2\2\u01fd\u0086\3\2\2\2\u01fe\u01ff\7[\2"+ - "\2\u01ff\u0088\3\2\2\2\u0200\u0201\7C\2\2\u0201\u0202\7Z\2\2\u0202\u008a"+ - "\3\2\2\2\u0203\u0204\7C\2\2\u0204\u0205\7[\2\2\u0205\u008c\3\2\2\2\u0206"+ - "\u0207\7Z\2\2\u0207\u0208\7[\2\2\u0208\u008e\3\2\2\2\u0209\u020a\7\60"+ - "\2\2\u020a\u020b\7y\2\2\u020b\u0090\3\2\2\2\u020c\u020d\7v\2\2\u020d\u020e"+ - "\7t\2\2\u020e\u020f\7w\2\2\u020f\u0210\7g\2\2\u0210\u0092\3\2\2\2\u0211"+ - "\u0212\7h\2\2\u0212\u0213\7c\2\2\u0213\u0214\7n\2\2\u0214\u0215\7u\2\2"+ - "\u0215\u0216\7g\2\2\u0216\u0094\3\2\2\2\u0217\u0218\7\'\2\2\u0218\u0219"+ - "\7c\2\2\u0219\u021a\7u\2\2\u021a\u021b\7o\2\2\u021b\u0096\3\2\2\2\u021c"+ - "\u021d\7u\2\2\u021d\u021e\7w\2\2\u021e\u021f\7d\2\2\u021f\u0098\3\2\2"+ - "\2\u0220\u0221\7/\2\2\u0221\u0222\7@\2\2\u0222\u009a\3\2\2\2\u0223\u0224"+ - "\7}\2\2\u0224\u009c\3\2\2\2\u0225\u0226\7\177\2\2\u0226\u009e\3\2\2\2"+ - "\u0227\u0228\7k\2\2\u0228\u0229\7h\2\2\u0229\u00a0\3\2\2\2\u022a\u022b"+ - "\7g\2\2\u022b\u022c\7n\2\2\u022c\u022d\7u\2\2\u022d\u022e\7g\2\2\u022e"+ - "\u00a2\3\2\2\2\u022f\u0230\7k\2\2\u0230\u0231\7h\2\2\u0231\u0232\7a\2"+ - "\2\u0232\u0233\7e\2\2\u0233\u0234\7u\2\2\u0234\u00a4\3\2\2\2\u0235\u0236"+ - "\7k\2\2\u0236\u0237\7h\2\2\u0237\u0238\7a\2\2\u0238\u0239\7e\2\2\u0239"+ - "\u023a\7e\2\2\u023a\u00a6\3\2\2\2\u023b\u023c\7k\2\2\u023c\u023d\7h\2"+ - "\2\u023d\u023e\7a\2\2\u023e\u023f\7g\2\2\u023f\u0240\7s\2\2\u0240\u00a8"+ - "\3\2\2\2\u0241\u0242\7k\2\2\u0242\u0243\7h\2\2\u0243\u0244\7a\2\2\u0244"+ - "\u0245\7|\2\2\u0245\u00aa\3\2\2\2\u0246\u0247\7k\2\2\u0247\u0248\7h\2"+ - "\2\u0248\u0249\7a\2\2\u0249\u024a\7p\2\2\u024a\u024b\7g\2\2\u024b\u00ac"+ - "\3\2\2\2\u024c\u024d\7k\2\2\u024d\u024e\7h\2\2\u024e\u024f\7a\2\2\u024f"+ - "\u0250\7p\2\2\u0250\u0251\7|\2\2\u0251\u00ae\3\2\2\2\u0252\u0253\7k\2"+ - "\2\u0253\u0254\7h\2\2\u0254\u0255\7a\2\2\u0255\u0256\7r\2\2\u0256\u0257"+ - "\7n\2\2\u0257\u00b0\3\2\2\2\u0258\u0259\7k\2\2\u0259\u025a\7h\2\2\u025a"+ - "\u025b\7a\2\2\u025b\u025c\7r\2\2\u025c\u025d\7q\2\2\u025d\u025e\7u\2\2"+ - "\u025e\u00b2\3\2\2\2\u025f\u0260\7k\2\2\u0260\u0261\7h\2\2\u0261\u0262"+ - "\7a\2\2\u0262\u0263\7o\2\2\u0263\u0264\7k\2\2\u0264\u00b4\3\2\2\2\u0265"+ - "\u0266\7k\2\2\u0266\u0267\7h\2\2\u0267\u0268\7a\2\2\u0268\u0269\7p\2\2"+ - "\u0269\u026a\7g\2\2\u026a\u026b\7i\2\2\u026b\u00b6\3\2\2\2\u026c\u026d"+ - "\7k\2\2\u026d\u026e\7h\2\2\u026e\u026f\7a\2\2\u026f\u0270\7x\2\2\u0270"+ - "\u0271\7u\2\2\u0271\u00b8\3\2\2\2\u0272\u0273\7k\2\2\u0273\u0274\7h\2"+ - "\2\u0274\u0275\7a\2\2\u0275\u0276\7x\2\2\u0276\u0277\7e\2\2\u0277\u00ba"+ - "\3\2\2\2\u0278\u0279\7h\2\2\u0279\u027a\7q\2\2\u027a\u027b\7t\2\2\u027b"+ - "\u00bc\3\2\2\2\u027c\u027d\7k\2\2\u027d\u027e\7p\2\2\u027e\u00be\3\2\2"+ - "\2\u027f\u0280\7y\2\2\u0280\u0281\7j\2\2\u0281\u0282\7k\2\2\u0282\u0283"+ - "\7n\2\2\u0283\u0284\7g\2\2\u0284\u00c0\3\2\2\2\u0285\u0286\7t\2\2\u0286"+ - "\u0287\7g\2\2\u0287\u0288\7r\2\2\u0288\u0289\7g\2\2\u0289\u028a\7c\2\2"+ - "\u028a\u028b\7v\2\2\u028b\u00c2\3\2\2\2\u028c\u028d\7w\2\2\u028d\u028e"+ - "\7p\2\2\u028e\u028f\7v\2\2\u028f\u0290\7k\2\2\u0290\u0291\7n\2\2\u0291"+ - "\u00c4\3\2\2\2\u0292\u0296\t\2\2\2\u0293\u0295\t\3\2\2\u0294\u0293\3\2"+ - "\2\2\u0295\u0298\3\2\2\2\u0296\u0294\3\2\2\2\u0296\u0297\3\2\2\2\u0297"+ - "\u0299\3\2\2\2\u0298\u0296\3\2\2\2\u0299\u029a\5\u00c7d\2\u029a\u029b"+ - "\3\2\2\2\u029b\u029c\bc\2\2\u029c\u00c6\3\2\2\2\u029d\u02a1\7=\2\2\u029e"+ - "\u02a0\n\2\2\2\u029f\u029e\3\2\2\2\u02a0\u02a3\3\2\2\2\u02a1\u029f\3\2"+ - "\2\2\u02a1\u02a2\3\2\2\2\u02a2\u02a4\3\2\2\2\u02a3\u02a1\3\2\2\2\u02a4"+ - "\u02a5\bd\2\2\u02a5\u00c8\3\2\2\2\u02a6\u02a7\t\3\2\2\u02a7\u02a8\3\2"+ - "\2\2\u02a8\u02a9\be\3\2\u02a9\u00ca\3\2\2\2\u02aa\u02ac\t\2\2\2\u02ab"+ - "\u02aa\3\2\2\2\u02ac\u02ad\3\2\2\2\u02ad\u02ab\3\2\2\2\u02ad\u02ae\3\2"+ - "\2\2\u02ae\u00cc\3\2\2\2\u02af\u02b3\t\4\2\2\u02b0\u02b2\t\5\2\2\u02b1"+ - "\u02b0\3\2\2\2\u02b2\u02b5\3\2\2\2\u02b3\u02b1\3\2\2\2\u02b3\u02b4\3\2"+ - "\2\2\u02b4\u00ce\3\2\2\2\u02b5\u02b3\3\2\2\2\u02b6\u02be\4\62;\2\u02b7"+ - "\u02b9\4\63;\2\u02b8\u02ba\4\62;\2\u02b9\u02b8\3\2\2\2\u02ba\u02bb\3\2"+ - "\2\2\u02bb\u02b9\3\2\2\2\u02bb\u02bc\3\2\2\2\u02bc\u02be\3\2\2\2\u02bd"+ - "\u02b6\3\2\2\2\u02bd\u02b7\3\2\2\2\u02be\u00d0\3\2\2\2\u02bf\u02c1\7&"+ - "\2\2\u02c0\u02c2\t\6\2\2\u02c1\u02c0\3\2\2\2\u02c2\u02c3\3\2\2\2\u02c3"+ - "\u02c1\3\2\2\2\u02c3\u02c4\3\2\2\2\u02c4\u00d2\3\2\2\2\u02c5\u02c7\7\'"+ - "\2\2\u02c6\u02c8\4\62\63\2\u02c7\u02c6\3\2\2\2\u02c8\u02c9\3\2\2\2\u02c9"+ - "\u02c7\3\2\2\2\u02c9\u02ca\3\2\2\2\u02ca\u00d4\3\2\2\2\u02cb\u02d1\5\u00d7"+ - "l\2\u02cc\u02ce\t\7\2\2\u02cd\u02cf\t\b\2\2\u02ce\u02cd\3\2\2\2\u02ce"+ - "\u02cf\3\2\2\2\u02cf\u02d0\3\2\2\2\u02d0\u02d2\5\u00d7l\2\u02d1\u02cc"+ - "\3\2\2\2\u02d1\u02d2\3\2\2\2\u02d2\u00d6\3\2\2\2\u02d3\u02d5\4\62;\2\u02d4"+ - "\u02d3\3\2\2\2\u02d5\u02d6\3\2\2\2\u02d6\u02d4\3\2\2\2\u02d6\u02d7\3\2"+ - "\2\2\u02d7\u02de\3\2\2\2\u02d8\u02da\7\60\2\2\u02d9\u02db\4\62;\2\u02da"+ - "\u02d9\3\2\2\2\u02db\u02dc\3\2\2\2\u02dc\u02da\3\2\2\2\u02dc\u02dd\3\2"+ - "\2\2\u02dd\u02df\3\2\2\2\u02de\u02d8\3\2\2\2\u02de\u02df\3\2\2\2\u02df"+ - "\u00d8\3\2\2\2\u02e0\u02e1\7^\2\2\u02e1\u02e5\13\2\2\2\u02e2\u02e3\7^"+ - "\2\2\u02e3\u02e5\5\u00cbf\2\u02e4\u02e0\3\2\2\2\u02e4\u02e2\3\2\2\2\u02e5"+ - "\u00da\3\2\2\2\u02e6\u02eb\7$\2\2\u02e7\u02ea\5\u00d9m\2\u02e8\u02ea\n"+ - "\t\2\2\u02e9\u02e7\3\2\2\2\u02e9\u02e8\3\2\2\2\u02ea\u02ed\3\2\2\2\u02eb"+ - "\u02e9\3\2\2\2\u02eb\u02ec\3\2\2\2\u02ec\u02ee\3\2\2\2\u02ed\u02eb\3\2"+ - "\2\2\u02ee\u02ef\7$\2\2\u02ef\u02f0\bn\4\2\u02f0\u00dc\3\2\2\2\u02f1\u02f2"+ - "\7}\2\2\u02f2\u02f3\7}\2\2\u02f3\u02f5\3\2\2\2\u02f4\u02f6\13\2\2\2\u02f5"+ - "\u02f4\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f7\u02f8\3\2\2\2\u02f7\u02f5\3\2"+ - "\2\2\u02f8\u02f9\3\2\2\2\u02f9\u02fa\7\177\2\2\u02fa\u02fb\7\177\2\2\u02fb"+ - "\u02fc\3\2\2\2\u02fc\u02fd\bo\5\2\u02fd\u00de\3\2\2\2\u02fe\u0301\7)\2"+ - "\2\u02ff\u0302\5\u00d9m\2\u0300\u0302\n\t\2\2\u0301\u02ff\3\2\2\2\u0301"+ - "\u0300\3\2\2\2\u0302\u0303\3\2\2\2\u0303\u0304\7)\2\2\u0304\u0305\bp\6"+ - "\2\u0305\u00e0\3\2\2\2\26\2\u0296\u02a1\u02ad\u02b3\u02bb\u02bd\u02c1"+ - "\u02c3\u02c9\u02ce\u02d1\u02d6\u02dc\u02de\u02e4\u02e9\u02eb\u02f7\u0301"+ - "\7\2\3\2\b\2\2\3n\2\3o\3\3p\4"; + "k\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv\4"+ + "w\tw\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+ + "\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7"+ + "\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3"+ + "\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3"+ + "\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3"+ + "\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\17"+ + "\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\21"+ + "\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24"+ + "\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27"+ + "\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\32"+ + "\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\36\3\36\3\36\3\36"+ + "\3\37\3\37\3\37\3 \3 \3 \3 \3!\3!\3!\3\"\3\"\3\"\3#\3#\3#\3$\3$\3$\3%"+ + "\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3*\3+\3+\3,\3,\3-\3-\3-\3.\3.\3"+ + "/\3/\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64"+ + "\3\64\3\65\3\65\3\66\3\66\3\67\3\67\38\38\38\39\39\39\39\39\3:\3:\3:\3"+ + ":\3;\3;\3;\3<\3<\3<\3<\3=\3=\3=\3=\3>\3>\3>\3>\3>\3>\3>\3?\3?\3?\3?\3"+ + "?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3B\3B\3C\3C\3D\3D\3E\3E\3E\3F\3"+ + "F\3F\3G\3G\3G\3H\3H\3H\3I\3I\3I\3J\3J\3J\3K\3K\3K\3L\3L\3L\3M\3M\3M\3"+ + "M\3M\3N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\3Q\3Q\3Q\3R\3R\3S\3"+ + "S\3T\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3U\3U\3U\3V\3V\3W\3W\3W\3X\3"+ + "X\3X\3X\3X\3Y\3Y\3Y\3Y\3Y\3Y\3Z\3Z\3Z\3Z\3Z\3Z\3[\3[\3[\3[\3[\3[\3\\\3"+ + "\\\3\\\3\\\3\\\3]\3]\3]\3]\3]\3]\3^\3^\3^\3^\3^\3^\3_\3_\3_\3_\3_\3_\3"+ + "`\3`\3`\3`\3`\3`\3`\3a\3a\3a\3a\3a\3a\3b\3b\3b\3b\3b\3b\3b\3c\3c\3c\3"+ + "c\3c\3c\3d\3d\3d\3d\3d\3d\3e\3e\3e\3e\3f\3f\3f\3g\3g\3g\3g\3g\3g\3h\3"+ + "h\3h\3h\3h\3h\3h\3i\3i\3i\3i\3i\3i\3j\3j\7j\u02c1\nj\fj\16j\u02c4\13j"+ + "\3j\3j\3j\3j\3k\3k\7k\u02cc\nk\fk\16k\u02cf\13k\3k\3k\3l\3l\3l\3l\3m\6"+ + "m\u02d8\nm\rm\16m\u02d9\3n\3n\7n\u02de\nn\fn\16n\u02e1\13n\3o\3o\3o\6"+ + "o\u02e6\no\ro\16o\u02e7\5o\u02ea\no\3p\3p\6p\u02ee\np\rp\16p\u02ef\3q"+ + "\3q\6q\u02f4\nq\rq\16q\u02f5\3r\3r\3r\5r\u02fb\nr\3r\5r\u02fe\nr\3s\6"+ + "s\u0301\ns\rs\16s\u0302\3s\3s\6s\u0307\ns\rs\16s\u0308\5s\u030b\ns\3t"+ + "\3t\3t\3t\5t\u0311\nt\3u\3u\3u\7u\u0316\nu\fu\16u\u0319\13u\3u\3u\3u\3"+ + "v\3v\3v\3v\6v\u0322\nv\rv\16v\u0323\3v\3v\3v\3v\3v\3w\3w\3w\5w\u032e\n"+ + "w\3w\3w\3w\3\u0323\2x\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27"+ + "\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33"+ + "\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63"+ + "e\64g\65i\66k\67m8o9q:s;u{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089"+ + "F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009d"+ + "P\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1"+ + "Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3c\u00c5"+ + "d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1j\u00d3k\u00d5l\u00d7m\u00d9"+ + "n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5\2\u00e7\2\u00e9t\u00ebu\u00ed"+ + "v\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;"+ + "CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u0341\2\3\3\2\2\2\2\5\3\2\2\2"+ + "\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3"+ + "\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2"+ + "\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2"+ + "\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2"+ + "\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2"+ + "\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2"+ + "\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y"+ + "\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2"+ + "\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2"+ + "\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177"+ + "\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2"+ + "\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091"+ + "\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2"+ + "\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3"+ + "\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2"+ + "\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5"+ + "\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2"+ + "\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7"+ + "\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\2\u00cf\3\2\2"+ + "\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7\3\2\2\2\2\u00d9"+ + "\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2\2\2\u00e1\3\2\2"+ + "\2\2\u00e3\3\2\2\2\2\u00e9\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\3\u00ef"+ + "\3\2\2\2\5\u00f1\3\2\2\2\7\u00f3\3\2\2\2\t\u00f8\3\2\2\2\13\u0100\3\2"+ + "\2\2\r\u010a\3\2\2\2\17\u0114\3\2\2\2\21\u011d\3\2\2\2\23\u0125\3\2\2"+ + "\2\25\u0131\3\2\2\2\27\u013d\3\2\2\2\31\u0148\3\2\2\2\33\u0150\3\2\2\2"+ + "\35\u0152\3\2\2\2\37\u0154\3\2\2\2!\u015a\3\2\2\2#\u0161\3\2\2\2%\u0166"+ + "\3\2\2\2\'\u016b\3\2\2\2)\u0171\3\2\2\2+\u0175\3\2\2\2-\u017b\3\2\2\2"+ + "/\u0181\3\2\2\2\61\u0188\3\2\2\2\63\u018a\3\2\2\2\65\u018c\3\2\2\2\67"+ + "\u018f\3\2\2\29\u0192\3\2\2\2;\u0195\3\2\2\2=\u0199\3\2\2\2?\u019c\3\2"+ + "\2\2A\u01a0\3\2\2\2C\u01a3\3\2\2\2E\u01a6\3\2\2\2G\u01a9\3\2\2\2I\u01ac"+ + "\3\2\2\2K\u01af\3\2\2\2M\u01b1\3\2\2\2O\u01b3\3\2\2\2Q\u01b5\3\2\2\2S"+ + "\u01b7\3\2\2\2U\u01ba\3\2\2\2W\u01bc\3\2\2\2Y\u01be\3\2\2\2[\u01c1\3\2"+ + "\2\2]\u01c3\3\2\2\2_\u01c5\3\2\2\2a\u01c7\3\2\2\2c\u01ca\3\2\2\2e\u01cd"+ + "\3\2\2\2g\u01d0\3\2\2\2i\u01d3\3\2\2\2k\u01d5\3\2\2\2m\u01d7\3\2\2\2o"+ + "\u01d9\3\2\2\2q\u01dc\3\2\2\2s\u01e1\3\2\2\2u\u01e5\3\2\2\2w\u01e8\3\2"+ + "\2\2y\u01ec\3\2\2\2{\u01f0\3\2\2\2}\u01f7\3\2\2\2\177\u01fd\3\2\2\2\u0081"+ + "\u0206\3\2\2\2\u0083\u0208\3\2\2\2\u0085\u020a\3\2\2\2\u0087\u020c\3\2"+ + "\2\2\u0089\u020e\3\2\2\2\u008b\u0211\3\2\2\2\u008d\u0214\3\2\2\2\u008f"+ + "\u0217\3\2\2\2\u0091\u021a\3\2\2\2\u0093\u021d\3\2\2\2\u0095\u0220\3\2"+ + "\2\2\u0097\u0223\3\2\2\2\u0099\u0226\3\2\2\2\u009b\u022b\3\2\2\2\u009d"+ + "\u0231\3\2\2\2\u009f\u0236\3\2\2\2\u00a1\u023a\3\2\2\2\u00a3\u023d\3\2"+ + "\2\2\u00a5\u023f\3\2\2\2\u00a7\u0241\3\2\2\2\u00a9\u0248\3\2\2\2\u00ab"+ + "\u0251\3\2\2\2\u00ad\u0253\3\2\2\2\u00af\u0256\3\2\2\2\u00b1\u025b\3\2"+ + "\2\2\u00b3\u0261\3\2\2\2\u00b5\u0267\3\2\2\2\u00b7\u026d\3\2\2\2\u00b9"+ + "\u0272\3\2\2\2\u00bb\u0278\3\2\2\2\u00bd\u027e\3\2\2\2\u00bf\u0284\3\2"+ + "\2\2\u00c1\u028b\3\2\2\2\u00c3\u0291\3\2\2\2\u00c5\u0298\3\2\2\2\u00c7"+ + "\u029e\3\2\2\2\u00c9\u02a4\3\2\2\2\u00cb\u02a8\3\2\2\2\u00cd\u02ab\3\2"+ + "\2\2\u00cf\u02b1\3\2\2\2\u00d1\u02b8\3\2\2\2\u00d3\u02be\3\2\2\2\u00d5"+ + "\u02c9\3\2\2\2\u00d7\u02d2\3\2\2\2\u00d9\u02d7\3\2\2\2\u00db\u02db\3\2"+ + "\2\2\u00dd\u02e9\3\2\2\2\u00df\u02eb\3\2\2\2\u00e1\u02f1\3\2\2\2\u00e3"+ + "\u02f7\3\2\2\2\u00e5\u0300\3\2\2\2\u00e7\u0310\3\2\2\2\u00e9\u0312\3\2"+ + "\2\2\u00eb\u031d\3\2\2\2\u00ed\u032a\3\2\2\2\u00ef\u00f0\7\u0080\2\2\u00f0"+ + "\4\3\2\2\2\u00f1\u00f2\7<\2\2\u00f2\6\3\2\2\2\u00f3\u00f4\7i\2\2\u00f4"+ + "\u00f5\7q\2\2\u00f5\u00f6\7v\2\2\u00f6\u00f7\7q\2\2\u00f7\b\3\2\2\2\u00f8"+ + "\u00f9\7\'\2\2\u00f9\u00fa\7q\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7v\2"+ + "\2\u00fc\u00fd\7r\2\2\u00fd\u00fe\7w\2\2\u00fe\u00ff\7v\2\2\u00ff\n\3"+ + "\2\2\2\u0100\u0101\7\'\2\2\u0101\u0102\7n\2\2\u0102\u0103\7c\2\2\u0103"+ + "\u0104\7w\2\2\u0104\u0105\7p\2\2\u0105\u0106\7e\2\2\u0106\u0107\7j\2\2"+ + "\u0107\u0108\7g\2\2\u0108\u0109\7t\2\2\u0109\f\3\2\2\2\u010a\u010b\7\'"+ + "\2\2\u010b\u010c\7|\2\2\u010c\u010d\7g\2\2\u010d\u010e\7t\2\2\u010e\u010f"+ + "\7q\2\2\u010f\u0110\7r\2\2\u0110\u0111\7c\2\2\u0111\u0112\7i\2\2\u0112"+ + "\u0113\7g\2\2\u0113\16\3\2\2\2\u0114\u0115\7\'\2\2\u0115\u0116\7c\2\2"+ + "\u0116\u0117\7f\2\2\u0117\u0118\7f\2\2\u0118\u0119\7t\2\2\u0119\u011a"+ + "\7g\2\2\u011a\u011b\7u\2\2\u011b\u011c\7u\2\2\u011c\20\3\2\2\2\u011d\u011e"+ + "\7\'\2\2\u011e\u011f\7k\2\2\u011f\u0120\7o\2\2\u0120\u0121\7r\2\2\u0121"+ + "\u0122\7q\2\2\u0122\u0123\7t\2\2\u0123\u0124\7v\2\2\u0124\22\3\2\2\2\u0125"+ + "\u0126\7\'\2\2\u0126\u0127\7d\2\2\u0127\u0128\7t\2\2\u0128\u0129\7g\2"+ + "\2\u0129\u012a\7c\2\2\u012a\u012b\7m\2\2\u012b\u012c\7r\2\2\u012c\u012d"+ + "\7q\2\2\u012d\u012e\7k\2\2\u012e\u012f\7p\2\2\u012f\u0130\7v\2\2\u0130"+ + "\24\3\2\2\2\u0131\u0132\7\'\2\2\u0132\u0133\7c\2\2\u0133\u0134\7u\2\2"+ + "\u0134\u0135\7o\2\2\u0135\u0136\7k\2\2\u0136\u0137\7p\2\2\u0137\u0138"+ + "\7e\2\2\u0138\u0139\7n\2\2\u0139\u013a\7w\2\2\u013a\u013b\7f\2\2\u013b"+ + "\u013c\7g\2\2\u013c\26\3\2\2\2\u013d\u013e\7\'\2\2\u013e\u013f\7c\2\2"+ + "\u013f\u0140\7u\2\2\u0140\u0141\7o\2\2\u0141\u0142\7d\2\2\u0142\u0143"+ + "\7k\2\2\u0143\u0144\7p\2\2\u0144\u0145\7c\2\2\u0145\u0146\7t\2\2\u0146"+ + "\u0147\7{\2\2\u0147\30\3\2\2\2\u0148\u0149\7\'\2\2\u0149\u014a\7q\2\2"+ + "\u014a\u014b\7r\2\2\u014b\u014c\7v\2\2\u014c\u014d\7k\2\2\u014d\u014e"+ + "\7q\2\2\u014e\u014f\7p\2\2\u014f\32\3\2\2\2\u0150\u0151\7.\2\2\u0151\34"+ + "\3\2\2\2\u0152\u0153\7?\2\2\u0153\36\3\2\2\2\u0154\u0155\7e\2\2\u0155"+ + "\u0156\7q\2\2\u0156\u0157\7p\2\2\u0157\u0158\7u\2\2\u0158\u0159\7v\2\2"+ + "\u0159 \3\2\2\2\u015a\u015b\7o\2\2\u015b\u015c\7g\2\2\u015c\u015d\7o\2"+ + "\2\u015d\u015e\7q\2\2\u015e\u015f\7t\2\2\u015f\u0160\7{\2\2\u0160\"\3"+ + "\2\2\2\u0161\u0162\7d\2\2\u0162\u0163\7{\2\2\u0163\u0164\7v\2\2\u0164"+ + "\u0165\7g\2\2\u0165$\3\2\2\2\u0166\u0167\7y\2\2\u0167\u0168\7q\2\2\u0168"+ + "\u0169\7t\2\2\u0169\u016a\7f\2\2\u016a&\3\2\2\2\u016b\u016c\7h\2\2\u016c"+ + "\u016d\7n\2\2\u016d\u016e\7q\2\2\u016e\u016f\7c\2\2\u016f\u0170\7v\2\2"+ + "\u0170(\3\2\2\2\u0171\u0172\7u\2\2\u0172\u0173\7v\2\2\u0173\u0174\7t\2"+ + "\2\u0174*\3\2\2\2\u0175\u0176\7u\2\2\u0176\u0177\7v\2\2\u0177\u0178\7"+ + "t\2\2\u0178\u0179\7a\2\2\u0179\u017a\7r\2\2\u017a,\3\2\2\2\u017b\u017c"+ + "\7u\2\2\u017c\u017d\7v\2\2\u017d\u017e\7t\2\2\u017e\u017f\7a\2\2\u017f"+ + "\u0180\7u\2\2\u0180.\3\2\2\2\u0181\u0182\7u\2\2\u0182\u0183\7v\2\2\u0183"+ + "\u0184\7t\2\2\u0184\u0185\7a\2\2\u0185\u0186\7r\2\2\u0186\u0187\7u\2\2"+ + "\u0187\60\3\2\2\2\u0188\u0189\7]\2\2\u0189\62\3\2\2\2\u018a\u018b\7_\2"+ + "\2\u018b\64\3\2\2\2\u018c\u018d\7-\2\2\u018d\u018e\7?\2\2\u018e\66\3\2"+ + "\2\2\u018f\u0190\7/\2\2\u0190\u0191\7?\2\2\u01918\3\2\2\2\u0192\u0193"+ + "\7\61\2\2\u0193\u0194\7?\2\2\u0194:\3\2\2\2\u0195\u0196\7\61\2\2\u0196"+ + "\u0197\7\61\2\2\u0197\u0198\7?\2\2\u0198<\3\2\2\2\u0199\u019a\7,\2\2\u019a"+ + "\u019b\7?\2\2\u019b>\3\2\2\2\u019c\u019d\7,\2\2\u019d\u019e\7,\2\2\u019e"+ + "\u019f\7?\2\2\u019f@\3\2\2\2\u01a0\u01a1\7(\2\2\u01a1\u01a2\7?\2\2\u01a2"+ + "B\3\2\2\2\u01a3\u01a4\7~\2\2\u01a4\u01a5\7?\2\2\u01a5D\3\2\2\2\u01a6\u01a7"+ + "\7`\2\2\u01a7\u01a8\7?\2\2\u01a8F\3\2\2\2\u01a9\u01aa\7-\2\2\u01aa\u01ab"+ + "\7-\2\2\u01abH\3\2\2\2\u01ac\u01ad\7/\2\2\u01ad\u01ae\7/\2\2\u01aeJ\3"+ + "\2\2\2\u01af\u01b0\7*\2\2\u01b0L\3\2\2\2\u01b1\u01b2\7+\2\2\u01b2N\3\2"+ + "\2\2\u01b3\u01b4\7-\2\2\u01b4P\3\2\2\2\u01b5\u01b6\7/\2\2\u01b6R\3\2\2"+ + "\2\u01b7\u01b8\7,\2\2\u01b8\u01b9\7,\2\2\u01b9T\3\2\2\2\u01ba\u01bb\7"+ + ",\2\2\u01bbV\3\2\2\2\u01bc\u01bd\7\61\2\2\u01bdX\3\2\2\2\u01be\u01bf\7"+ + "\61\2\2\u01bf\u01c0\7\61\2\2\u01c0Z\3\2\2\2\u01c1\u01c2\7\'\2\2\u01c2"+ + "\\\3\2\2\2\u01c3\u01c4\7>\2\2\u01c4^\3\2\2\2\u01c5\u01c6\7@\2\2\u01c6"+ + "`\3\2\2\2\u01c7\u01c8\7>\2\2\u01c8\u01c9\7?\2\2\u01c9b\3\2\2\2\u01ca\u01cb"+ + "\7@\2\2\u01cb\u01cc\7?\2\2\u01ccd\3\2\2\2\u01cd\u01ce\7?\2\2\u01ce\u01cf"+ + "\7?\2\2\u01cff\3\2\2\2\u01d0\u01d1\7#\2\2\u01d1\u01d2\7?\2\2\u01d2h\3"+ + "\2\2\2\u01d3\u01d4\7(\2\2\u01d4j\3\2\2\2\u01d5\u01d6\7`\2\2\u01d6l\3\2"+ + "\2\2\u01d7\u01d8\7~\2\2\u01d8n\3\2\2\2\u01d9\u01da\7v\2\2\u01da\u01db"+ + "\7q\2\2\u01dbp\3\2\2\2\u01dc\u01dd\7u\2\2\u01dd\u01de\7v\2\2\u01de\u01df"+ + "\7g\2\2\u01df\u01e0\7r\2\2\u01e0r\3\2\2\2\u01e1\u01e2\7c\2\2\u01e2\u01e3"+ + "\7p\2\2\u01e3\u01e4\7f\2\2\u01e4t\3\2\2\2\u01e5\u01e6\7q\2\2\u01e6\u01e7"+ + "\7t\2\2\u01e7v\3\2\2\2\u01e8\u01e9\7z\2\2\u01e9\u01ea\7q\2\2\u01ea\u01eb"+ + "\7t\2\2\u01ebx\3\2\2\2\u01ec\u01ed\7p\2\2\u01ed\u01ee\7q\2\2\u01ee\u01ef"+ + "\7v\2\2\u01efz\3\2\2\2\u01f0\u01f1\7t\2\2\u01f1\u01f2\7g\2\2\u01f2\u01f3"+ + "\7v\2\2\u01f3\u01f4\7w\2\2\u01f4\u01f5\7t\2\2\u01f5\u01f6\7p\2\2\u01f6"+ + "|\3\2\2\2\u01f7\u01f8\7d\2\2\u01f8\u01f9\7t\2\2\u01f9\u01fa\7g\2\2\u01fa"+ + "\u01fb\7c\2\2\u01fb\u01fc\7m\2\2\u01fc~\3\2\2\2\u01fd\u01fe\7e\2\2\u01fe"+ + "\u01ff\7q\2\2\u01ff\u0200\7p\2\2\u0200\u0201\7v\2\2\u0201\u0202\7k\2\2"+ + "\u0202\u0203\7p\2\2\u0203\u0204\7w\2\2\u0204\u0205\7g\2\2\u0205\u0080"+ + "\3\2\2\2\u0206\u0207\7\60\2\2\u0207\u0082\3\2\2\2\u0208\u0209\7C\2\2\u0209"+ + "\u0084\3\2\2\2\u020a\u020b\7Z\2\2\u020b\u0086\3\2\2\2\u020c\u020d\7[\2"+ + "\2\u020d\u0088\3\2\2\2\u020e\u020f\7C\2\2\u020f\u0210\7Z\2\2\u0210\u008a"+ + "\3\2\2\2\u0211\u0212\7C\2\2\u0212\u0213\7[\2\2\u0213\u008c\3\2\2\2\u0214"+ + "\u0215\7Z\2\2\u0215\u0216\7[\2\2\u0216\u008e\3\2\2\2\u0217\u0218\7R\2"+ + "\2\u0218\u0219\7e\2\2\u0219\u0090\3\2\2\2\u021a\u021b\7R\2\2\u021b\u021c"+ + "\7|\2\2\u021c\u0092\3\2\2\2\u021d\u021e\7R\2\2\u021e\u021f\7p\2\2\u021f"+ + "\u0094\3\2\2\2\u0220\u0221\7R\2\2\u0221\u0222\7x\2\2\u0222\u0096\3\2\2"+ + "\2\u0223\u0224\7\60\2\2\u0224\u0225\7y\2\2\u0225\u0098\3\2\2\2\u0226\u0227"+ + "\7v\2\2\u0227\u0228\7t\2\2\u0228\u0229\7w\2\2\u0229\u022a\7g\2\2\u022a"+ + "\u009a\3\2\2\2\u022b\u022c\7h\2\2\u022c\u022d\7c\2\2\u022d\u022e\7n\2"+ + "\2\u022e\u022f\7u\2\2\u022f\u0230\7g\2\2\u0230\u009c\3\2\2\2\u0231\u0232"+ + "\7\'\2\2\u0232\u0233\7c\2\2\u0233\u0234\7u\2\2\u0234\u0235\7o\2\2\u0235"+ + "\u009e\3\2\2\2\u0236\u0237\7u\2\2\u0237\u0238\7w\2\2\u0238\u0239\7d\2"+ + "\2\u0239\u00a0\3\2\2\2\u023a\u023b\7/\2\2\u023b\u023c\7@\2\2\u023c\u00a2"+ + "\3\2\2\2\u023d\u023e\7}\2\2\u023e\u00a4\3\2\2\2\u023f\u0240\7\177\2\2"+ + "\u0240\u00a6\3\2\2\2\u0241\u0242\7c\2\2\u0242\u0243\7u\2\2\u0243\u0244"+ + "\7o\2\2\u0244\u0245\7u\2\2\u0245\u0246\7w\2\2\u0246\u0247\7d\2\2\u0247"+ + "\u00a8\3\2\2\2\u0248\u0249\7e\2\2\u0249\u024a\7n\2\2\u024a\u024b\7q\2"+ + "\2\u024b\u024c\7d\2\2\u024c\u024d\7d\2\2\u024d\u024e\7g\2\2\u024e\u024f"+ + "\7t\2\2\u024f\u0250\7u\2\2\u0250\u00aa\3\2\2\2\u0251\u0252\7B\2\2\u0252"+ + "\u00ac\3\2\2\2\u0253\u0254\7k\2\2\u0254\u0255\7h\2\2\u0255\u00ae\3\2\2"+ + "\2\u0256\u0257\7g\2\2\u0257\u0258\7n\2\2\u0258\u0259\7u\2\2\u0259\u025a"+ + "\7g\2\2\u025a\u00b0\3\2\2\2\u025b\u025c\7k\2\2\u025c\u025d\7h\2\2\u025d"+ + "\u025e\7a\2\2\u025e\u025f\7e\2\2\u025f\u0260\7u\2\2\u0260\u00b2\3\2\2"+ + "\2\u0261\u0262\7k\2\2\u0262\u0263\7h\2\2\u0263\u0264\7a\2\2\u0264\u0265"+ + "\7e\2\2\u0265\u0266\7e\2\2\u0266\u00b4\3\2\2\2\u0267\u0268\7k\2\2\u0268"+ + "\u0269\7h\2\2\u0269\u026a\7a\2\2\u026a\u026b\7g\2\2\u026b\u026c\7s\2\2"+ + "\u026c\u00b6\3\2\2\2\u026d\u026e\7k\2\2\u026e\u026f\7h\2\2\u026f\u0270"+ + "\7a\2\2\u0270\u0271\7|\2\2\u0271\u00b8\3\2\2\2\u0272\u0273\7k\2\2\u0273"+ + "\u0274\7h\2\2\u0274\u0275\7a\2\2\u0275\u0276\7p\2\2\u0276\u0277\7g\2\2"+ + "\u0277\u00ba\3\2\2\2\u0278\u0279\7k\2\2\u0279\u027a\7h\2\2\u027a\u027b"+ + "\7a\2\2\u027b\u027c\7p\2\2\u027c\u027d\7|\2\2\u027d\u00bc\3\2\2\2\u027e"+ + "\u027f\7k\2\2\u027f\u0280\7h\2\2\u0280\u0281\7a\2\2\u0281\u0282\7r\2\2"+ + "\u0282\u0283\7n\2\2\u0283\u00be\3\2\2\2\u0284\u0285\7k\2\2\u0285\u0286"+ + "\7h\2\2\u0286\u0287\7a\2\2\u0287\u0288\7r\2\2\u0288\u0289\7q\2\2\u0289"+ + "\u028a\7u\2\2\u028a\u00c0\3\2\2\2\u028b\u028c\7k\2\2\u028c\u028d\7h\2"+ + "\2\u028d\u028e\7a\2\2\u028e\u028f\7o\2\2\u028f\u0290\7k\2\2\u0290\u00c2"+ + "\3\2\2\2\u0291\u0292\7k\2\2\u0292\u0293\7h\2\2\u0293\u0294\7a\2\2\u0294"+ + "\u0295\7p\2\2\u0295\u0296\7g\2\2\u0296\u0297\7i\2\2\u0297\u00c4\3\2\2"+ + "\2\u0298\u0299\7k\2\2\u0299\u029a\7h\2\2\u029a\u029b\7a\2\2\u029b\u029c"+ + "\7x\2\2\u029c\u029d\7u\2\2\u029d\u00c6\3\2\2\2\u029e\u029f\7k\2\2\u029f"+ + "\u02a0\7h\2\2\u02a0\u02a1\7a\2\2\u02a1\u02a2\7x\2\2\u02a2\u02a3\7e\2\2"+ + "\u02a3\u00c8\3\2\2\2\u02a4\u02a5\7h\2\2\u02a5\u02a6\7q\2\2\u02a6\u02a7"+ + "\7t\2\2\u02a7\u00ca\3\2\2\2\u02a8\u02a9\7k\2\2\u02a9\u02aa\7p\2\2\u02aa"+ + "\u00cc\3\2\2\2\u02ab\u02ac\7y\2\2\u02ac\u02ad\7j\2\2\u02ad\u02ae\7k\2"+ + "\2\u02ae\u02af\7n\2\2\u02af\u02b0\7g\2\2\u02b0\u00ce\3\2\2\2\u02b1\u02b2"+ + "\7t\2\2\u02b2\u02b3\7g\2\2\u02b3\u02b4\7r\2\2\u02b4\u02b5\7g\2\2\u02b5"+ + "\u02b6\7c\2\2\u02b6\u02b7\7v\2\2\u02b7\u00d0\3\2\2\2\u02b8\u02b9\7w\2"+ + "\2\u02b9\u02ba\7p\2\2\u02ba\u02bb\7v\2\2\u02bb\u02bc\7k\2\2\u02bc\u02bd"+ + "\7n\2\2\u02bd\u00d2\3\2\2\2\u02be\u02c2\t\2\2\2\u02bf\u02c1\t\3\2\2\u02c0"+ + "\u02bf\3\2\2\2\u02c1\u02c4\3\2\2\2\u02c2\u02c0\3\2\2\2\u02c2\u02c3\3\2"+ + "\2\2\u02c3\u02c5\3\2\2\2\u02c4\u02c2\3\2\2\2\u02c5\u02c6\5\u00d5k\2\u02c6"+ + "\u02c7\3\2\2\2\u02c7\u02c8\bj\2\2\u02c8\u00d4\3\2\2\2\u02c9\u02cd\7=\2"+ + "\2\u02ca\u02cc\n\2\2\2\u02cb\u02ca\3\2\2\2\u02cc\u02cf\3\2\2\2\u02cd\u02cb"+ + "\3\2\2\2\u02cd\u02ce\3\2\2\2\u02ce\u02d0\3\2\2\2\u02cf\u02cd\3\2\2\2\u02d0"+ + "\u02d1\bk\2\2\u02d1\u00d6\3\2\2\2\u02d2\u02d3\t\3\2\2\u02d3\u02d4\3\2"+ + "\2\2\u02d4\u02d5\bl\3\2\u02d5\u00d8\3\2\2\2\u02d6\u02d8\t\2\2\2\u02d7"+ + "\u02d6\3\2\2\2\u02d8\u02d9\3\2\2\2\u02d9\u02d7\3\2\2\2\u02d9\u02da\3\2"+ + "\2\2\u02da\u00da\3\2\2\2\u02db\u02df\t\4\2\2\u02dc\u02de\t\5\2\2\u02dd"+ + "\u02dc\3\2\2\2\u02de\u02e1\3\2\2\2\u02df\u02dd\3\2\2\2\u02df\u02e0\3\2"+ + "\2\2\u02e0\u00dc\3\2\2\2\u02e1\u02df\3\2\2\2\u02e2\u02ea\4\62;\2\u02e3"+ + "\u02e5\4\63;\2\u02e4\u02e6\4\62;\2\u02e5\u02e4\3\2\2\2\u02e6\u02e7\3\2"+ + "\2\2\u02e7\u02e5\3\2\2\2\u02e7\u02e8\3\2\2\2\u02e8\u02ea\3\2\2\2\u02e9"+ + "\u02e2\3\2\2\2\u02e9\u02e3\3\2\2\2\u02ea\u00de\3\2\2\2\u02eb\u02ed\7&"+ + "\2\2\u02ec\u02ee\t\6\2\2\u02ed\u02ec\3\2\2\2\u02ee\u02ef\3\2\2\2\u02ef"+ + "\u02ed\3\2\2\2\u02ef\u02f0\3\2\2\2\u02f0\u00e0\3\2\2\2\u02f1\u02f3\7\'"+ + "\2\2\u02f2\u02f4\4\62\63\2\u02f3\u02f2\3\2\2\2\u02f4\u02f5\3\2\2\2\u02f5"+ + "\u02f3\3\2\2\2\u02f5\u02f6\3\2\2\2\u02f6\u00e2\3\2\2\2\u02f7\u02fd\5\u00e5"+ + "s\2\u02f8\u02fa\t\7\2\2\u02f9\u02fb\t\b\2\2\u02fa\u02f9\3\2\2\2\u02fa"+ + "\u02fb\3\2\2\2\u02fb\u02fc\3\2\2\2\u02fc\u02fe\5\u00e5s\2\u02fd\u02f8"+ + "\3\2\2\2\u02fd\u02fe\3\2\2\2\u02fe\u00e4\3\2\2\2\u02ff\u0301\4\62;\2\u0300"+ + "\u02ff\3\2\2\2\u0301\u0302\3\2\2\2\u0302\u0300\3\2\2\2\u0302\u0303\3\2"+ + "\2\2\u0303\u030a\3\2\2\2\u0304\u0306\7\60\2\2\u0305\u0307\4\62;\2\u0306"+ + "\u0305\3\2\2\2\u0307\u0308\3\2\2\2\u0308\u0306\3\2\2\2\u0308\u0309\3\2"+ + "\2\2\u0309\u030b\3\2\2\2\u030a\u0304\3\2\2\2\u030a\u030b\3\2\2\2\u030b"+ + "\u00e6\3\2\2\2\u030c\u030d\7^\2\2\u030d\u0311\13\2\2\2\u030e\u030f\7^"+ + "\2\2\u030f\u0311\5\u00d9m\2\u0310\u030c\3\2\2\2\u0310\u030e\3\2\2\2\u0311"+ + "\u00e8\3\2\2\2\u0312\u0317\7$\2\2\u0313\u0316\5\u00e7t\2\u0314\u0316\n"+ + "\t\2\2\u0315\u0313\3\2\2\2\u0315\u0314\3\2\2\2\u0316\u0319\3\2\2\2\u0317"+ + "\u0315\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u031a\3\2\2\2\u0319\u0317\3\2"+ + "\2\2\u031a\u031b\7$\2\2\u031b\u031c\bu\4\2\u031c\u00ea\3\2\2\2\u031d\u031e"+ + "\7}\2\2\u031e\u031f\7}\2\2\u031f\u0321\3\2\2\2\u0320\u0322\13\2\2\2\u0321"+ + "\u0320\3\2\2\2\u0322\u0323\3\2\2\2\u0323\u0324\3\2\2\2\u0323\u0321\3\2"+ + "\2\2\u0324\u0325\3\2\2\2\u0325\u0326\7\177\2\2\u0326\u0327\7\177\2\2\u0327"+ + "\u0328\3\2\2\2\u0328\u0329\bv\5\2\u0329\u00ec\3\2\2\2\u032a\u032d\7)\2"+ + "\2\u032b\u032e\5\u00e7t\2\u032c\u032e\n\t\2\2\u032d\u032b\3\2\2\2\u032d"+ + "\u032c\3\2\2\2\u032e\u032f\3\2\2\2\u032f\u0330\7)\2\2\u0330\u0331\bw\6"+ + "\2\u0331\u00ee\3\2\2\2\26\2\u02c2\u02cd\u02d9\u02df\u02e7\u02e9\u02ed"+ + "\u02ef\u02f5\u02fa\u02fd\u0302\u0308\u030a\u0310\u0315\u0317\u0323\u032d"+ + "\7\2\3\2\b\2\2\3u\2\3v\3\3w\4"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/compiler/src/prog8/parser/prog8Parser.java b/compiler/src/prog8/parser/prog8Parser.java index 6d793bcc4..22074f94a 100644 --- a/compiler/src/prog8/parser/prog8Parser.java +++ b/compiler/src/prog8/parser/prog8Parser.java @@ -30,9 +30,10 @@ public class prog8Parser extends Parser { T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, - T__94=95, T__95=96, T__96=97, LINECOMMENT=98, COMMENT=99, WS=100, EOL=101, - NAME=102, DEC_INTEGER=103, HEX_INTEGER=104, BIN_INTEGER=105, FLOAT_NUMBER=106, - STRING=107, INLINEASMBLOCK=108, SINGLECHAR=109; + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, LINECOMMENT=105, COMMENT=106, WS=107, + EOL=108, NAME=109, DEC_INTEGER=110, HEX_INTEGER=111, BIN_INTEGER=112, + FLOAT_NUMBER=113, STRING=114, INLINEASMBLOCK=115, SINGLECHAR=116; public static final int RULE_module = 0, RULE_modulestatement = 1, RULE_block = 2, RULE_statement = 3, RULE_labeldef = 4, RULE_unconditionaljump = 5, RULE_directive = 6, RULE_directivearg = 7, @@ -41,25 +42,28 @@ public class prog8Parser extends Parser { RULE_assign_target = 16, RULE_postincrdecr = 17, RULE_expression = 18, RULE_functioncall = 19, RULE_functioncall_stmt = 20, RULE_expression_list = 21, RULE_returnstmt = 22, RULE_breakstmt = 23, RULE_continuestmt = 24, RULE_identifier = 25, - RULE_scoped_identifier = 26, RULE_register = 27, RULE_integerliteral = 28, - RULE_wordsuffix = 29, RULE_booleanliteral = 30, RULE_arrayliteral = 31, - RULE_stringliteral = 32, RULE_charliteral = 33, RULE_floatliteral = 34, - RULE_literalvalue = 35, RULE_inlineasm = 36, RULE_subroutine = 37, RULE_sub_return_part = 38, - RULE_statement_block = 39, RULE_sub_address = 40, RULE_sub_params = 41, - RULE_sub_param = 42, RULE_sub_returns = 43, RULE_if_stmt = 44, RULE_else_part = 45, - RULE_branch_stmt = 46, RULE_branchcondition = 47, RULE_forloop = 48, RULE_whileloop = 49, - RULE_repeatloop = 50; + RULE_scoped_identifier = 26, RULE_register = 27, RULE_statusregister = 28, + RULE_integerliteral = 29, RULE_wordsuffix = 30, RULE_booleanliteral = 31, + RULE_arrayliteral = 32, RULE_stringliteral = 33, RULE_charliteral = 34, + RULE_floatliteral = 35, RULE_literalvalue = 36, RULE_inlineasm = 37, RULE_subroutine = 38, + RULE_sub_return_part = 39, RULE_statement_block = 40, RULE_sub_params = 41, + RULE_sub_param = 42, RULE_sub_returns = 43, RULE_asmsubroutine = 44, RULE_asmsub_address = 45, + RULE_asmsub_params = 46, RULE_asmsub_param = 47, RULE_clobber = 48, RULE_asmsub_returns = 49, + RULE_asmsub_return = 50, RULE_if_stmt = 51, RULE_else_part = 52, RULE_branch_stmt = 53, + RULE_branchcondition = 54, RULE_forloop = 55, RULE_whileloop = 56, RULE_repeatloop = 57; public static final String[] ruleNames = { "module", "modulestatement", "block", "statement", "labeldef", "unconditionaljump", "directive", "directivearg", "vardecl", "varinitializer", "constdecl", "memoryvardecl", "datatype", "arrayspec", "assignment", "augassignment", "assign_target", "postincrdecr", "expression", "functioncall", "functioncall_stmt", "expression_list", "returnstmt", "breakstmt", "continuestmt", "identifier", - "scoped_identifier", "register", "integerliteral", "wordsuffix", "booleanliteral", - "arrayliteral", "stringliteral", "charliteral", "floatliteral", "literalvalue", - "inlineasm", "subroutine", "sub_return_part", "statement_block", "sub_address", - "sub_params", "sub_param", "sub_returns", "if_stmt", "else_part", "branch_stmt", - "branchcondition", "forloop", "whileloop", "repeatloop" + "scoped_identifier", "register", "statusregister", "integerliteral", "wordsuffix", + "booleanliteral", "arrayliteral", "stringliteral", "charliteral", "floatliteral", + "literalvalue", "inlineasm", "subroutine", "sub_return_part", "statement_block", + "sub_params", "sub_param", "sub_returns", "asmsubroutine", "asmsub_address", + "asmsub_params", "asmsub_param", "clobber", "asmsub_returns", "asmsub_return", + "if_stmt", "else_part", "branch_stmt", "branchcondition", "forloop", "whileloop", + "repeatloop" }; private static final String[] _LITERAL_NAMES = { @@ -71,11 +75,12 @@ public class prog8Parser extends Parser { "'--'", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", "'return'", "'break'", "'continue'", - "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'.w'", "'true'", - "'false'", "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'if'", "'else'", - "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", "'if_nz'", "'if_pl'", - "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", - "'while'", "'repeat'", "'until'" + "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", + "'Pv'", "'.w'", "'true'", "'false'", "'%asm'", "'sub'", "'->'", "'{'", + "'}'", "'asmsub'", "'clobbers'", "'@'", "'if'", "'else'", "'if_cs'", "'if_cc'", + "'if_eq'", "'if_z'", "'if_ne'", "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", + "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", "'while'", "'repeat'", + "'until'" }; private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null, null, @@ -86,9 +91,9 @@ public class prog8Parser extends Parser { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", - "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK", - "SINGLECHAR" + null, null, null, null, null, null, null, null, null, "LINECOMMENT", "COMMENT", + "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", + "STRING", "INLINEASMBLOCK", "SINGLECHAR" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -164,12 +169,12 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(106); + setState(120); _errHandler.sync(this); _la = _input.LA(1); while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << T__7) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11))) != 0) || _la==EOL) { { - setState(104); + setState(118); _errHandler.sync(this); switch (_input.LA(1)) { case T__0: @@ -183,13 +188,13 @@ public class prog8Parser extends Parser { case T__10: case T__11: { - setState(102); + setState(116); modulestatement(); } break; case EOL: { - setState(103); + setState(117); match(EOL); } break; @@ -197,11 +202,11 @@ public class prog8Parser extends Parser { throw new NoViableAltException(this); } } - setState(108); + setState(122); _errHandler.sync(this); _la = _input.LA(1); } - setState(109); + setState(123); match(EOF); } } @@ -233,7 +238,7 @@ public class prog8Parser extends Parser { ModulestatementContext _localctx = new ModulestatementContext(_ctx, getState()); enterRule(_localctx, 2, RULE_modulestatement); try { - setState(113); + setState(127); _errHandler.sync(this); switch (_input.LA(1)) { case T__3: @@ -247,14 +252,14 @@ public class prog8Parser extends Parser { case T__11: enterOuterAlt(_localctx, 1); { - setState(111); + setState(125); directive(); } break; case T__0: enterOuterAlt(_localctx, 2); { - setState(112); + setState(126); block(); } break; @@ -297,23 +302,23 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(115); + setState(129); match(T__0); - setState(116); + setState(130); identifier(); - setState(118); + setState(132); _errHandler.sync(this); _la = _input.LA(1); - if (((((_la - 103)) & ~0x3f) == 0 && ((1L << (_la - 103)) & ((1L << (DEC_INTEGER - 103)) | (1L << (HEX_INTEGER - 103)) | (1L << (BIN_INTEGER - 103)))) != 0)) { + if (((((_la - 110)) & ~0x3f) == 0 && ((1L << (_la - 110)) & ((1L << (DEC_INTEGER - 110)) | (1L << (HEX_INTEGER - 110)) | (1L << (BIN_INTEGER - 110)))) != 0)) { { - setState(117); + setState(131); integerliteral(); } } - setState(120); + setState(134); statement_block(); - setState(121); + setState(135); match(EOL); } } @@ -368,6 +373,9 @@ public class prog8Parser extends Parser { public SubroutineContext subroutine() { return getRuleContext(SubroutineContext.class,0); } + public AsmsubroutineContext asmsubroutine() { + return getRuleContext(AsmsubroutineContext.class,0); + } public InlineasmContext inlineasm() { return getRuleContext(InlineasmContext.class,0); } @@ -402,153 +410,160 @@ public class prog8Parser extends Parser { StatementContext _localctx = new StatementContext(_ctx, getState()); enterRule(_localctx, 6, RULE_statement); try { - setState(144); + setState(159); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(123); + setState(137); directive(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(124); + setState(138); varinitializer(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(125); + setState(139); vardecl(); } break; case 4: enterOuterAlt(_localctx, 4); { - setState(126); + setState(140); constdecl(); } break; case 5: enterOuterAlt(_localctx, 5); { - setState(127); + setState(141); memoryvardecl(); } break; case 6: enterOuterAlt(_localctx, 6); { - setState(128); + setState(142); assignment(); } break; case 7: enterOuterAlt(_localctx, 7); { - setState(129); + setState(143); augassignment(); } break; case 8: enterOuterAlt(_localctx, 8); { - setState(130); + setState(144); unconditionaljump(); } break; case 9: enterOuterAlt(_localctx, 9); { - setState(131); + setState(145); postincrdecr(); } break; case 10: enterOuterAlt(_localctx, 10); { - setState(132); + setState(146); functioncall_stmt(); } break; case 11: enterOuterAlt(_localctx, 11); { - setState(133); + setState(147); if_stmt(); } break; case 12: enterOuterAlt(_localctx, 12); { - setState(134); + setState(148); branch_stmt(); } break; case 13: enterOuterAlt(_localctx, 13); { - setState(135); + setState(149); subroutine(); } break; case 14: enterOuterAlt(_localctx, 14); { - setState(136); - inlineasm(); + setState(150); + asmsubroutine(); } break; case 15: enterOuterAlt(_localctx, 15); { - setState(137); - returnstmt(); + setState(151); + inlineasm(); } break; case 16: enterOuterAlt(_localctx, 16); { - setState(138); - forloop(); + setState(152); + returnstmt(); } break; case 17: enterOuterAlt(_localctx, 17); { - setState(139); - whileloop(); + setState(153); + forloop(); } break; case 18: enterOuterAlt(_localctx, 18); { - setState(140); - repeatloop(); + setState(154); + whileloop(); } break; case 19: enterOuterAlt(_localctx, 19); { - setState(141); - breakstmt(); + setState(155); + repeatloop(); } break; case 20: enterOuterAlt(_localctx, 20); { - setState(142); - continuestmt(); + setState(156); + breakstmt(); } break; case 21: enterOuterAlt(_localctx, 21); { - setState(143); + setState(157); + continuestmt(); + } + break; + case 22: + enterOuterAlt(_localctx, 22); + { + setState(158); labeldef(); } break; @@ -581,9 +596,9 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(146); + setState(161); identifier(); - setState(147); + setState(162); match(T__1); } } @@ -620,26 +635,26 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(149); + setState(164); match(T__2); - setState(153); + setState(168); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) { case 1: { - setState(150); + setState(165); integerliteral(); } break; case 2: { - setState(151); + setState(166); identifier(); } break; case 3: { - setState(152); + setState(167); scoped_identifier(); } break; @@ -678,7 +693,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(155); + setState(170); ((DirectiveContext)_localctx).directivename = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << T__7) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11))) != 0)) ) { @@ -689,17 +704,17 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(167); + setState(182); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { case 1: { - setState(157); + setState(172); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { case 1: { - setState(156); + setState(171); directivearg(); } break; @@ -708,21 +723,21 @@ public class prog8Parser extends Parser { break; case 2: { - setState(159); + setState(174); directivearg(); - setState(164); + setState(179); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(160); + setState(175); match(T__12); - setState(161); + setState(176); directivearg(); } } - setState(166); + setState(181); _errHandler.sync(this); _la = _input.LA(1); } @@ -762,20 +777,20 @@ public class prog8Parser extends Parser { DirectiveargContext _localctx = new DirectiveargContext(_ctx, getState()); enterRule(_localctx, 14, RULE_directivearg); try { - setState(172); + setState(187); _errHandler.sync(this); switch (_input.LA(1)) { case STRING: enterOuterAlt(_localctx, 1); { - setState(169); + setState(184); stringliteral(); } break; case NAME: enterOuterAlt(_localctx, 2); { - setState(170); + setState(185); identifier(); } break; @@ -784,7 +799,7 @@ public class prog8Parser extends Parser { case BIN_INTEGER: enterOuterAlt(_localctx, 3); { - setState(171); + setState(186); integerliteral(); } break; @@ -826,19 +841,19 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(174); + setState(189); datatype(); - setState(176); + setState(191); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__23) { { - setState(175); + setState(190); arrayspec(); } } - setState(178); + setState(193); identifier(); } } @@ -879,23 +894,23 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(180); + setState(195); datatype(); - setState(182); + setState(197); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__23) { { - setState(181); + setState(196); arrayspec(); } } - setState(184); + setState(199); identifier(); - setState(185); + setState(200); match(T__13); - setState(186); + setState(201); expression(0); } } @@ -926,9 +941,9 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(188); + setState(203); match(T__14); - setState(189); + setState(204); varinitializer(); } } @@ -959,9 +974,9 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(191); + setState(206); match(T__15); - setState(192); + setState(207); varinitializer(); } } @@ -990,7 +1005,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(194); + setState(209); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) ) { _errHandler.recoverInline(this); @@ -1033,23 +1048,23 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(196); + setState(211); match(T__23); - setState(197); + setState(212); expression(0); - setState(200); + setState(215); _errHandler.sync(this); _la = _input.LA(1); if (_la==T__12) { { - setState(198); + setState(213); match(T__12); - setState(199); + setState(214); expression(0); } } - setState(202); + setState(217); match(T__24); } } @@ -1083,11 +1098,11 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(204); + setState(219); assign_target(); - setState(205); + setState(220); match(T__13); - setState(206); + setState(221); expression(0); } } @@ -1123,9 +1138,9 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(208); + setState(223); assign_target(); - setState(209); + setState(224); ((AugassignmentContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__25) | (1L << T__26) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33))) != 0)) ) { @@ -1136,7 +1151,7 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(210); + setState(225); expression(0); } } @@ -1171,27 +1186,27 @@ public class prog8Parser extends Parser { Assign_targetContext _localctx = new Assign_targetContext(_ctx, getState()); enterRule(_localctx, 32, RULE_assign_target); try { - setState(215); + setState(230); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(212); + setState(227); register(); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(213); + setState(228); identifier(); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(214); + setState(229); scoped_identifier(); } break; @@ -1226,9 +1241,9 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(217); + setState(232); assign_target(); - setState(218); + setState(233); ((PostincrdecrContext)_localctx).operator = _input.LT(1); _la = _input.LA(1); if ( !(_la==T__34 || _la==T__35) ) { @@ -1306,28 +1321,28 @@ public class prog8Parser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(234); + setState(249); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { case 1: { - setState(221); + setState(236); match(T__36); - setState(222); + setState(237); expression(0); - setState(223); + setState(238); match(T__37); } break; case 2: { - setState(225); + setState(240); functioncall(); } break; case 3: { - setState(226); + setState(241); ((ExpressionContext)_localctx).prefix = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__38) | (1L << T__39))) != 0)) ) { @@ -1338,45 +1353,45 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(227); + setState(242); expression(18); } break; case 4: { - setState(228); + setState(243); ((ExpressionContext)_localctx).prefix = match(T__59); - setState(229); + setState(244); expression(5); } break; case 5: { - setState(230); + setState(245); literalvalue(); } break; case 6: { - setState(231); + setState(246); register(); } break; case 7: { - setState(232); + setState(247); identifier(); } break; case 8: { - setState(233); + setState(248); scoped_identifier(); } break; } _ctx.stop = _input.LT(-1); - setState(280); + setState(295); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { @@ -1384,7 +1399,7 @@ public class prog8Parser extends Parser { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(278); + setState(293); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) { case 1: @@ -1393,11 +1408,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(236); + setState(251); if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)"); - setState(237); + setState(252); ((ExpressionContext)_localctx).bop = match(T__40); - setState(238); + setState(253); ((ExpressionContext)_localctx).right = expression(18); } break; @@ -1407,9 +1422,9 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(239); + setState(254); if (!(precpred(_ctx, 16))) throw new FailedPredicateException(this, "precpred(_ctx, 16)"); - setState(240); + setState(255); ((ExpressionContext)_localctx).bop = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__44))) != 0)) ) { @@ -1420,7 +1435,7 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(241); + setState(256); ((ExpressionContext)_localctx).right = expression(17); } break; @@ -1430,9 +1445,9 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(242); + setState(257); if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)"); - setState(243); + setState(258); ((ExpressionContext)_localctx).bop = _input.LT(1); _la = _input.LA(1); if ( !(_la==T__38 || _la==T__39) ) { @@ -1443,7 +1458,7 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(244); + setState(259); ((ExpressionContext)_localctx).right = expression(16); } break; @@ -1453,9 +1468,9 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(245); + setState(260); if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)"); - setState(246); + setState(261); ((ExpressionContext)_localctx).bop = _input.LT(1); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48))) != 0)) ) { @@ -1466,7 +1481,7 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(247); + setState(262); ((ExpressionContext)_localctx).right = expression(15); } break; @@ -1476,9 +1491,9 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(248); + setState(263); if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)"); - setState(249); + setState(264); ((ExpressionContext)_localctx).bop = _input.LT(1); _la = _input.LA(1); if ( !(_la==T__49 || _la==T__50) ) { @@ -1489,7 +1504,7 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(250); + setState(265); ((ExpressionContext)_localctx).right = expression(14); } break; @@ -1499,11 +1514,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(251); + setState(266); if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); - setState(252); + setState(267); ((ExpressionContext)_localctx).bop = match(T__51); - setState(253); + setState(268); ((ExpressionContext)_localctx).right = expression(13); } break; @@ -1513,11 +1528,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(254); + setState(269); if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)"); - setState(255); + setState(270); ((ExpressionContext)_localctx).bop = match(T__52); - setState(256); + setState(271); ((ExpressionContext)_localctx).right = expression(12); } break; @@ -1527,11 +1542,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(257); + setState(272); if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); - setState(258); + setState(273); ((ExpressionContext)_localctx).bop = match(T__53); - setState(259); + setState(274); ((ExpressionContext)_localctx).right = expression(11); } break; @@ -1541,11 +1556,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(260); + setState(275); if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); - setState(261); + setState(276); ((ExpressionContext)_localctx).bop = match(T__56); - setState(262); + setState(277); ((ExpressionContext)_localctx).right = expression(9); } break; @@ -1555,11 +1570,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(263); + setState(278); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(264); + setState(279); ((ExpressionContext)_localctx).bop = match(T__57); - setState(265); + setState(280); ((ExpressionContext)_localctx).right = expression(8); } break; @@ -1569,11 +1584,11 @@ public class prog8Parser extends Parser { _localctx.left = _prevctx; _localctx.left = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(266); + setState(281); if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); - setState(267); + setState(282); ((ExpressionContext)_localctx).bop = match(T__58); - setState(268); + setState(283); ((ExpressionContext)_localctx).right = expression(7); } break; @@ -1581,9 +1596,9 @@ public class prog8Parser extends Parser { { _localctx = new ExpressionContext(_parentctx, _parentState); pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(269); + setState(284); if (!(precpred(_ctx, 20))) throw new FailedPredicateException(this, "precpred(_ctx, 20)"); - setState(270); + setState(285); arrayspec(); } break; @@ -1593,20 +1608,20 @@ public class prog8Parser extends Parser { _localctx.rangefrom = _prevctx; _localctx.rangefrom = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(271); + setState(286); if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); - setState(272); + setState(287); match(T__54); - setState(273); + setState(288); ((ExpressionContext)_localctx).rangeto = expression(0); - setState(276); + setState(291); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) { case 1: { - setState(274); + setState(289); match(T__55); - setState(275); + setState(290); ((ExpressionContext)_localctx).rangestep = expression(0); } break; @@ -1616,7 +1631,7 @@ public class prog8Parser extends Parser { } } } - setState(282); + setState(297); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,17,_ctx); } @@ -1656,35 +1671,35 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(285); + setState(300); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: { - setState(283); + setState(298); identifier(); } break; case 2: { - setState(284); + setState(299); scoped_identifier(); } break; } - setState(287); + setState(302); match(T__36); - setState(289); + setState(304); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__36) | (1L << T__38) | (1L << T__39) | (1L << T__59))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__71 - 65)) | (1L << (T__72 - 65)) | (1L << (NAME - 65)) | (1L << (DEC_INTEGER - 65)) | (1L << (HEX_INTEGER - 65)) | (1L << (BIN_INTEGER - 65)) | (1L << (FLOAT_NUMBER - 65)) | (1L << (STRING - 65)) | (1L << (SINGLECHAR - 65)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__36) | (1L << T__38) | (1L << T__39) | (1L << T__59))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__75 - 65)) | (1L << (T__76 - 65)) | (1L << (NAME - 65)) | (1L << (DEC_INTEGER - 65)) | (1L << (HEX_INTEGER - 65)) | (1L << (BIN_INTEGER - 65)) | (1L << (FLOAT_NUMBER - 65)) | (1L << (STRING - 65)) | (1L << (SINGLECHAR - 65)))) != 0)) { { - setState(288); + setState(303); expression_list(); } } - setState(291); + setState(306); match(T__37); } } @@ -1722,35 +1737,35 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(295); + setState(310); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) { case 1: { - setState(293); + setState(308); identifier(); } break; case 2: { - setState(294); + setState(309); scoped_identifier(); } break; } - setState(297); + setState(312); match(T__36); - setState(299); + setState(314); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__36) | (1L << T__38) | (1L << T__39) | (1L << T__59))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__71 - 65)) | (1L << (T__72 - 65)) | (1L << (NAME - 65)) | (1L << (DEC_INTEGER - 65)) | (1L << (HEX_INTEGER - 65)) | (1L << (BIN_INTEGER - 65)) | (1L << (FLOAT_NUMBER - 65)) | (1L << (STRING - 65)) | (1L << (SINGLECHAR - 65)))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__23) | (1L << T__36) | (1L << T__38) | (1L << T__39) | (1L << T__59))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__75 - 65)) | (1L << (T__76 - 65)) | (1L << (NAME - 65)) | (1L << (DEC_INTEGER - 65)) | (1L << (HEX_INTEGER - 65)) | (1L << (BIN_INTEGER - 65)) | (1L << (FLOAT_NUMBER - 65)) | (1L << (STRING - 65)) | (1L << (SINGLECHAR - 65)))) != 0)) { { - setState(298); + setState(313); expression_list(); } } - setState(301); + setState(316); match(T__37); } } @@ -1785,21 +1800,21 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(303); + setState(318); expression(0); - setState(308); + setState(323); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(304); + setState(319); match(T__12); - setState(305); + setState(320); expression(0); } } - setState(310); + setState(325); _errHandler.sync(this); _la = _input.LA(1); } @@ -1832,14 +1847,14 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(311); + setState(326); match(T__60); - setState(313); + setState(328); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,23,_ctx) ) { case 1: { - setState(312); + setState(327); expression_list(); } break; @@ -1870,7 +1885,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(315); + setState(330); match(T__61); } } @@ -1898,7 +1913,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(317); + setState(332); match(T__62); } } @@ -1927,7 +1942,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(319); + setState(334); match(NAME); } } @@ -1960,9 +1975,9 @@ public class prog8Parser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(321); + setState(336); match(NAME); - setState(324); + setState(339); _errHandler.sync(this); _alt = 1; do { @@ -1970,9 +1985,9 @@ public class prog8Parser extends Parser { case 1: { { - setState(322); + setState(337); match(T__63); - setState(323); + setState(338); match(NAME); } } @@ -1980,7 +1995,7 @@ public class prog8Parser extends Parser { default: throw new NoViableAltException(this); } - setState(326); + setState(341); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,24,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); @@ -2011,7 +2026,7 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(328); + setState(343); _la = _input.LA(1); if ( !(((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)))) != 0)) ) { _errHandler.recoverInline(this); @@ -2034,6 +2049,43 @@ public class prog8Parser extends Parser { return _localctx; } + public static class StatusregisterContext extends ParserRuleContext { + public StatusregisterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statusregister; } + } + + public final StatusregisterContext statusregister() throws RecognitionException { + StatusregisterContext _localctx = new StatusregisterContext(_ctx, getState()); + enterRule(_localctx, 56, RULE_statusregister); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(345); + _la = _input.LA(1); + if ( !(((((_la - 71)) & ~0x3f) == 0 && ((1L << (_la - 71)) & ((1L << (T__70 - 71)) | (1L << (T__71 - 71)) | (1L << (T__72 - 71)) | (1L << (T__73 - 71)))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + public static class IntegerliteralContext extends ParserRuleContext { public Token intpart; public TerminalNode DEC_INTEGER() { return getToken(prog8Parser.DEC_INTEGER, 0); } @@ -2050,15 +2102,15 @@ public class prog8Parser extends Parser { public final IntegerliteralContext integerliteral() throws RecognitionException { IntegerliteralContext _localctx = new IntegerliteralContext(_ctx, getState()); - enterRule(_localctx, 56, RULE_integerliteral); + enterRule(_localctx, 58, RULE_integerliteral); int _la; try { enterOuterAlt(_localctx, 1); { - setState(330); + setState(347); ((IntegerliteralContext)_localctx).intpart = _input.LT(1); _la = _input.LA(1); - if ( !(((((_la - 103)) & ~0x3f) == 0 && ((1L << (_la - 103)) & ((1L << (DEC_INTEGER - 103)) | (1L << (HEX_INTEGER - 103)) | (1L << (BIN_INTEGER - 103)))) != 0)) ) { + if ( !(((((_la - 110)) & ~0x3f) == 0 && ((1L << (_la - 110)) & ((1L << (DEC_INTEGER - 110)) | (1L << (HEX_INTEGER - 110)) | (1L << (BIN_INTEGER - 110)))) != 0)) ) { ((IntegerliteralContext)_localctx).intpart = (Token)_errHandler.recoverInline(this); } else { @@ -2066,12 +2118,12 @@ public class prog8Parser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(332); + setState(349); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) { case 1: { - setState(331); + setState(348); wordsuffix(); } break; @@ -2098,12 +2150,12 @@ public class prog8Parser extends Parser { public final WordsuffixContext wordsuffix() throws RecognitionException { WordsuffixContext _localctx = new WordsuffixContext(_ctx, getState()); - enterRule(_localctx, 58, RULE_wordsuffix); + enterRule(_localctx, 60, RULE_wordsuffix); try { enterOuterAlt(_localctx, 1); { - setState(334); - match(T__70); + setState(351); + match(T__74); } } catch (RecognitionException re) { @@ -2126,14 +2178,14 @@ public class prog8Parser extends Parser { public final BooleanliteralContext booleanliteral() throws RecognitionException { BooleanliteralContext _localctx = new BooleanliteralContext(_ctx, getState()); - enterRule(_localctx, 60, RULE_booleanliteral); + enterRule(_localctx, 62, RULE_booleanliteral); int _la; try { enterOuterAlt(_localctx, 1); { - setState(336); + setState(353); _la = _input.LA(1); - if ( !(_la==T__71 || _la==T__72) ) { + if ( !(_la==T__75 || _la==T__76) ) { _errHandler.recoverInline(this); } else { @@ -2169,32 +2221,32 @@ public class prog8Parser extends Parser { public final ArrayliteralContext arrayliteral() throws RecognitionException { ArrayliteralContext _localctx = new ArrayliteralContext(_ctx, getState()); - enterRule(_localctx, 62, RULE_arrayliteral); + enterRule(_localctx, 64, RULE_arrayliteral); int _la; try { enterOuterAlt(_localctx, 1); { - setState(338); + setState(355); match(T__23); - setState(339); + setState(356); expression(0); - setState(344); + setState(361); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(340); + setState(357); match(T__12); - setState(341); + setState(358); expression(0); } } - setState(346); + setState(363); _errHandler.sync(this); _la = _input.LA(1); } - setState(347); + setState(364); match(T__24); } } @@ -2219,11 +2271,11 @@ public class prog8Parser extends Parser { public final StringliteralContext stringliteral() throws RecognitionException { StringliteralContext _localctx = new StringliteralContext(_ctx, getState()); - enterRule(_localctx, 64, RULE_stringliteral); + enterRule(_localctx, 66, RULE_stringliteral); try { enterOuterAlt(_localctx, 1); { - setState(349); + setState(366); match(STRING); } } @@ -2248,11 +2300,11 @@ public class prog8Parser extends Parser { public final CharliteralContext charliteral() throws RecognitionException { CharliteralContext _localctx = new CharliteralContext(_ctx, getState()); - enterRule(_localctx, 66, RULE_charliteral); + enterRule(_localctx, 68, RULE_charliteral); try { enterOuterAlt(_localctx, 1); { - setState(351); + setState(368); match(SINGLECHAR); } } @@ -2277,11 +2329,11 @@ public class prog8Parser extends Parser { public final FloatliteralContext floatliteral() throws RecognitionException { FloatliteralContext _localctx = new FloatliteralContext(_ctx, getState()); - enterRule(_localctx, 68, RULE_floatliteral); + enterRule(_localctx, 70, RULE_floatliteral); try { enterOuterAlt(_localctx, 1); { - setState(353); + setState(370); match(FLOAT_NUMBER); } } @@ -2323,9 +2375,9 @@ public class prog8Parser extends Parser { public final LiteralvalueContext literalvalue() throws RecognitionException { LiteralvalueContext _localctx = new LiteralvalueContext(_ctx, getState()); - enterRule(_localctx, 70, RULE_literalvalue); + enterRule(_localctx, 72, RULE_literalvalue); try { - setState(361); + setState(378); _errHandler.sync(this); switch (_input.LA(1)) { case DEC_INTEGER: @@ -2333,43 +2385,43 @@ public class prog8Parser extends Parser { case BIN_INTEGER: enterOuterAlt(_localctx, 1); { - setState(355); + setState(372); integerliteral(); } break; - case T__71: - case T__72: + case T__75: + case T__76: enterOuterAlt(_localctx, 2); { - setState(356); + setState(373); booleanliteral(); } break; case T__23: enterOuterAlt(_localctx, 3); { - setState(357); + setState(374); arrayliteral(); } break; case STRING: enterOuterAlt(_localctx, 4); { - setState(358); + setState(375); stringliteral(); } break; case SINGLECHAR: enterOuterAlt(_localctx, 5); { - setState(359); + setState(376); charliteral(); } break; case FLOAT_NUMBER: enterOuterAlt(_localctx, 6); { - setState(360); + setState(377); floatliteral(); } break; @@ -2398,13 +2450,13 @@ public class prog8Parser extends Parser { public final InlineasmContext inlineasm() throws RecognitionException { InlineasmContext _localctx = new InlineasmContext(_ctx, getState()); - enterRule(_localctx, 72, RULE_inlineasm); + enterRule(_localctx, 74, RULE_inlineasm); try { enterOuterAlt(_localctx, 1); { - setState(363); - match(T__73); - setState(364); + setState(380); + match(T__77); + setState(381); match(INLINEASMBLOCK); } } @@ -2423,19 +2475,16 @@ public class prog8Parser extends Parser { public IdentifierContext identifier() { return getRuleContext(IdentifierContext.class,0); } - public Sub_addressContext sub_address() { - return getRuleContext(Sub_addressContext.class,0); + public Statement_blockContext statement_block() { + return getRuleContext(Statement_blockContext.class,0); } + public TerminalNode EOL() { return getToken(prog8Parser.EOL, 0); } public Sub_paramsContext sub_params() { return getRuleContext(Sub_paramsContext.class,0); } public Sub_return_partContext sub_return_part() { return getRuleContext(Sub_return_partContext.class,0); } - public Statement_blockContext statement_block() { - return getRuleContext(Statement_blockContext.class,0); - } - public TerminalNode EOL() { return getToken(prog8Parser.EOL, 0); } public SubroutineContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -2444,60 +2493,44 @@ public class prog8Parser extends Parser { public final SubroutineContext subroutine() throws RecognitionException { SubroutineContext _localctx = new SubroutineContext(_ctx, getState()); - enterRule(_localctx, 74, RULE_subroutine); + enterRule(_localctx, 76, RULE_subroutine); int _la; try { enterOuterAlt(_localctx, 1); { - setState(366); - match(T__74); - setState(367); + setState(383); + match(T__78); + setState(384); identifier(); - setState(368); + setState(385); match(T__36); - setState(370); + setState(387); _errHandler.sync(this); _la = _input.LA(1); if (_la==NAME) { { - setState(369); + setState(386); sub_params(); } } - setState(372); + setState(389); match(T__37); - setState(374); + setState(391); _errHandler.sync(this); _la = _input.LA(1); - if (_la==T__75) { + if (_la==T__79) { { - setState(373); + setState(390); sub_return_part(); } } - setState(380); - _errHandler.sync(this); - switch (_input.LA(1)) { - case T__13: - { - setState(376); - sub_address(); - } - break; - case T__76: - { - { - setState(377); - statement_block(); - setState(378); - match(EOL); - } - } - break; - default: - throw new NoViableAltException(this); + { + setState(393); + statement_block(); + setState(394); + match(EOL); } } } @@ -2524,13 +2557,13 @@ public class prog8Parser extends Parser { public final Sub_return_partContext sub_return_part() throws RecognitionException { Sub_return_partContext _localctx = new Sub_return_partContext(_ctx, getState()); - enterRule(_localctx, 76, RULE_sub_return_part); + enterRule(_localctx, 78, RULE_sub_return_part); try { enterOuterAlt(_localctx, 1); { - setState(382); - match(T__75); - setState(383); + setState(396); + match(T__79); + setState(397); sub_returns(); } } @@ -2564,21 +2597,21 @@ public class prog8Parser extends Parser { public final Statement_blockContext statement_block() throws RecognitionException { Statement_blockContext _localctx = new Statement_blockContext(_ctx, getState()); - enterRule(_localctx, 78, RULE_statement_block); + enterRule(_localctx, 80, RULE_statement_block); int _la; try { enterOuterAlt(_localctx, 1); { - setState(385); - match(T__76); - setState(386); + setState(399); + match(T__80); + setState(400); match(EOL); - setState(391); + setState(405); _errHandler.sync(this); _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << T__7) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__60) | (1L << T__61) | (1L << T__62))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__73 - 65)) | (1L << (T__74 - 65)) | (1L << (T__78 - 65)) | (1L << (T__80 - 65)) | (1L << (T__81 - 65)) | (1L << (T__82 - 65)) | (1L << (T__83 - 65)) | (1L << (T__84 - 65)) | (1L << (T__85 - 65)) | (1L << (T__86 - 65)) | (1L << (T__87 - 65)) | (1L << (T__88 - 65)) | (1L << (T__89 - 65)) | (1L << (T__90 - 65)) | (1L << (T__91 - 65)) | (1L << (T__92 - 65)) | (1L << (T__94 - 65)) | (1L << (T__95 - 65)) | (1L << (EOL - 65)) | (1L << (NAME - 65)))) != 0)) { + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__3) | (1L << T__4) | (1L << T__5) | (1L << T__6) | (1L << T__7) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__60) | (1L << T__61) | (1L << T__62))) != 0) || ((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)) | (1L << (T__77 - 65)) | (1L << (T__78 - 65)) | (1L << (T__82 - 65)) | (1L << (T__85 - 65)) | (1L << (T__87 - 65)) | (1L << (T__88 - 65)) | (1L << (T__89 - 65)) | (1L << (T__90 - 65)) | (1L << (T__91 - 65)) | (1L << (T__92 - 65)) | (1L << (T__93 - 65)) | (1L << (T__94 - 65)) | (1L << (T__95 - 65)) | (1L << (T__96 - 65)) | (1L << (T__97 - 65)) | (1L << (T__98 - 65)) | (1L << (T__99 - 65)) | (1L << (T__101 - 65)) | (1L << (T__102 - 65)) | (1L << (EOL - 65)) | (1L << (NAME - 65)))) != 0)) { { - setState(389); + setState(403); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -2609,33 +2642,34 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(387); + setState(401); statement(); } break; case EOL: { - setState(388); + setState(402); match(EOL); } break; @@ -2643,45 +2677,12 @@ public class prog8Parser extends Parser { throw new NoViableAltException(this); } } - setState(393); + setState(407); _errHandler.sync(this); _la = _input.LA(1); } - setState(394); - match(T__77); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public static class Sub_addressContext extends ParserRuleContext { - public IntegerliteralContext integerliteral() { - return getRuleContext(IntegerliteralContext.class,0); - } - public Sub_addressContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_sub_address; } - } - - public final Sub_addressContext sub_address() throws RecognitionException { - Sub_addressContext _localctx = new Sub_addressContext(_ctx, getState()); - enterRule(_localctx, 80, RULE_sub_address); - try { - enterOuterAlt(_localctx, 1); - { - setState(396); - match(T__13); - setState(397); - integerliteral(); + setState(408); + match(T__81); } } catch (RecognitionException re) { @@ -2715,21 +2716,21 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(399); + setState(410); sub_param(); - setState(404); + setState(415); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(400); + setState(411); match(T__12); - setState(401); + setState(412); sub_param(); } } - setState(406); + setState(417); _errHandler.sync(this); _la = _input.LA(1); } @@ -2765,11 +2766,11 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(407); + setState(418); identifier(); - setState(408); + setState(419); match(T__1); - setState(409); + setState(420); datatype(); } } @@ -2804,21 +2805,21 @@ public class prog8Parser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(411); + setState(422); datatype(); - setState(416); + setState(427); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(412); + setState(423); match(T__12); - setState(413); + setState(424); datatype(); } } - setState(418); + setState(429); _errHandler.sync(this); _la = _input.LA(1); } @@ -2835,6 +2836,445 @@ public class prog8Parser extends Parser { return _localctx; } + public static class AsmsubroutineContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public Asmsub_addressContext asmsub_address() { + return getRuleContext(Asmsub_addressContext.class,0); + } + public Statement_blockContext statement_block() { + return getRuleContext(Statement_blockContext.class,0); + } + public Asmsub_paramsContext asmsub_params() { + return getRuleContext(Asmsub_paramsContext.class,0); + } + public ClobberContext clobber() { + return getRuleContext(ClobberContext.class,0); + } + public Asmsub_returnsContext asmsub_returns() { + return getRuleContext(Asmsub_returnsContext.class,0); + } + public AsmsubroutineContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsubroutine; } + } + + public final AsmsubroutineContext asmsubroutine() throws RecognitionException { + AsmsubroutineContext _localctx = new AsmsubroutineContext(_ctx, getState()); + enterRule(_localctx, 88, RULE_asmsubroutine); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(430); + match(T__82); + setState(431); + identifier(); + setState(432); + match(T__36); + setState(434); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==NAME) { + { + setState(433); + asmsub_params(); + } + } + + setState(436); + match(T__37); + setState(437); + match(T__79); + setState(438); + match(T__83); + setState(439); + match(T__36); + setState(441); + _errHandler.sync(this); + _la = _input.LA(1); + if (((((_la - 65)) & ~0x3f) == 0 && ((1L << (_la - 65)) & ((1L << (T__64 - 65)) | (1L << (T__65 - 65)) | (1L << (T__66 - 65)) | (1L << (T__67 - 65)) | (1L << (T__68 - 65)) | (1L << (T__69 - 65)))) != 0)) { + { + setState(440); + clobber(); + } + } + + setState(443); + match(T__37); + setState(444); + match(T__79); + setState(445); + match(T__36); + setState(447); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22))) != 0)) { + { + setState(446); + asmsub_returns(); + } + } + + setState(449); + match(T__37); + setState(452); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__13: + { + setState(450); + asmsub_address(); + } + break; + case T__80: + { + setState(451); + statement_block(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class Asmsub_addressContext extends ParserRuleContext { + public IntegerliteralContext address; + public IntegerliteralContext integerliteral() { + return getRuleContext(IntegerliteralContext.class,0); + } + public Asmsub_addressContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsub_address; } + } + + public final Asmsub_addressContext asmsub_address() throws RecognitionException { + Asmsub_addressContext _localctx = new Asmsub_addressContext(_ctx, getState()); + enterRule(_localctx, 90, RULE_asmsub_address); + try { + enterOuterAlt(_localctx, 1); + { + setState(454); + match(T__13); + setState(455); + ((Asmsub_addressContext)_localctx).address = integerliteral(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class Asmsub_paramsContext extends ParserRuleContext { + public List asmsub_param() { + return getRuleContexts(Asmsub_paramContext.class); + } + public Asmsub_paramContext asmsub_param(int i) { + return getRuleContext(Asmsub_paramContext.class,i); + } + public Asmsub_paramsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsub_params; } + } + + public final Asmsub_paramsContext asmsub_params() throws RecognitionException { + Asmsub_paramsContext _localctx = new Asmsub_paramsContext(_ctx, getState()); + enterRule(_localctx, 92, RULE_asmsub_params); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(457); + asmsub_param(); + setState(462); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__12) { + { + { + setState(458); + match(T__12); + setState(459); + asmsub_param(); + } + } + setState(464); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class Asmsub_paramContext extends ParserRuleContext { + public IdentifierContext identifier() { + return getRuleContext(IdentifierContext.class,0); + } + public DatatypeContext datatype() { + return getRuleContext(DatatypeContext.class,0); + } + public RegisterContext register() { + return getRuleContext(RegisterContext.class,0); + } + public StatusregisterContext statusregister() { + return getRuleContext(StatusregisterContext.class,0); + } + public Asmsub_paramContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsub_param; } + } + + public final Asmsub_paramContext asmsub_param() throws RecognitionException { + Asmsub_paramContext _localctx = new Asmsub_paramContext(_ctx, getState()); + enterRule(_localctx, 94, RULE_asmsub_param); + try { + enterOuterAlt(_localctx, 1); + { + setState(465); + identifier(); + setState(466); + match(T__1); + setState(467); + datatype(); + setState(468); + match(T__84); + setState(471); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__64: + case T__65: + case T__66: + case T__67: + case T__68: + case T__69: + { + setState(469); + register(); + } + break; + case T__70: + case T__71: + case T__72: + case T__73: + { + setState(470); + statusregister(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ClobberContext extends ParserRuleContext { + public List register() { + return getRuleContexts(RegisterContext.class); + } + public RegisterContext register(int i) { + return getRuleContext(RegisterContext.class,i); + } + public ClobberContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_clobber; } + } + + public final ClobberContext clobber() throws RecognitionException { + ClobberContext _localctx = new ClobberContext(_ctx, getState()); + enterRule(_localctx, 96, RULE_clobber); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(473); + register(); + setState(478); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__12) { + { + { + setState(474); + match(T__12); + setState(475); + register(); + } + } + setState(480); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class Asmsub_returnsContext extends ParserRuleContext { + public List asmsub_return() { + return getRuleContexts(Asmsub_returnContext.class); + } + public Asmsub_returnContext asmsub_return(int i) { + return getRuleContext(Asmsub_returnContext.class,i); + } + public Asmsub_returnsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsub_returns; } + } + + public final Asmsub_returnsContext asmsub_returns() throws RecognitionException { + Asmsub_returnsContext _localctx = new Asmsub_returnsContext(_ctx, getState()); + enterRule(_localctx, 98, RULE_asmsub_returns); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(481); + asmsub_return(); + setState(486); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==T__12) { + { + { + setState(482); + match(T__12); + setState(483); + asmsub_return(); + } + } + setState(488); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class Asmsub_returnContext extends ParserRuleContext { + public DatatypeContext datatype() { + return getRuleContext(DatatypeContext.class,0); + } + public RegisterContext register() { + return getRuleContext(RegisterContext.class,0); + } + public StatusregisterContext statusregister() { + return getRuleContext(StatusregisterContext.class,0); + } + public Asmsub_returnContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_asmsub_return; } + } + + public final Asmsub_returnContext asmsub_return() throws RecognitionException { + Asmsub_returnContext _localctx = new Asmsub_returnContext(_ctx, getState()); + enterRule(_localctx, 100, RULE_asmsub_return); + try { + enterOuterAlt(_localctx, 1); + { + setState(489); + datatype(); + setState(490); + match(T__84); + setState(493); + _errHandler.sync(this); + switch (_input.LA(1)) { + case T__64: + case T__65: + case T__66: + case T__67: + case T__68: + case T__69: + { + setState(491); + register(); + } + break; + case T__70: + case T__71: + case T__72: + case T__73: + { + setState(492); + statusregister(); + } + break; + default: + throw new NoViableAltException(this); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + public static class If_stmtContext extends ParserRuleContext { public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); @@ -2860,26 +3300,26 @@ public class prog8Parser extends Parser { public final If_stmtContext if_stmt() throws RecognitionException { If_stmtContext _localctx = new If_stmtContext(_ctx, getState()); - enterRule(_localctx, 88, RULE_if_stmt); + enterRule(_localctx, 102, RULE_if_stmt); int _la; try { enterOuterAlt(_localctx, 1); { - setState(419); - match(T__78); - setState(420); + setState(495); + match(T__85); + setState(496); expression(0); - setState(422); + setState(498); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(421); + setState(497); match(EOL); } } - setState(426); + setState(502); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -2910,60 +3350,61 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(424); + setState(500); statement(); } break; - case T__76: + case T__80: { - setState(425); + setState(501); statement_block(); } break; default: throw new NoViableAltException(this); } - setState(429); + setState(505); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,45,_ctx) ) { case 1: { - setState(428); + setState(504); match(EOL); } break; } - setState(432); + setState(508); _errHandler.sync(this); _la = _input.LA(1); - if (_la==T__79) { + if (_la==T__86) { { - setState(431); + setState(507); else_part(); } } - setState(434); + setState(510); match(EOL); } } @@ -2994,24 +3435,24 @@ public class prog8Parser extends Parser { public final Else_partContext else_part() throws RecognitionException { Else_partContext _localctx = new Else_partContext(_ctx, getState()); - enterRule(_localctx, 90, RULE_else_part); + enterRule(_localctx, 104, RULE_else_part); int _la; try { enterOuterAlt(_localctx, 1); { - setState(436); - match(T__79); - setState(438); + setState(512); + match(T__86); + setState(514); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(437); + setState(513); match(EOL); } } - setState(442); + setState(518); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -3042,33 +3483,34 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(440); + setState(516); statement(); } break; - case T__76: + case T__80: { - setState(441); + setState(517); statement_block(); } break; @@ -3113,24 +3555,24 @@ public class prog8Parser extends Parser { public final Branch_stmtContext branch_stmt() throws RecognitionException { Branch_stmtContext _localctx = new Branch_stmtContext(_ctx, getState()); - enterRule(_localctx, 92, RULE_branch_stmt); + enterRule(_localctx, 106, RULE_branch_stmt); int _la; try { enterOuterAlt(_localctx, 1); { - setState(444); + setState(520); branchcondition(); - setState(446); + setState(522); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(445); + setState(521); match(EOL); } } - setState(450); + setState(526); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -3161,60 +3603,61 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(448); + setState(524); statement(); } break; - case T__76: + case T__80: { - setState(449); + setState(525); statement_block(); } break; default: throw new NoViableAltException(this); } - setState(453); + setState(529); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,43,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) { case 1: { - setState(452); + setState(528); match(EOL); } break; } - setState(456); + setState(532); _errHandler.sync(this); _la = _input.LA(1); - if (_la==T__79) { + if (_la==T__86) { { - setState(455); + setState(531); else_part(); } } - setState(458); + setState(534); match(EOL); } } @@ -3238,14 +3681,14 @@ public class prog8Parser extends Parser { public final BranchconditionContext branchcondition() throws RecognitionException { BranchconditionContext _localctx = new BranchconditionContext(_ctx, getState()); - enterRule(_localctx, 94, RULE_branchcondition); + enterRule(_localctx, 108, RULE_branchcondition); int _la; try { enterOuterAlt(_localctx, 1); { - setState(460); + setState(536); _la = _input.LA(1); - if ( !(((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (T__80 - 81)) | (1L << (T__81 - 81)) | (1L << (T__82 - 81)) | (1L << (T__83 - 81)) | (1L << (T__84 - 81)) | (1L << (T__85 - 81)) | (1L << (T__86 - 81)) | (1L << (T__87 - 81)) | (1L << (T__88 - 81)) | (1L << (T__89 - 81)) | (1L << (T__90 - 81)) | (1L << (T__91 - 81)))) != 0)) ) { + if ( !(((((_la - 88)) & ~0x3f) == 0 && ((1L << (_la - 88)) & ((1L << (T__87 - 88)) | (1L << (T__88 - 88)) | (1L << (T__89 - 88)) | (1L << (T__90 - 88)) | (1L << (T__91 - 88)) | (1L << (T__92 - 88)) | (1L << (T__93 - 88)) | (1L << (T__94 - 88)) | (1L << (T__95 - 88)) | (1L << (T__96 - 88)) | (1L << (T__97 - 88)) | (1L << (T__98 - 88)))) != 0)) ) { _errHandler.recoverInline(this); } else { @@ -3288,14 +3731,14 @@ public class prog8Parser extends Parser { public final ForloopContext forloop() throws RecognitionException { ForloopContext _localctx = new ForloopContext(_ctx, getState()); - enterRule(_localctx, 96, RULE_forloop); + enterRule(_localctx, 110, RULE_forloop); int _la; try { enterOuterAlt(_localctx, 1); { - setState(462); - match(T__92); - setState(465); + setState(538); + match(T__99); + setState(541); _errHandler.sync(this); switch (_input.LA(1)) { case T__64: @@ -3305,34 +3748,34 @@ public class prog8Parser extends Parser { case T__68: case T__69: { - setState(463); + setState(539); register(); } break; case NAME: { - setState(464); + setState(540); identifier(); } break; default: throw new NoViableAltException(this); } - setState(467); - match(T__93); - setState(468); + setState(543); + match(T__100); + setState(544); expression(0); - setState(470); + setState(546); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(469); + setState(545); match(EOL); } } - setState(472); + setState(548); statement_block(); } } @@ -3366,26 +3809,26 @@ public class prog8Parser extends Parser { public final WhileloopContext whileloop() throws RecognitionException { WhileloopContext _localctx = new WhileloopContext(_ctx, getState()); - enterRule(_localctx, 98, RULE_whileloop); + enterRule(_localctx, 112, RULE_whileloop); int _la; try { enterOuterAlt(_localctx, 1); { - setState(474); - match(T__94); - setState(475); + setState(550); + match(T__101); + setState(551); expression(0); - setState(477); + setState(553); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(476); + setState(552); match(EOL); } } - setState(481); + setState(557); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -3416,33 +3859,34 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(479); + setState(555); statement(); } break; - case T__76: + case T__80: { - setState(480); + setState(556); statement_block(); } break; @@ -3481,14 +3925,14 @@ public class prog8Parser extends Parser { public final RepeatloopContext repeatloop() throws RecognitionException { RepeatloopContext _localctx = new RepeatloopContext(_ctx, getState()); - enterRule(_localctx, 100, RULE_repeatloop); + enterRule(_localctx, 114, RULE_repeatloop); int _la; try { enterOuterAlt(_localctx, 1); { - setState(483); - match(T__95); - setState(486); + setState(559); + match(T__102); + setState(562); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -3519,52 +3963,53 @@ public class prog8Parser extends Parser { case T__67: case T__68: case T__69: - case T__73: - case T__74: + case T__77: case T__78: - case T__80: - case T__81: case T__82: - case T__83: - case T__84: case T__85: - case T__86: case T__87: case T__88: case T__89: case T__90: case T__91: case T__92: + case T__93: case T__94: case T__95: + case T__96: + case T__97: + case T__98: + case T__99: + case T__101: + case T__102: case NAME: { - setState(484); + setState(560); statement(); } break; - case T__76: + case T__80: { - setState(485); + setState(561); statement_block(); } break; default: throw new NoViableAltException(this); } - setState(489); + setState(565); _errHandler.sync(this); _la = _input.LA(1); if (_la==EOL) { { - setState(488); + setState(564); match(EOL); } } - setState(491); - match(T__96); - setState(492); + setState(567); + match(T__103); + setState(568); expression(0); } } @@ -3619,191 +4064,220 @@ public class prog8Parser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3o\u01f1\4\2\t\2\4"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3v\u023d\4\2\t\2\4"+ "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ "\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+ - "\64\3\2\3\2\7\2k\n\2\f\2\16\2n\13\2\3\2\3\2\3\3\3\3\5\3t\n\3\3\4\3\4\3"+ - "\4\5\4y\n\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+ - "\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5\u0093\n\5\3\6\3\6\3\6\3\7\3"+ - "\7\3\7\3\7\5\7\u009c\n\7\3\b\3\b\5\b\u00a0\n\b\3\b\3\b\3\b\7\b\u00a5\n"+ - "\b\f\b\16\b\u00a8\13\b\5\b\u00aa\n\b\3\t\3\t\3\t\5\t\u00af\n\t\3\n\3\n"+ - "\5\n\u00b3\n\n\3\n\3\n\3\13\3\13\5\13\u00b9\n\13\3\13\3\13\3\13\3\13\3"+ - "\f\3\f\3\f\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\17\3\17\5\17\u00cb\n\17\3"+ - "\17\3\17\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\22\3\22\3\22\5\22\u00da"+ + "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\3\2\3\2\7\2"+ + "y\n\2\f\2\16\2|\13\2\3\2\3\2\3\3\3\3\5\3\u0082\n\3\3\4\3\4\3\4\5\4\u0087"+ + "\n\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+ + "\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\5\5\u00a2\n\5\3\6\3\6\3\6\3\7\3\7\3"+ + "\7\3\7\5\7\u00ab\n\7\3\b\3\b\5\b\u00af\n\b\3\b\3\b\3\b\7\b\u00b4\n\b\f"+ + "\b\16\b\u00b7\13\b\5\b\u00b9\n\b\3\t\3\t\3\t\5\t\u00be\n\t\3\n\3\n\5\n"+ + "\u00c2\n\n\3\n\3\n\3\13\3\13\5\13\u00c8\n\13\3\13\3\13\3\13\3\13\3\f\3"+ + "\f\3\f\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\17\3\17\5\17\u00da\n\17\3\17"+ + "\3\17\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\22\3\22\3\22\5\22\u00e9"+ "\n\22\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+ - "\3\24\3\24\3\24\3\24\5\24\u00ed\n\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+ + "\3\24\3\24\3\24\3\24\5\24\u00fc\n\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+ "\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+ "\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24"+ - "\3\24\3\24\3\24\3\24\3\24\5\24\u0117\n\24\7\24\u0119\n\24\f\24\16\24\u011c"+ - "\13\24\3\25\3\25\5\25\u0120\n\25\3\25\3\25\5\25\u0124\n\25\3\25\3\25\3"+ - "\26\3\26\5\26\u012a\n\26\3\26\3\26\5\26\u012e\n\26\3\26\3\26\3\27\3\27"+ - "\3\27\7\27\u0135\n\27\f\27\16\27\u0138\13\27\3\30\3\30\5\30\u013c\n\30"+ - "\3\31\3\31\3\32\3\32\3\33\3\33\3\34\3\34\3\34\6\34\u0147\n\34\r\34\16"+ - "\34\u0148\3\35\3\35\3\36\3\36\5\36\u014f\n\36\3\37\3\37\3 \3 \3!\3!\3"+ - "!\3!\7!\u0159\n!\f!\16!\u015c\13!\3!\3!\3\"\3\"\3#\3#\3$\3$\3%\3%\3%\3"+ - "%\3%\3%\5%\u016c\n%\3&\3&\3&\3\'\3\'\3\'\3\'\5\'\u0175\n\'\3\'\3\'\5\'"+ - "\u0179\n\'\3\'\3\'\3\'\3\'\5\'\u017f\n\'\3(\3(\3(\3)\3)\3)\3)\7)\u0188"+ - "\n)\f)\16)\u018b\13)\3)\3)\3*\3*\3*\3+\3+\3+\7+\u0195\n+\f+\16+\u0198"+ - "\13+\3,\3,\3,\3,\3-\3-\3-\7-\u01a1\n-\f-\16-\u01a4\13-\3.\3.\3.\5.\u01a9"+ - "\n.\3.\3.\5.\u01ad\n.\3.\5.\u01b0\n.\3.\5.\u01b3\n.\3.\3.\3/\3/\5/\u01b9"+ - "\n/\3/\3/\5/\u01bd\n/\3\60\3\60\5\60\u01c1\n\60\3\60\3\60\5\60\u01c5\n"+ - "\60\3\60\5\60\u01c8\n\60\3\60\5\60\u01cb\n\60\3\60\3\60\3\61\3\61\3\62"+ - "\3\62\3\62\5\62\u01d4\n\62\3\62\3\62\3\62\5\62\u01d9\n\62\3\62\3\62\3"+ - "\63\3\63\3\63\5\63\u01e0\n\63\3\63\3\63\5\63\u01e4\n\63\3\64\3\64\3\64"+ - "\5\64\u01e9\n\64\3\64\5\64\u01ec\n\64\3\64\3\64\3\64\3\64\2\3&\65\2\4"+ - "\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNP"+ - "RTVXZ\\^`bdf\2\17\3\2\6\16\3\2\23\31\3\2\34$\3\2%&\4\2\3\3)*\3\2,/\3\2"+ - ")*\3\2\60\63\3\2\64\65\3\2CH\3\2ik\3\2JK\3\2S^\2\u021b\2l\3\2\2\2\4s\3"+ - "\2\2\2\6u\3\2\2\2\b\u0092\3\2\2\2\n\u0094\3\2\2\2\f\u0097\3\2\2\2\16\u009d"+ - "\3\2\2\2\20\u00ae\3\2\2\2\22\u00b0\3\2\2\2\24\u00b6\3\2\2\2\26\u00be\3"+ - "\2\2\2\30\u00c1\3\2\2\2\32\u00c4\3\2\2\2\34\u00c6\3\2\2\2\36\u00ce\3\2"+ - "\2\2 \u00d2\3\2\2\2\"\u00d9\3\2\2\2$\u00db\3\2\2\2&\u00ec\3\2\2\2(\u011f"+ - "\3\2\2\2*\u0129\3\2\2\2,\u0131\3\2\2\2.\u0139\3\2\2\2\60\u013d\3\2\2\2"+ - "\62\u013f\3\2\2\2\64\u0141\3\2\2\2\66\u0143\3\2\2\28\u014a\3\2\2\2:\u014c"+ - "\3\2\2\2<\u0150\3\2\2\2>\u0152\3\2\2\2@\u0154\3\2\2\2B\u015f\3\2\2\2D"+ - "\u0161\3\2\2\2F\u0163\3\2\2\2H\u016b\3\2\2\2J\u016d\3\2\2\2L\u0170\3\2"+ - "\2\2N\u0180\3\2\2\2P\u0183\3\2\2\2R\u018e\3\2\2\2T\u0191\3\2\2\2V\u0199"+ - "\3\2\2\2X\u019d\3\2\2\2Z\u01a5\3\2\2\2\\\u01b6\3\2\2\2^\u01be\3\2\2\2"+ - "`\u01ce\3\2\2\2b\u01d0\3\2\2\2d\u01dc\3\2\2\2f\u01e5\3\2\2\2hk\5\4\3\2"+ - "ik\7g\2\2jh\3\2\2\2ji\3\2\2\2kn\3\2\2\2lj\3\2\2\2lm\3\2\2\2mo\3\2\2\2"+ - "nl\3\2\2\2op\7\2\2\3p\3\3\2\2\2qt\5\16\b\2rt\5\6\4\2sq\3\2\2\2sr\3\2\2"+ - "\2t\5\3\2\2\2uv\7\3\2\2vx\5\64\33\2wy\5:\36\2xw\3\2\2\2xy\3\2\2\2yz\3"+ - "\2\2\2z{\5P)\2{|\7g\2\2|\7\3\2\2\2}\u0093\5\16\b\2~\u0093\5\24\13\2\177"+ - "\u0093\5\22\n\2\u0080\u0093\5\26\f\2\u0081\u0093\5\30\r\2\u0082\u0093"+ - "\5\36\20\2\u0083\u0093\5 \21\2\u0084\u0093\5\f\7\2\u0085\u0093\5$\23\2"+ - "\u0086\u0093\5*\26\2\u0087\u0093\5Z.\2\u0088\u0093\5^\60\2\u0089\u0093"+ - "\5L\'\2\u008a\u0093\5J&\2\u008b\u0093\5.\30\2\u008c\u0093\5b\62\2\u008d"+ - "\u0093\5d\63\2\u008e\u0093\5f\64\2\u008f\u0093\5\60\31\2\u0090\u0093\5"+ - "\62\32\2\u0091\u0093\5\n\6\2\u0092}\3\2\2\2\u0092~\3\2\2\2\u0092\177\3"+ - "\2\2\2\u0092\u0080\3\2\2\2\u0092\u0081\3\2\2\2\u0092\u0082\3\2\2\2\u0092"+ - "\u0083\3\2\2\2\u0092\u0084\3\2\2\2\u0092\u0085\3\2\2\2\u0092\u0086\3\2"+ - "\2\2\u0092\u0087\3\2\2\2\u0092\u0088\3\2\2\2\u0092\u0089\3\2\2\2\u0092"+ - "\u008a\3\2\2\2\u0092\u008b\3\2\2\2\u0092\u008c\3\2\2\2\u0092\u008d\3\2"+ - "\2\2\u0092\u008e\3\2\2\2\u0092\u008f\3\2\2\2\u0092\u0090\3\2\2\2\u0092"+ - "\u0091\3\2\2\2\u0093\t\3\2\2\2\u0094\u0095\5\64\33\2\u0095\u0096\7\4\2"+ - "\2\u0096\13\3\2\2\2\u0097\u009b\7\5\2\2\u0098\u009c\5:\36\2\u0099\u009c"+ - "\5\64\33\2\u009a\u009c\5\66\34\2\u009b\u0098\3\2\2\2\u009b\u0099\3\2\2"+ - "\2\u009b\u009a\3\2\2\2\u009c\r\3\2\2\2\u009d\u00a9\t\2\2\2\u009e\u00a0"+ - "\5\20\t\2\u009f\u009e\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u00aa\3\2\2\2"+ - "\u00a1\u00a6\5\20\t\2\u00a2\u00a3\7\17\2\2\u00a3\u00a5\5\20\t\2\u00a4"+ - "\u00a2\3\2\2\2\u00a5\u00a8\3\2\2\2\u00a6\u00a4\3\2\2\2\u00a6\u00a7\3\2"+ - "\2\2\u00a7\u00aa\3\2\2\2\u00a8\u00a6\3\2\2\2\u00a9\u009f\3\2\2\2\u00a9"+ - "\u00a1\3\2\2\2\u00aa\17\3\2\2\2\u00ab\u00af\5B\"\2\u00ac\u00af\5\64\33"+ - "\2\u00ad\u00af\5:\36\2\u00ae\u00ab\3\2\2\2\u00ae\u00ac\3\2\2\2\u00ae\u00ad"+ - "\3\2\2\2\u00af\21\3\2\2\2\u00b0\u00b2\5\32\16\2\u00b1\u00b3\5\34\17\2"+ - "\u00b2\u00b1\3\2\2\2\u00b2\u00b3\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b4\u00b5"+ - "\5\64\33\2\u00b5\23\3\2\2\2\u00b6\u00b8\5\32\16\2\u00b7\u00b9\5\34\17"+ - "\2\u00b8\u00b7\3\2\2\2\u00b8\u00b9\3\2\2\2\u00b9\u00ba\3\2\2\2\u00ba\u00bb"+ - "\5\64\33\2\u00bb\u00bc\7\20\2\2\u00bc\u00bd\5&\24\2\u00bd\25\3\2\2\2\u00be"+ - "\u00bf\7\21\2\2\u00bf\u00c0\5\24\13\2\u00c0\27\3\2\2\2\u00c1\u00c2\7\22"+ - "\2\2\u00c2\u00c3\5\24\13\2\u00c3\31\3\2\2\2\u00c4\u00c5\t\3\2\2\u00c5"+ - "\33\3\2\2\2\u00c6\u00c7\7\32\2\2\u00c7\u00ca\5&\24\2\u00c8\u00c9\7\17"+ - "\2\2\u00c9\u00cb\5&\24\2\u00ca\u00c8\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb"+ - "\u00cc\3\2\2\2\u00cc\u00cd\7\33\2\2\u00cd\35\3\2\2\2\u00ce\u00cf\5\"\22"+ - "\2\u00cf\u00d0\7\20\2\2\u00d0\u00d1\5&\24\2\u00d1\37\3\2\2\2\u00d2\u00d3"+ - "\5\"\22\2\u00d3\u00d4\t\4\2\2\u00d4\u00d5\5&\24\2\u00d5!\3\2\2\2\u00d6"+ - "\u00da\58\35\2\u00d7\u00da\5\64\33\2\u00d8\u00da\5\66\34\2\u00d9\u00d6"+ - "\3\2\2\2\u00d9\u00d7\3\2\2\2\u00d9\u00d8\3\2\2\2\u00da#\3\2\2\2\u00db"+ - "\u00dc\5\"\22\2\u00dc\u00dd\t\5\2\2\u00dd%\3\2\2\2\u00de\u00df\b\24\1"+ - "\2\u00df\u00e0\7\'\2\2\u00e0\u00e1\5&\24\2\u00e1\u00e2\7(\2\2\u00e2\u00ed"+ - "\3\2\2\2\u00e3\u00ed\5(\25\2\u00e4\u00e5\t\6\2\2\u00e5\u00ed\5&\24\24"+ - "\u00e6\u00e7\7>\2\2\u00e7\u00ed\5&\24\7\u00e8\u00ed\5H%\2\u00e9\u00ed"+ - "\58\35\2\u00ea\u00ed\5\64\33\2\u00eb\u00ed\5\66\34\2\u00ec\u00de\3\2\2"+ - "\2\u00ec\u00e3\3\2\2\2\u00ec\u00e4\3\2\2\2\u00ec\u00e6\3\2\2\2\u00ec\u00e8"+ - "\3\2\2\2\u00ec\u00e9\3\2\2\2\u00ec\u00ea\3\2\2\2\u00ec\u00eb\3\2\2\2\u00ed"+ - "\u011a\3\2\2\2\u00ee\u00ef\f\23\2\2\u00ef\u00f0\7+\2\2\u00f0\u0119\5&"+ - "\24\24\u00f1\u00f2\f\22\2\2\u00f2\u00f3\t\7\2\2\u00f3\u0119\5&\24\23\u00f4"+ - "\u00f5\f\21\2\2\u00f5\u00f6\t\b\2\2\u00f6\u0119\5&\24\22\u00f7\u00f8\f"+ - "\20\2\2\u00f8\u00f9\t\t\2\2\u00f9\u0119\5&\24\21\u00fa\u00fb\f\17\2\2"+ - "\u00fb\u00fc\t\n\2\2\u00fc\u0119\5&\24\20\u00fd\u00fe\f\16\2\2\u00fe\u00ff"+ - "\7\66\2\2\u00ff\u0119\5&\24\17\u0100\u0101\f\r\2\2\u0101\u0102\7\67\2"+ - "\2\u0102\u0119\5&\24\16\u0103\u0104\f\f\2\2\u0104\u0105\78\2\2\u0105\u0119"+ - "\5&\24\r\u0106\u0107\f\n\2\2\u0107\u0108\7;\2\2\u0108\u0119\5&\24\13\u0109"+ - "\u010a\f\t\2\2\u010a\u010b\7<\2\2\u010b\u0119\5&\24\n\u010c\u010d\f\b"+ - "\2\2\u010d\u010e\7=\2\2\u010e\u0119\5&\24\t\u010f\u0110\f\26\2\2\u0110"+ - "\u0119\5\34\17\2\u0111\u0112\f\13\2\2\u0112\u0113\79\2\2\u0113\u0116\5"+ - "&\24\2\u0114\u0115\7:\2\2\u0115\u0117\5&\24\2\u0116\u0114\3\2\2\2\u0116"+ - "\u0117\3\2\2\2\u0117\u0119\3\2\2\2\u0118\u00ee\3\2\2\2\u0118\u00f1\3\2"+ - "\2\2\u0118\u00f4\3\2\2\2\u0118\u00f7\3\2\2\2\u0118\u00fa\3\2\2\2\u0118"+ - "\u00fd\3\2\2\2\u0118\u0100\3\2\2\2\u0118\u0103\3\2\2\2\u0118\u0106\3\2"+ - "\2\2\u0118\u0109\3\2\2\2\u0118\u010c\3\2\2\2\u0118\u010f\3\2\2\2\u0118"+ - "\u0111\3\2\2\2\u0119\u011c\3\2\2\2\u011a\u0118\3\2\2\2\u011a\u011b\3\2"+ - "\2\2\u011b\'\3\2\2\2\u011c\u011a\3\2\2\2\u011d\u0120\5\64\33\2\u011e\u0120"+ - "\5\66\34\2\u011f\u011d\3\2\2\2\u011f\u011e\3\2\2\2\u0120\u0121\3\2\2\2"+ - "\u0121\u0123\7\'\2\2\u0122\u0124\5,\27\2\u0123\u0122\3\2\2\2\u0123\u0124"+ - "\3\2\2\2\u0124\u0125\3\2\2\2\u0125\u0126\7(\2\2\u0126)\3\2\2\2\u0127\u012a"+ - "\5\64\33\2\u0128\u012a\5\66\34\2\u0129\u0127\3\2\2\2\u0129\u0128\3\2\2"+ - "\2\u012a\u012b\3\2\2\2\u012b\u012d\7\'\2\2\u012c\u012e\5,\27\2\u012d\u012c"+ - "\3\2\2\2\u012d\u012e\3\2\2\2\u012e\u012f\3\2\2\2\u012f\u0130\7(\2\2\u0130"+ - "+\3\2\2\2\u0131\u0136\5&\24\2\u0132\u0133\7\17\2\2\u0133\u0135\5&\24\2"+ - "\u0134\u0132\3\2\2\2\u0135\u0138\3\2\2\2\u0136\u0134\3\2\2\2\u0136\u0137"+ - "\3\2\2\2\u0137-\3\2\2\2\u0138\u0136\3\2\2\2\u0139\u013b\7?\2\2\u013a\u013c"+ - "\5,\27\2\u013b\u013a\3\2\2\2\u013b\u013c\3\2\2\2\u013c/\3\2\2\2\u013d"+ - "\u013e\7@\2\2\u013e\61\3\2\2\2\u013f\u0140\7A\2\2\u0140\63\3\2\2\2\u0141"+ - "\u0142\7h\2\2\u0142\65\3\2\2\2\u0143\u0146\7h\2\2\u0144\u0145\7B\2\2\u0145"+ - "\u0147\7h\2\2\u0146\u0144\3\2\2\2\u0147\u0148\3\2\2\2\u0148\u0146\3\2"+ - "\2\2\u0148\u0149\3\2\2\2\u0149\67\3\2\2\2\u014a\u014b\t\13\2\2\u014b9"+ - "\3\2\2\2\u014c\u014e\t\f\2\2\u014d\u014f\5<\37\2\u014e\u014d\3\2\2\2\u014e"+ - "\u014f\3\2\2\2\u014f;\3\2\2\2\u0150\u0151\7I\2\2\u0151=\3\2\2\2\u0152"+ - "\u0153\t\r\2\2\u0153?\3\2\2\2\u0154\u0155\7\32\2\2\u0155\u015a\5&\24\2"+ - "\u0156\u0157\7\17\2\2\u0157\u0159\5&\24\2\u0158\u0156\3\2\2\2\u0159\u015c"+ - "\3\2\2\2\u015a\u0158\3\2\2\2\u015a\u015b\3\2\2\2\u015b\u015d\3\2\2\2\u015c"+ - "\u015a\3\2\2\2\u015d\u015e\7\33\2\2\u015eA\3\2\2\2\u015f\u0160\7m\2\2"+ - "\u0160C\3\2\2\2\u0161\u0162\7o\2\2\u0162E\3\2\2\2\u0163\u0164\7l\2\2\u0164"+ - "G\3\2\2\2\u0165\u016c\5:\36\2\u0166\u016c\5> \2\u0167\u016c\5@!\2\u0168"+ - "\u016c\5B\"\2\u0169\u016c\5D#\2\u016a\u016c\5F$\2\u016b\u0165\3\2\2\2"+ - "\u016b\u0166\3\2\2\2\u016b\u0167\3\2\2\2\u016b\u0168\3\2\2\2\u016b\u0169"+ - "\3\2\2\2\u016b\u016a\3\2\2\2\u016cI\3\2\2\2\u016d\u016e\7L\2\2\u016e\u016f"+ - "\7n\2\2\u016fK\3\2\2\2\u0170\u0171\7M\2\2\u0171\u0172\5\64\33\2\u0172"+ - "\u0174\7\'\2\2\u0173\u0175\5T+\2\u0174\u0173\3\2\2\2\u0174\u0175\3\2\2"+ - "\2\u0175\u0176\3\2\2\2\u0176\u0178\7(\2\2\u0177\u0179\5N(\2\u0178\u0177"+ - "\3\2\2\2\u0178\u0179\3\2\2\2\u0179\u017e\3\2\2\2\u017a\u017f\5R*\2\u017b"+ - "\u017c\5P)\2\u017c\u017d\7g\2\2\u017d\u017f\3\2\2\2\u017e\u017a\3\2\2"+ - "\2\u017e\u017b\3\2\2\2\u017fM\3\2\2\2\u0180\u0181\7N\2\2\u0181\u0182\5"+ - "X-\2\u0182O\3\2\2\2\u0183\u0184\7O\2\2\u0184\u0189\7g\2\2\u0185\u0188"+ - "\5\b\5\2\u0186\u0188\7g\2\2\u0187\u0185\3\2\2\2\u0187\u0186\3\2\2\2\u0188"+ - "\u018b\3\2\2\2\u0189\u0187\3\2\2\2\u0189\u018a\3\2\2\2\u018a\u018c\3\2"+ - "\2\2\u018b\u0189\3\2\2\2\u018c\u018d\7P\2\2\u018dQ\3\2\2\2\u018e\u018f"+ - "\7\20\2\2\u018f\u0190\5:\36\2\u0190S\3\2\2\2\u0191\u0196\5V,\2\u0192\u0193"+ - "\7\17\2\2\u0193\u0195\5V,\2\u0194\u0192\3\2\2\2\u0195\u0198\3\2\2\2\u0196"+ - "\u0194\3\2\2\2\u0196\u0197\3\2\2\2\u0197U\3\2\2\2\u0198\u0196\3\2\2\2"+ - "\u0199\u019a\5\64\33\2\u019a\u019b\7\4\2\2\u019b\u019c\5\32\16\2\u019c"+ - "W\3\2\2\2\u019d\u01a2\5\32\16\2\u019e\u019f\7\17\2\2\u019f\u01a1\5\32"+ - "\16\2\u01a0\u019e\3\2\2\2\u01a1\u01a4\3\2\2\2\u01a2\u01a0\3\2\2\2\u01a2"+ - "\u01a3\3\2\2\2\u01a3Y\3\2\2\2\u01a4\u01a2\3\2\2\2\u01a5\u01a6\7Q\2\2\u01a6"+ - "\u01a8\5&\24\2\u01a7\u01a9\7g\2\2\u01a8\u01a7\3\2\2\2\u01a8\u01a9\3\2"+ - "\2\2\u01a9\u01ac\3\2\2\2\u01aa\u01ad\5\b\5\2\u01ab\u01ad\5P)\2\u01ac\u01aa"+ - "\3\2\2\2\u01ac\u01ab\3\2\2\2\u01ad\u01af\3\2\2\2\u01ae\u01b0\7g\2\2\u01af"+ - "\u01ae\3\2\2\2\u01af\u01b0\3\2\2\2\u01b0\u01b2\3\2\2\2\u01b1\u01b3\5\\"+ - "/\2\u01b2\u01b1\3\2\2\2\u01b2\u01b3\3\2\2\2\u01b3\u01b4\3\2\2\2\u01b4"+ - "\u01b5\7g\2\2\u01b5[\3\2\2\2\u01b6\u01b8\7R\2\2\u01b7\u01b9\7g\2\2\u01b8"+ - "\u01b7\3\2\2\2\u01b8\u01b9\3\2\2\2\u01b9\u01bc\3\2\2\2\u01ba\u01bd\5\b"+ - "\5\2\u01bb\u01bd\5P)\2\u01bc\u01ba\3\2\2\2\u01bc\u01bb\3\2\2\2\u01bd]"+ - "\3\2\2\2\u01be\u01c0\5`\61\2\u01bf\u01c1\7g\2\2\u01c0\u01bf\3\2\2\2\u01c0"+ - "\u01c1\3\2\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c5\5\b\5\2\u01c3\u01c5\5P"+ - ")\2\u01c4\u01c2\3\2\2\2\u01c4\u01c3\3\2\2\2\u01c5\u01c7\3\2\2\2\u01c6"+ - "\u01c8\7g\2\2\u01c7\u01c6\3\2\2\2\u01c7\u01c8\3\2\2\2\u01c8\u01ca\3\2"+ - "\2\2\u01c9\u01cb\5\\/\2\u01ca\u01c9\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb"+ - "\u01cc\3\2\2\2\u01cc\u01cd\7g\2\2\u01cd_\3\2\2\2\u01ce\u01cf\t\16\2\2"+ - "\u01cfa\3\2\2\2\u01d0\u01d3\7_\2\2\u01d1\u01d4\58\35\2\u01d2\u01d4\5\64"+ - "\33\2\u01d3\u01d1\3\2\2\2\u01d3\u01d2\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5"+ - "\u01d6\7`\2\2\u01d6\u01d8\5&\24\2\u01d7\u01d9\7g\2\2\u01d8\u01d7\3\2\2"+ - "\2\u01d8\u01d9\3\2\2\2\u01d9\u01da\3\2\2\2\u01da\u01db\5P)\2\u01dbc\3"+ - "\2\2\2\u01dc\u01dd\7a\2\2\u01dd\u01df\5&\24\2\u01de\u01e0\7g\2\2\u01df"+ - "\u01de\3\2\2\2\u01df\u01e0\3\2\2\2\u01e0\u01e3\3\2\2\2\u01e1\u01e4\5\b"+ - "\5\2\u01e2\u01e4\5P)\2\u01e3\u01e1\3\2\2\2\u01e3\u01e2\3\2\2\2\u01e4e"+ - "\3\2\2\2\u01e5\u01e8\7b\2\2\u01e6\u01e9\5\b\5\2\u01e7\u01e9\5P)\2\u01e8"+ - "\u01e6\3\2\2\2\u01e8\u01e7\3\2\2\2\u01e9\u01eb\3\2\2\2\u01ea\u01ec\7g"+ - "\2\2\u01eb\u01ea\3\2\2\2\u01eb\u01ec\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed"+ - "\u01ee\7c\2\2\u01ee\u01ef\5&\24\2\u01efg\3\2\2\2\65jlsx\u0092\u009b\u009f"+ - "\u00a6\u00a9\u00ae\u00b2\u00b8\u00ca\u00d9\u00ec\u0116\u0118\u011a\u011f"+ - "\u0123\u0129\u012d\u0136\u013b\u0148\u014e\u015a\u016b\u0174\u0178\u017e"+ - "\u0187\u0189\u0196\u01a2\u01a8\u01ac\u01af\u01b2\u01b8\u01bc\u01c0\u01c4"+ - "\u01c7\u01ca\u01d3\u01d8\u01df\u01e3\u01e8\u01eb"; + "\3\24\3\24\3\24\3\24\3\24\5\24\u0126\n\24\7\24\u0128\n\24\f\24\16\24\u012b"+ + "\13\24\3\25\3\25\5\25\u012f\n\25\3\25\3\25\5\25\u0133\n\25\3\25\3\25\3"+ + "\26\3\26\5\26\u0139\n\26\3\26\3\26\5\26\u013d\n\26\3\26\3\26\3\27\3\27"+ + "\3\27\7\27\u0144\n\27\f\27\16\27\u0147\13\27\3\30\3\30\5\30\u014b\n\30"+ + "\3\31\3\31\3\32\3\32\3\33\3\33\3\34\3\34\3\34\6\34\u0156\n\34\r\34\16"+ + "\34\u0157\3\35\3\35\3\36\3\36\3\37\3\37\5\37\u0160\n\37\3 \3 \3!\3!\3"+ + "\"\3\"\3\"\3\"\7\"\u016a\n\"\f\"\16\"\u016d\13\"\3\"\3\"\3#\3#\3$\3$\3"+ + "%\3%\3&\3&\3&\3&\3&\3&\5&\u017d\n&\3\'\3\'\3\'\3(\3(\3(\3(\5(\u0186\n"+ + "(\3(\3(\5(\u018a\n(\3(\3(\3(\3)\3)\3)\3*\3*\3*\3*\7*\u0196\n*\f*\16*\u0199"+ + "\13*\3*\3*\3+\3+\3+\7+\u01a0\n+\f+\16+\u01a3\13+\3,\3,\3,\3,\3-\3-\3-"+ + "\7-\u01ac\n-\f-\16-\u01af\13-\3.\3.\3.\3.\5.\u01b5\n.\3.\3.\3.\3.\3.\5"+ + ".\u01bc\n.\3.\3.\3.\3.\5.\u01c2\n.\3.\3.\3.\5.\u01c7\n.\3/\3/\3/\3\60"+ + "\3\60\3\60\7\60\u01cf\n\60\f\60\16\60\u01d2\13\60\3\61\3\61\3\61\3\61"+ + "\3\61\3\61\5\61\u01da\n\61\3\62\3\62\3\62\7\62\u01df\n\62\f\62\16\62\u01e2"+ + "\13\62\3\63\3\63\3\63\7\63\u01e7\n\63\f\63\16\63\u01ea\13\63\3\64\3\64"+ + "\3\64\3\64\5\64\u01f0\n\64\3\65\3\65\3\65\5\65\u01f5\n\65\3\65\3\65\5"+ + "\65\u01f9\n\65\3\65\5\65\u01fc\n\65\3\65\5\65\u01ff\n\65\3\65\3\65\3\66"+ + "\3\66\5\66\u0205\n\66\3\66\3\66\5\66\u0209\n\66\3\67\3\67\5\67\u020d\n"+ + "\67\3\67\3\67\5\67\u0211\n\67\3\67\5\67\u0214\n\67\3\67\5\67\u0217\n\67"+ + "\3\67\3\67\38\38\39\39\39\59\u0220\n9\39\39\39\59\u0225\n9\39\39\3:\3"+ + ":\3:\5:\u022c\n:\3:\3:\5:\u0230\n:\3;\3;\3;\5;\u0235\n;\3;\5;\u0238\n"+ + ";\3;\3;\3;\3;\2\3&<\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+ + "\62\64\668:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprt\2\20\3\2\6\16\3\2\23\31\3\2"+ + "\34$\3\2%&\4\2\3\3)*\3\2,/\3\2)*\3\2\60\63\3\2\64\65\3\2CH\3\2IL\3\2p"+ + "r\3\2NO\3\2Ze\2\u0269\2z\3\2\2\2\4\u0081\3\2\2\2\6\u0083\3\2\2\2\b\u00a1"+ + "\3\2\2\2\n\u00a3\3\2\2\2\f\u00a6\3\2\2\2\16\u00ac\3\2\2\2\20\u00bd\3\2"+ + "\2\2\22\u00bf\3\2\2\2\24\u00c5\3\2\2\2\26\u00cd\3\2\2\2\30\u00d0\3\2\2"+ + "\2\32\u00d3\3\2\2\2\34\u00d5\3\2\2\2\36\u00dd\3\2\2\2 \u00e1\3\2\2\2\""+ + "\u00e8\3\2\2\2$\u00ea\3\2\2\2&\u00fb\3\2\2\2(\u012e\3\2\2\2*\u0138\3\2"+ + "\2\2,\u0140\3\2\2\2.\u0148\3\2\2\2\60\u014c\3\2\2\2\62\u014e\3\2\2\2\64"+ + "\u0150\3\2\2\2\66\u0152\3\2\2\28\u0159\3\2\2\2:\u015b\3\2\2\2<\u015d\3"+ + "\2\2\2>\u0161\3\2\2\2@\u0163\3\2\2\2B\u0165\3\2\2\2D\u0170\3\2\2\2F\u0172"+ + "\3\2\2\2H\u0174\3\2\2\2J\u017c\3\2\2\2L\u017e\3\2\2\2N\u0181\3\2\2\2P"+ + "\u018e\3\2\2\2R\u0191\3\2\2\2T\u019c\3\2\2\2V\u01a4\3\2\2\2X\u01a8\3\2"+ + "\2\2Z\u01b0\3\2\2\2\\\u01c8\3\2\2\2^\u01cb\3\2\2\2`\u01d3\3\2\2\2b\u01db"+ + "\3\2\2\2d\u01e3\3\2\2\2f\u01eb\3\2\2\2h\u01f1\3\2\2\2j\u0202\3\2\2\2l"+ + "\u020a\3\2\2\2n\u021a\3\2\2\2p\u021c\3\2\2\2r\u0228\3\2\2\2t\u0231\3\2"+ + "\2\2vy\5\4\3\2wy\7n\2\2xv\3\2\2\2xw\3\2\2\2y|\3\2\2\2zx\3\2\2\2z{\3\2"+ + "\2\2{}\3\2\2\2|z\3\2\2\2}~\7\2\2\3~\3\3\2\2\2\177\u0082\5\16\b\2\u0080"+ + "\u0082\5\6\4\2\u0081\177\3\2\2\2\u0081\u0080\3\2\2\2\u0082\5\3\2\2\2\u0083"+ + "\u0084\7\3\2\2\u0084\u0086\5\64\33\2\u0085\u0087\5<\37\2\u0086\u0085\3"+ + "\2\2\2\u0086\u0087\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\5R*\2\u0089"+ + "\u008a\7n\2\2\u008a\7\3\2\2\2\u008b\u00a2\5\16\b\2\u008c\u00a2\5\24\13"+ + "\2\u008d\u00a2\5\22\n\2\u008e\u00a2\5\26\f\2\u008f\u00a2\5\30\r\2\u0090"+ + "\u00a2\5\36\20\2\u0091\u00a2\5 \21\2\u0092\u00a2\5\f\7\2\u0093\u00a2\5"+ + "$\23\2\u0094\u00a2\5*\26\2\u0095\u00a2\5h\65\2\u0096\u00a2\5l\67\2\u0097"+ + "\u00a2\5N(\2\u0098\u00a2\5Z.\2\u0099\u00a2\5L\'\2\u009a\u00a2\5.\30\2"+ + "\u009b\u00a2\5p9\2\u009c\u00a2\5r:\2\u009d\u00a2\5t;\2\u009e\u00a2\5\60"+ + "\31\2\u009f\u00a2\5\62\32\2\u00a0\u00a2\5\n\6\2\u00a1\u008b\3\2\2\2\u00a1"+ + "\u008c\3\2\2\2\u00a1\u008d\3\2\2\2\u00a1\u008e\3\2\2\2\u00a1\u008f\3\2"+ + "\2\2\u00a1\u0090\3\2\2\2\u00a1\u0091\3\2\2\2\u00a1\u0092\3\2\2\2\u00a1"+ + "\u0093\3\2\2\2\u00a1\u0094\3\2\2\2\u00a1\u0095\3\2\2\2\u00a1\u0096\3\2"+ + "\2\2\u00a1\u0097\3\2\2\2\u00a1\u0098\3\2\2\2\u00a1\u0099\3\2\2\2\u00a1"+ + "\u009a\3\2\2\2\u00a1\u009b\3\2\2\2\u00a1\u009c\3\2\2\2\u00a1\u009d\3\2"+ + "\2\2\u00a1\u009e\3\2\2\2\u00a1\u009f\3\2\2\2\u00a1\u00a0\3\2\2\2\u00a2"+ + "\t\3\2\2\2\u00a3\u00a4\5\64\33\2\u00a4\u00a5\7\4\2\2\u00a5\13\3\2\2\2"+ + "\u00a6\u00aa\7\5\2\2\u00a7\u00ab\5<\37\2\u00a8\u00ab\5\64\33\2\u00a9\u00ab"+ + "\5\66\34\2\u00aa\u00a7\3\2\2\2\u00aa\u00a8\3\2\2\2\u00aa\u00a9\3\2\2\2"+ + "\u00ab\r\3\2\2\2\u00ac\u00b8\t\2\2\2\u00ad\u00af\5\20\t\2\u00ae\u00ad"+ + "\3\2\2\2\u00ae\u00af\3\2\2\2\u00af\u00b9\3\2\2\2\u00b0\u00b5\5\20\t\2"+ + "\u00b1\u00b2\7\17\2\2\u00b2\u00b4\5\20\t\2\u00b3\u00b1\3\2\2\2\u00b4\u00b7"+ + "\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b5\u00b6\3\2\2\2\u00b6\u00b9\3\2\2\2\u00b7"+ + "\u00b5\3\2\2\2\u00b8\u00ae\3\2\2\2\u00b8\u00b0\3\2\2\2\u00b9\17\3\2\2"+ + "\2\u00ba\u00be\5D#\2\u00bb\u00be\5\64\33\2\u00bc\u00be\5<\37\2\u00bd\u00ba"+ + "\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be\21\3\2\2\2\u00bf"+ + "\u00c1\5\32\16\2\u00c0\u00c2\5\34\17\2\u00c1\u00c0\3\2\2\2\u00c1\u00c2"+ + "\3\2\2\2\u00c2\u00c3\3\2\2\2\u00c3\u00c4\5\64\33\2\u00c4\23\3\2\2\2\u00c5"+ + "\u00c7\5\32\16\2\u00c6\u00c8\5\34\17\2\u00c7\u00c6\3\2\2\2\u00c7\u00c8"+ + "\3\2\2\2\u00c8\u00c9\3\2\2\2\u00c9\u00ca\5\64\33\2\u00ca\u00cb\7\20\2"+ + "\2\u00cb\u00cc\5&\24\2\u00cc\25\3\2\2\2\u00cd\u00ce\7\21\2\2\u00ce\u00cf"+ + "\5\24\13\2\u00cf\27\3\2\2\2\u00d0\u00d1\7\22\2\2\u00d1\u00d2\5\24\13\2"+ + "\u00d2\31\3\2\2\2\u00d3\u00d4\t\3\2\2\u00d4\33\3\2\2\2\u00d5\u00d6\7\32"+ + "\2\2\u00d6\u00d9\5&\24\2\u00d7\u00d8\7\17\2\2\u00d8\u00da\5&\24\2\u00d9"+ + "\u00d7\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u00db\3\2\2\2\u00db\u00dc\7\33"+ + "\2\2\u00dc\35\3\2\2\2\u00dd\u00de\5\"\22\2\u00de\u00df\7\20\2\2\u00df"+ + "\u00e0\5&\24\2\u00e0\37\3\2\2\2\u00e1\u00e2\5\"\22\2\u00e2\u00e3\t\4\2"+ + "\2\u00e3\u00e4\5&\24\2\u00e4!\3\2\2\2\u00e5\u00e9\58\35\2\u00e6\u00e9"+ + "\5\64\33\2\u00e7\u00e9\5\66\34\2\u00e8\u00e5\3\2\2\2\u00e8\u00e6\3\2\2"+ + "\2\u00e8\u00e7\3\2\2\2\u00e9#\3\2\2\2\u00ea\u00eb\5\"\22\2\u00eb\u00ec"+ + "\t\5\2\2\u00ec%\3\2\2\2\u00ed\u00ee\b\24\1\2\u00ee\u00ef\7\'\2\2\u00ef"+ + "\u00f0\5&\24\2\u00f0\u00f1\7(\2\2\u00f1\u00fc\3\2\2\2\u00f2\u00fc\5(\25"+ + "\2\u00f3\u00f4\t\6\2\2\u00f4\u00fc\5&\24\24\u00f5\u00f6\7>\2\2\u00f6\u00fc"+ + "\5&\24\7\u00f7\u00fc\5J&\2\u00f8\u00fc\58\35\2\u00f9\u00fc\5\64\33\2\u00fa"+ + "\u00fc\5\66\34\2\u00fb\u00ed\3\2\2\2\u00fb\u00f2\3\2\2\2\u00fb\u00f3\3"+ + "\2\2\2\u00fb\u00f5\3\2\2\2\u00fb\u00f7\3\2\2\2\u00fb\u00f8\3\2\2\2\u00fb"+ + "\u00f9\3\2\2\2\u00fb\u00fa\3\2\2\2\u00fc\u0129\3\2\2\2\u00fd\u00fe\f\23"+ + "\2\2\u00fe\u00ff\7+\2\2\u00ff\u0128\5&\24\24\u0100\u0101\f\22\2\2\u0101"+ + "\u0102\t\7\2\2\u0102\u0128\5&\24\23\u0103\u0104\f\21\2\2\u0104\u0105\t"+ + "\b\2\2\u0105\u0128\5&\24\22\u0106\u0107\f\20\2\2\u0107\u0108\t\t\2\2\u0108"+ + "\u0128\5&\24\21\u0109\u010a\f\17\2\2\u010a\u010b\t\n\2\2\u010b\u0128\5"+ + "&\24\20\u010c\u010d\f\16\2\2\u010d\u010e\7\66\2\2\u010e\u0128\5&\24\17"+ + "\u010f\u0110\f\r\2\2\u0110\u0111\7\67\2\2\u0111\u0128\5&\24\16\u0112\u0113"+ + "\f\f\2\2\u0113\u0114\78\2\2\u0114\u0128\5&\24\r\u0115\u0116\f\n\2\2\u0116"+ + "\u0117\7;\2\2\u0117\u0128\5&\24\13\u0118\u0119\f\t\2\2\u0119\u011a\7<"+ + "\2\2\u011a\u0128\5&\24\n\u011b\u011c\f\b\2\2\u011c\u011d\7=\2\2\u011d"+ + "\u0128\5&\24\t\u011e\u011f\f\26\2\2\u011f\u0128\5\34\17\2\u0120\u0121"+ + "\f\13\2\2\u0121\u0122\79\2\2\u0122\u0125\5&\24\2\u0123\u0124\7:\2\2\u0124"+ + "\u0126\5&\24\2\u0125\u0123\3\2\2\2\u0125\u0126\3\2\2\2\u0126\u0128\3\2"+ + "\2\2\u0127\u00fd\3\2\2\2\u0127\u0100\3\2\2\2\u0127\u0103\3\2\2\2\u0127"+ + "\u0106\3\2\2\2\u0127\u0109\3\2\2\2\u0127\u010c\3\2\2\2\u0127\u010f\3\2"+ + "\2\2\u0127\u0112\3\2\2\2\u0127\u0115\3\2\2\2\u0127\u0118\3\2\2\2\u0127"+ + "\u011b\3\2\2\2\u0127\u011e\3\2\2\2\u0127\u0120\3\2\2\2\u0128\u012b\3\2"+ + "\2\2\u0129\u0127\3\2\2\2\u0129\u012a\3\2\2\2\u012a\'\3\2\2\2\u012b\u0129"+ + "\3\2\2\2\u012c\u012f\5\64\33\2\u012d\u012f\5\66\34\2\u012e\u012c\3\2\2"+ + "\2\u012e\u012d\3\2\2\2\u012f\u0130\3\2\2\2\u0130\u0132\7\'\2\2\u0131\u0133"+ + "\5,\27\2\u0132\u0131\3\2\2\2\u0132\u0133\3\2\2\2\u0133\u0134\3\2\2\2\u0134"+ + "\u0135\7(\2\2\u0135)\3\2\2\2\u0136\u0139\5\64\33\2\u0137\u0139\5\66\34"+ + "\2\u0138\u0136\3\2\2\2\u0138\u0137\3\2\2\2\u0139\u013a\3\2\2\2\u013a\u013c"+ + "\7\'\2\2\u013b\u013d\5,\27\2\u013c\u013b\3\2\2\2\u013c\u013d\3\2\2\2\u013d"+ + "\u013e\3\2\2\2\u013e\u013f\7(\2\2\u013f+\3\2\2\2\u0140\u0145\5&\24\2\u0141"+ + "\u0142\7\17\2\2\u0142\u0144\5&\24\2\u0143\u0141\3\2\2\2\u0144\u0147\3"+ + "\2\2\2\u0145\u0143\3\2\2\2\u0145\u0146\3\2\2\2\u0146-\3\2\2\2\u0147\u0145"+ + "\3\2\2\2\u0148\u014a\7?\2\2\u0149\u014b\5,\27\2\u014a\u0149\3\2\2\2\u014a"+ + "\u014b\3\2\2\2\u014b/\3\2\2\2\u014c\u014d\7@\2\2\u014d\61\3\2\2\2\u014e"+ + "\u014f\7A\2\2\u014f\63\3\2\2\2\u0150\u0151\7o\2\2\u0151\65\3\2\2\2\u0152"+ + "\u0155\7o\2\2\u0153\u0154\7B\2\2\u0154\u0156\7o\2\2\u0155\u0153\3\2\2"+ + "\2\u0156\u0157\3\2\2\2\u0157\u0155\3\2\2\2\u0157\u0158\3\2\2\2\u0158\67"+ + "\3\2\2\2\u0159\u015a\t\13\2\2\u015a9\3\2\2\2\u015b\u015c\t\f\2\2\u015c"+ + ";\3\2\2\2\u015d\u015f\t\r\2\2\u015e\u0160\5> \2\u015f\u015e\3\2\2\2\u015f"+ + "\u0160\3\2\2\2\u0160=\3\2\2\2\u0161\u0162\7M\2\2\u0162?\3\2\2\2\u0163"+ + "\u0164\t\16\2\2\u0164A\3\2\2\2\u0165\u0166\7\32\2\2\u0166\u016b\5&\24"+ + "\2\u0167\u0168\7\17\2\2\u0168\u016a\5&\24\2\u0169\u0167\3\2\2\2\u016a"+ + "\u016d\3\2\2\2\u016b\u0169\3\2\2\2\u016b\u016c\3\2\2\2\u016c\u016e\3\2"+ + "\2\2\u016d\u016b\3\2\2\2\u016e\u016f\7\33\2\2\u016fC\3\2\2\2\u0170\u0171"+ + "\7t\2\2\u0171E\3\2\2\2\u0172\u0173\7v\2\2\u0173G\3\2\2\2\u0174\u0175\7"+ + "s\2\2\u0175I\3\2\2\2\u0176\u017d\5<\37\2\u0177\u017d\5@!\2\u0178\u017d"+ + "\5B\"\2\u0179\u017d\5D#\2\u017a\u017d\5F$\2\u017b\u017d\5H%\2\u017c\u0176"+ + "\3\2\2\2\u017c\u0177\3\2\2\2\u017c\u0178\3\2\2\2\u017c\u0179\3\2\2\2\u017c"+ + "\u017a\3\2\2\2\u017c\u017b\3\2\2\2\u017dK\3\2\2\2\u017e\u017f\7P\2\2\u017f"+ + "\u0180\7u\2\2\u0180M\3\2\2\2\u0181\u0182\7Q\2\2\u0182\u0183\5\64\33\2"+ + "\u0183\u0185\7\'\2\2\u0184\u0186\5T+\2\u0185\u0184\3\2\2\2\u0185\u0186"+ + "\3\2\2\2\u0186\u0187\3\2\2\2\u0187\u0189\7(\2\2\u0188\u018a\5P)\2\u0189"+ + "\u0188\3\2\2\2\u0189\u018a\3\2\2\2\u018a\u018b\3\2\2\2\u018b\u018c\5R"+ + "*\2\u018c\u018d\7n\2\2\u018dO\3\2\2\2\u018e\u018f\7R\2\2\u018f\u0190\5"+ + "X-\2\u0190Q\3\2\2\2\u0191\u0192\7S\2\2\u0192\u0197\7n\2\2\u0193\u0196"+ + "\5\b\5\2\u0194\u0196\7n\2\2\u0195\u0193\3\2\2\2\u0195\u0194\3\2\2\2\u0196"+ + "\u0199\3\2\2\2\u0197\u0195\3\2\2\2\u0197\u0198\3\2\2\2\u0198\u019a\3\2"+ + "\2\2\u0199\u0197\3\2\2\2\u019a\u019b\7T\2\2\u019bS\3\2\2\2\u019c\u01a1"+ + "\5V,\2\u019d\u019e\7\17\2\2\u019e\u01a0\5V,\2\u019f\u019d\3\2\2\2\u01a0"+ + "\u01a3\3\2\2\2\u01a1\u019f\3\2\2\2\u01a1\u01a2\3\2\2\2\u01a2U\3\2\2\2"+ + "\u01a3\u01a1\3\2\2\2\u01a4\u01a5\5\64\33\2\u01a5\u01a6\7\4\2\2\u01a6\u01a7"+ + "\5\32\16\2\u01a7W\3\2\2\2\u01a8\u01ad\5\32\16\2\u01a9\u01aa\7\17\2\2\u01aa"+ + "\u01ac\5\32\16\2\u01ab\u01a9\3\2\2\2\u01ac\u01af\3\2\2\2\u01ad\u01ab\3"+ + "\2\2\2\u01ad\u01ae\3\2\2\2\u01aeY\3\2\2\2\u01af\u01ad\3\2\2\2\u01b0\u01b1"+ + "\7U\2\2\u01b1\u01b2\5\64\33\2\u01b2\u01b4\7\'\2\2\u01b3\u01b5\5^\60\2"+ + "\u01b4\u01b3\3\2\2\2\u01b4\u01b5\3\2\2\2\u01b5\u01b6\3\2\2\2\u01b6\u01b7"+ + "\7(\2\2\u01b7\u01b8\7R\2\2\u01b8\u01b9\7V\2\2\u01b9\u01bb\7\'\2\2\u01ba"+ + "\u01bc\5b\62\2\u01bb\u01ba\3\2\2\2\u01bb\u01bc\3\2\2\2\u01bc\u01bd\3\2"+ + "\2\2\u01bd\u01be\7(\2\2\u01be\u01bf\7R\2\2\u01bf\u01c1\7\'\2\2\u01c0\u01c2"+ + "\5d\63\2\u01c1\u01c0\3\2\2\2\u01c1\u01c2\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3"+ + "\u01c6\7(\2\2\u01c4\u01c7\5\\/\2\u01c5\u01c7\5R*\2\u01c6\u01c4\3\2\2\2"+ + "\u01c6\u01c5\3\2\2\2\u01c7[\3\2\2\2\u01c8\u01c9\7\20\2\2\u01c9\u01ca\5"+ + "<\37\2\u01ca]\3\2\2\2\u01cb\u01d0\5`\61\2\u01cc\u01cd\7\17\2\2\u01cd\u01cf"+ + "\5`\61\2\u01ce\u01cc\3\2\2\2\u01cf\u01d2\3\2\2\2\u01d0\u01ce\3\2\2\2\u01d0"+ + "\u01d1\3\2\2\2\u01d1_\3\2\2\2\u01d2\u01d0\3\2\2\2\u01d3\u01d4\5\64\33"+ + "\2\u01d4\u01d5\7\4\2\2\u01d5\u01d6\5\32\16\2\u01d6\u01d9\7W\2\2\u01d7"+ + "\u01da\58\35\2\u01d8\u01da\5:\36\2\u01d9\u01d7\3\2\2\2\u01d9\u01d8\3\2"+ + "\2\2\u01daa\3\2\2\2\u01db\u01e0\58\35\2\u01dc\u01dd\7\17\2\2\u01dd\u01df"+ + "\58\35\2\u01de\u01dc\3\2\2\2\u01df\u01e2\3\2\2\2\u01e0\u01de\3\2\2\2\u01e0"+ + "\u01e1\3\2\2\2\u01e1c\3\2\2\2\u01e2\u01e0\3\2\2\2\u01e3\u01e8\5f\64\2"+ + "\u01e4\u01e5\7\17\2\2\u01e5\u01e7\5f\64\2\u01e6\u01e4\3\2\2\2\u01e7\u01ea"+ + "\3\2\2\2\u01e8\u01e6\3\2\2\2\u01e8\u01e9\3\2\2\2\u01e9e\3\2\2\2\u01ea"+ + "\u01e8\3\2\2\2\u01eb\u01ec\5\32\16\2\u01ec\u01ef\7W\2\2\u01ed\u01f0\5"+ + "8\35\2\u01ee\u01f0\5:\36\2\u01ef\u01ed\3\2\2\2\u01ef\u01ee\3\2\2\2\u01f0"+ + "g\3\2\2\2\u01f1\u01f2\7X\2\2\u01f2\u01f4\5&\24\2\u01f3\u01f5\7n\2\2\u01f4"+ + "\u01f3\3\2\2\2\u01f4\u01f5\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6\u01f9\5\b"+ + "\5\2\u01f7\u01f9\5R*\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2\2\u01f9\u01fb"+ + "\3\2\2\2\u01fa\u01fc\7n\2\2\u01fb\u01fa\3\2\2\2\u01fb\u01fc\3\2\2\2\u01fc"+ + "\u01fe\3\2\2\2\u01fd\u01ff\5j\66\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2"+ + "\2\2\u01ff\u0200\3\2\2\2\u0200\u0201\7n\2\2\u0201i\3\2\2\2\u0202\u0204"+ + "\7Y\2\2\u0203\u0205\7n\2\2\u0204\u0203\3\2\2\2\u0204\u0205\3\2\2\2\u0205"+ + "\u0208\3\2\2\2\u0206\u0209\5\b\5\2\u0207\u0209\5R*\2\u0208\u0206\3\2\2"+ + "\2\u0208\u0207\3\2\2\2\u0209k\3\2\2\2\u020a\u020c\5n8\2\u020b\u020d\7"+ + "n\2\2\u020c\u020b\3\2\2\2\u020c\u020d\3\2\2\2\u020d\u0210\3\2\2\2\u020e"+ + "\u0211\5\b\5\2\u020f\u0211\5R*\2\u0210\u020e\3\2\2\2\u0210\u020f\3\2\2"+ + "\2\u0211\u0213\3\2\2\2\u0212\u0214\7n\2\2\u0213\u0212\3\2\2\2\u0213\u0214"+ + "\3\2\2\2\u0214\u0216\3\2\2\2\u0215\u0217\5j\66\2\u0216\u0215\3\2\2\2\u0216"+ + "\u0217\3\2\2\2\u0217\u0218\3\2\2\2\u0218\u0219\7n\2\2\u0219m\3\2\2\2\u021a"+ + "\u021b\t\17\2\2\u021bo\3\2\2\2\u021c\u021f\7f\2\2\u021d\u0220\58\35\2"+ + "\u021e\u0220\5\64\33\2\u021f\u021d\3\2\2\2\u021f\u021e\3\2\2\2\u0220\u0221"+ + "\3\2\2\2\u0221\u0222\7g\2\2\u0222\u0224\5&\24\2\u0223\u0225\7n\2\2\u0224"+ + "\u0223\3\2\2\2\u0224\u0225\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u0227\5R"+ + "*\2\u0227q\3\2\2\2\u0228\u0229\7h\2\2\u0229\u022b\5&\24\2\u022a\u022c"+ + "\7n\2\2\u022b\u022a\3\2\2\2\u022b\u022c\3\2\2\2\u022c\u022f\3\2\2\2\u022d"+ + "\u0230\5\b\5\2\u022e\u0230\5R*\2\u022f\u022d\3\2\2\2\u022f\u022e\3\2\2"+ + "\2\u0230s\3\2\2\2\u0231\u0234\7i\2\2\u0232\u0235\5\b\5\2\u0233\u0235\5"+ + "R*\2\u0234\u0232\3\2\2\2\u0234\u0233\3\2\2\2\u0235\u0237\3\2\2\2\u0236"+ + "\u0238\7n\2\2\u0237\u0236\3\2\2\2\u0237\u0238\3\2\2\2\u0238\u0239\3\2"+ + "\2\2\u0239\u023a\7j\2\2\u023a\u023b\5&\24\2\u023bu\3\2\2\2=xz\u0081\u0086"+ + "\u00a1\u00aa\u00ae\u00b5\u00b8\u00bd\u00c1\u00c7\u00d9\u00e8\u00fb\u0125"+ + "\u0127\u0129\u012e\u0132\u0138\u013c\u0145\u014a\u0157\u015f\u016b\u017c"+ + "\u0185\u0189\u0195\u0197\u01a1\u01ad\u01b4\u01bb\u01c1\u01c6\u01d0\u01d9"+ + "\u01e0\u01e8\u01ef\u01f4\u01f8\u01fb\u01fe\u0204\u0208\u020c\u0210\u0213"+ + "\u0216\u021f\u0224\u022b\u022f\u0234\u0237"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/prog8lib/c64lib.p8 b/prog8lib/c64lib.p8 index 822b74573..60cd9b7e9 100644 --- a/prog8lib/c64lib.p8 +++ b/prog8lib/c64lib.p8 @@ -1,12 +1,10 @@ ; Prog8 definitions for the Commodore-64 -; Including memory registers, I/O registers, Basic and Kernal subroutines, utility subroutines. +; Including memory registers, I/O registers, Basic and Kernal subroutines. ; ; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 -; ; +; ; indent format: TABS, size=8 -%option enable_floats - ~ c64 { memory byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP @@ -112,25 +110,25 @@ ; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. ; checked functions below: -sub MOVFM (mflpt: AY) -> (A?, Y?) = $bba2 ; load mflpt value from memory in A/Y into fac1 -sub FREADMEM () -> (A?, Y?) = $bba6 ; load mflpt value from memory in $22/$23 into fac1 -sub CONUPK (mflpt: AY) -> (A?, Y?) = $ba8c ; load mflpt value from memory in A/Y into fac2 -sub FAREADMEM () -> (A?, Y?) = $ba90 ; load mflpt value from memory in $22/$23 into fac2 -sub MOVFA () -> (A?, X?) = $bbfc ; copy fac2 to fac1 -sub MOVAF () -> (A?, X?) = $bc0c ; copy fac1 to fac2 (rounded) -sub MOVEF () -> (A?, X?) = $bc0f ; copy fac1 to fac2 -sub FTOMEMXY (mflpt: XY) -> (A?, Y?) = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt +asmsub MOVFM (mflpt: word @ AY) -> clobbers(A,Y) -> () = $bba2 ; load mflpt value from memory in A/Y into fac1 +asmsub FREADMEM () -> clobbers(A,Y) -> () = $bba6 ; load mflpt value from memory in $22/$23 into fac1 +asmsub CONUPK (mflpt: word @ AY) -> clobbers(A,Y) -> () = $ba8c ; load mflpt value from memory in A/Y into fac2 +asmsub FAREADMEM () -> clobbers(A,Y) -> () = $ba90 ; load mflpt value from memory in $22/$23 into fac2 +asmsub MOVFA () -> clobbers(A,X) -> () = $bbfc ; copy fac2 to fac1 +asmsub MOVAF () -> clobbers(A,X) -> () = $bc0c ; copy fac1 to fac2 (rounded) +asmsub MOVEF () -> clobbers(A,X) -> () = $bc0f ; copy fac1 to fac2 +asmsub FTOMEMXY (mflpt: word @ XY) -> clobbers(A,Y) -> () = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt ; fac1-> signed word in Y/A (might throw ILLEGAL QUANTITY) ; (use c64flt.FTOSWRDAY to get A/Y output; lo/hi switched to normal order) -sub FTOSWORDYA () -> (Y, A, X?) = $b1aa +asmsub FTOSWORDYA () -> clobbers(X) -> (byte @ Y, byte @ A) = $b1aa ; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) ; (use c64flt.GETADRAY to get A/Y output; lo/hi switched to normal order) -sub GETADR () -> (Y, A, X?) = $b7f7 +asmsub GETADR () -> clobbers(X) -> (byte @ Y, byte @ A) = $b7f7 -sub QINT () -> (?) = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST. -sub AYINT () -> (?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) +asmsub QINT () -> clobbers(A,X,Y) -> () = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST. +asmsub AYINT () -> clobbers(A,X,Y) -> () = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) ; signed word in Y/A -> float in fac1 ; (use c64flt.GIVAYFAY to use A/Y input; lo/hi switched to normal order) @@ -138,51 +136,51 @@ sub AYINT () -> (?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIR ; there is also c64flt.FREADS32 that reads from 98-101 ($62-$65) MSB FIRST ; there is also c64flt.FREADUS32 that reads from 98-101 ($62-$65) MSB FIRST ; there is also c64flt.FREADS24AXY that reads signed int24 into fac1 from A/X/Y (lo/mid/hi bytes) -sub GIVAYF (lo: Y, hi: A) -> (?) = $b391 +asmsub GIVAYF (lo: byte @ Y, hi: byte @ A) -> clobbers(A,X,Y) -> () = $b391 -sub FREADUY (ubyte: Y) -> (?) = $b3a2 ; 8 bit unsigned Y -> float in fac1 -sub FREADSA (sbyte: A) -> (?) = $bc3c ; 8 bit signed A -> float in fac1 -sub FREADSTR (length: A) -> (?) = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length -sub FPRINTLN () -> (?) = $aabc ; print string of fac1, on one line (= with newline) -sub FOUT () -> (AY, X?) = $bddd ; fac1 -> string, address returned in AY ($0100) +asmsub FREADUY (ubyte: byte @ Y) -> clobbers(A,X,Y) -> () = $b3a2 ; 8 bit unsigned Y -> float in fac1 +asmsub FREADSA (sbyte: byte @ A) -> clobbers(A,X,Y) -> () = $bc3c ; 8 bit signed A -> float in fac1 +asmsub FREADSTR (length: byte @ A) -> clobbers(A,X,Y) -> () = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length +asmsub FPRINTLN () -> clobbers(A,X,Y) -> () = $aabc ; print string of fac1, on one line (= with newline) +asmsub FOUT () -> clobbers(X) -> (word @ AY) = $bddd ; fac1 -> string, address returned in AY ($0100) -sub FADDH () -> (?) = $b849 ; fac1 += 0.5, for rounding- call this before INT -sub MUL10 () -> (?) = $bae2 ; fac1 *= 10 -sub DIV10 () -> (?) = $bafe ; fac1 /= 10 , CAUTION: result is always positive! -sub FCOMP (mflpt: AY) -> (A, X?, Y?) = $bc5b ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than +asmsub FADDH () -> clobbers(A,X,Y) -> () = $b849 ; fac1 += 0.5, for rounding- call this before INT +asmsub MUL10 () -> clobbers(A,X,Y) -> () = $bae2 ; fac1 *= 10 +asmsub DIV10 () -> clobbers(A,X,Y) -> () = $bafe ; fac1 /= 10 , CAUTION: result is always positive! +asmsub FCOMP (mflpt: word @ AY) -> clobbers(X,Y) -> (byte @ A) = $bc5b ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than -sub FADDT () -> (?) = $b86a ; fac1 += fac2 -sub FADD (mflpt: AY) -> (?) = $b867 ; fac1 += mflpt value from A/Y -sub FSUBT () -> (?) = $b853 ; fac1 = fac2-fac1 mind the order of the operands -sub FSUB (mflpt: AY) -> (?) = $b850 ; fac1 = mflpt from A/Y - fac1 -sub FMULTT () -> (?) = $ba2b ; fac1 *= fac2 -sub FMULT (mflpt: AY) -> (?) = $ba28 ; fac1 *= mflpt value from A/Y -sub FDIVT () -> (?) = $bb12 ; fac1 = fac2/fac1 mind the order of the operands -sub FDIV (mflpt: AY) -> (?) = $bb0f ; fac1 = mflpt in A/Y / fac1 -sub FPWRT () -> (?) = $bf7b ; fac1 = fac2 ** fac1 -sub FPWR (mflpt: AY) -> (?) = $bf78 ; fac1 = fac2 ** mflpt from A/Y +asmsub FADDT () -> clobbers(A,X,Y) -> () = $b86a ; fac1 += fac2 +asmsub FADD (mflpt: word @ AY) -> clobbers(A,X,Y) -> () = $b867 ; fac1 += mflpt value from A/Y +asmsub FSUBT () -> clobbers(A,X,Y) -> () = $b853 ; fac1 = fac2-fac1 mind the order of the operands +asmsub FSUB (mflpt: word @ AY) -> clobbers(A,X,Y) -> () = $b850 ; fac1 = mflpt from A/Y - fac1 +asmsub FMULTT () -> clobbers(A,X,Y) -> () = $ba2b ; fac1 *= fac2 +asmsub FMULT (mflpt: word @ AY) -> clobbers(A,X,Y) -> () = $ba28 ; fac1 *= mflpt value from A/Y +asmsub FDIVT () -> clobbers(A,X,Y) -> () = $bb12 ; fac1 = fac2/fac1 mind the order of the operands +asmsub FDIV (mflpt: word @ AY) -> clobbers(A,X,Y) -> () = $bb0f ; fac1 = mflpt in A/Y / fac1 +asmsub FPWRT () -> clobbers(A,X,Y) -> () = $bf7b ; fac1 = fac2 ** fac1 +asmsub FPWR (mflpt: word @ AY) -> clobbers(A,X,Y) -> () = $bf78 ; fac1 = fac2 ** mflpt from A/Y -sub NOTOP () -> (?) = $aed4 ; fac1 = NOT(fac1) -sub INT () -> (?) = $bccc ; INT() truncates, use FADDH first to round instead of trunc -sub LOG () -> (?) = $b9ea ; fac1 = LN(fac1) (natural log) -sub SGN () -> (?) = $bc39 ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) -sub SIGN () -> (A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive -sub ABS () -> () = $bc58 ; fac1 = ABS(fac1) -sub SQR () -> (?) = $bf71 ; fac1 = SQRT(fac1) -sub EXP () -> (?) = $bfed ; fac1 = EXP(fac1) (e ** fac1) -sub NEGOP () -> (A?) = $bfb4 ; switch the sign of fac1 -sub RND () -> (?) = $e097 ; fac1 = RND() (use RNDA instead) -sub RNDA (acc: A) -> (?) = $e09a ; fac1 = RND(A) -sub COS () -> (?) = $e264 ; fac1 = COS(fac1) -sub SIN () -> (?) = $e26b ; fac1 = SIN(fac1) -sub TAN () -> (?) = $e2b4 ; fac1 = TAN(fac1) -sub ATN () -> (?) = $e30e ; fac1 = ATN(fac1) +asmsub NOTOP () -> clobbers(A,X,Y) -> () = $aed4 ; fac1 = NOT(fac1) +asmsub INT () -> clobbers(A,X,Y) -> () = $bccc ; INT() truncates, use FADDH first to round instead of trunc +asmsub LOG () -> clobbers(A,X,Y) -> () = $b9ea ; fac1 = LN(fac1) (natural log) +asmsub SGN () -> clobbers(A,X,Y) -> () = $bc39 ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +asmsub SIGN () -> clobbers() -> (byte @ A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive +asmsub ABS () -> clobbers() -> () = $bc58 ; fac1 = ABS(fac1) +asmsub SQR () -> clobbers(A,X,Y) -> () = $bf71 ; fac1 = SQRT(fac1) +asmsub EXP () -> clobbers(A,X,Y) -> () = $bfed ; fac1 = EXP(fac1) (e ** fac1) +asmsub NEGOP () -> clobbers(A) -> () = $bfb4 ; switch the sign of fac1 +asmsub RND () -> clobbers(A,X,Y) -> () = $e097 ; fac1 = RND() (use RNDA instead) +asmsub RNDA (acc: byte @ A) -> clobbers(A,X,Y) -> () = $e09a ; fac1 = RND(A) +asmsub COS () -> clobbers(A,X,Y) -> () = $e264 ; fac1 = COS(fac1) +asmsub SIN () -> clobbers(A,X,Y) -> () = $e26b ; fac1 = SIN(fac1) +asmsub TAN () -> clobbers(A,X,Y) -> () = $e2b4 ; fac1 = TAN(fac1) +asmsub ATN () -> clobbers(A,X,Y) -> () = $e30e ; fac1 = ATN(fac1) ; ---- C64 basic routines ---- -sub CLEARSCR () -> (?) = $E544 ; clear the screen -sub HOMECRSR () -> (?) = $E566 ; cursor to top left of screen +asmsub CLEARSCR () -> clobbers(A,X,Y) -> () = $E544 ; clear the screen +asmsub HOMECRSR () -> clobbers(A,X,Y) -> () = $E566 ; cursor to top left of screen ; ---- end of C64 basic routines ---- @@ -191,895 +189,48 @@ sub HOMECRSR () -> (?) = $E566 ; cursor to top left of screen ; ---- C64 kernal routines ---- -sub IRQDFRT () -> (?) = $EA31 ; default IRQ routine -sub IRQDFEND () -> (?) = $EA81 ; default IRQ end/cleanup -sub CINT () -> (?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip -sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices (CIA, SID, IRQ) -sub RAMTAS () -> (?) = $FF87 ; initialize RAM, tape buffer, screen -sub RESTOR () -> (?) = $FF8A ; restore default I/O vectors -sub VECTOR (dir: Pc, userptr: XY) -> (A?, Y?) = $FF8D ; read/set I/O vector table -sub SETMSG (value: A) -> () = $FF90 ; set Kernal message control flag -sub SECOND (address: A) -> (A?) = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN -sub TKSA (address: A) -> (A?) = $FF96 ; (alias: TALKSA) send secondary address after TALK -sub MEMTOP (dir: Pc, address: XY) -> (XY) = $FF99 ; read/set top of memory pointer -sub MEMBOT (dir: Pc, address: XY) -> (XY) = $FF9C ; read/set bottom of memory pointer -sub SCNKEY () -> (?) = $FF9F ; scan the keyboard -sub SETTMO (timeout: A) -> () = $FFA2 ; set time-out flag for IEEE bus -sub ACPTR () -> (A) = $FFA5 ; (alias: IECIN) input byte from serial bus -sub CIOUT (databyte: A) -> () = $FFA8 ; (alias: IECOUT) output byte to serial bus -sub UNTLK () -> (A?) = $FFAB ; command serial bus device to UNTALK -sub UNLSN () -> (A?) = $FFAE ; command serial bus device to UNLISTEN -sub LISTEN (device: A) -> (A?) = $FFB1 ; command serial bus device to LISTEN -sub TALK (device: A) -> (A?) = $FFB4 ; command serial bus device to TALK -sub READST () -> (A) = $FFB7 ; read I/O status word -sub SETLFS (logical: A, device: X, address: Y) -> () = $FFBA ; set logical file parameters -sub SETNAM (namelen: A, filename: XY) -> () = $FFBD ; set filename parameters -sub OPEN () -> (?) = $FFC0 ; (via 794 ($31A)) open a logical file -sub CLOSE (logical: A) -> (?) = $FFC3 ; (via 796 ($31C)) close a logical file -sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel -sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel -sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices -sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. -sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character -sub LOAD (verify: A, address: XY) -> (Pc, A, X, Y) = $FFD5 ; (via 816 ($330)) load from device -sub SAVE (zp_startaddr: A, endaddr: XY) -> (Pc, A) = $FFD8 ; (via 818 ($332)) save to a device -sub SETTIM (low: A, middle: X, high: Y) -> () = $FFDB ; set the software clock -sub RDTIM () -> (A, X, Y) = $FFDE ; read the software clock -sub STOP () -> (Pz, Pc, A?, X?) = $FFE1 ; (via 808 ($328)) check the STOP key -sub GETIN () -> (A, X?, Y?) = $FFE4 ; (via 810 ($32A)) get a character -sub CLALL () -> (A?, X?) = $FFE7 ; (via 812 ($32C)) close all files -sub UDTIM () -> (A?, X?) = $FFEA ; update the software clock -sub SCREEN () -> (X, Y) = $FFED ; read number of screen rows and columns -sub PLOT (dir: Pc, col: Y, row: X) -> (X, Y) = $FFF0 ; read/set position of cursor on screen -sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices +asmsub IRQDFRT () -> clobbers(A,X,Y) -> () = $EA31 ; default IRQ routine +asmsub IRQDFEND () -> clobbers(A,X,Y) -> () = $EA81 ; default IRQ end/cleanup +asmsub CINT () -> clobbers(A,X,Y) -> () = $FF81 ; (alias: SCINIT) initialize screen editor and video chip +asmsub IOINIT () -> clobbers(A, X) -> () = $FF84 ; initialize I/O devices (CIA, SID, IRQ) +asmsub RAMTAS () -> clobbers(A,X,Y) -> () = $FF87 ; initialize RAM, tape buffer, screen +asmsub RESTOR () -> clobbers(A,X,Y) -> () = $FF8A ; restore default I/O vectors +asmsub VECTOR (dir: byte @ Pc, userptr: word @ XY) -> clobbers(A,Y) -> () = $FF8D ; read/set I/O vector table +asmsub SETMSG (value: byte @ A) -> clobbers() -> () = $FF90 ; set Kernal message control flag +asmsub SECOND (address: byte @ A) -> clobbers(A) -> () = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN +asmsub TKSA (address: byte @ A) -> clobbers(A) -> () = $FF96 ; (alias: TALKSA) send secondary address after TALK +asmsub MEMTOP (dir: byte @ Pc, address: word @ XY) -> clobbers() -> (word @ XY) = $FF99 ; read/set top of memory pointer +asmsub MEMBOT (dir: byte @ Pc, address: word @ XY) -> clobbers() -> (word @ XY) = $FF9C ; read/set bottom of memory pointer +asmsub SCNKEY () -> clobbers(A,X,Y) -> () = $FF9F ; scan the keyboard +asmsub SETTMO (timeout: byte @ A) -> clobbers() -> () = $FFA2 ; set time-out flag for IEEE bus +asmsub ACPTR () -> clobbers() -> (byte @ A) = $FFA5 ; (alias: IECIN) input byte from serial bus +asmsub CIOUT (databyte: byte @ A) -> clobbers() -> () = $FFA8 ; (alias: IECOUT) output byte to serial bus +asmsub UNTLK () -> clobbers(A) -> () = $FFAB ; command serial bus device to UNTALK +asmsub UNLSN () -> clobbers(A) -> () = $FFAE ; command serial bus device to UNLISTEN +asmsub LISTEN (device: byte @ A) -> clobbers(A) -> () = $FFB1 ; command serial bus device to LISTEN +asmsub TALK (device: byte @ A) -> clobbers(A) -> () = $FFB4 ; command serial bus device to TALK +asmsub READST () -> clobbers() -> (byte @ A) = $FFB7 ; read I/O status word +asmsub SETLFS (logical: byte @ A, device: byte @ X, address: byte @ Y) -> clobbers() -> () = $FFBA ; set logical file parameters +asmsub SETNAM (namelen: byte @ A, filename: word @ XY) -> clobbers() -> () = $FFBD ; set filename parameters +asmsub OPEN () -> clobbers(A,X,Y) -> () = $FFC0 ; (via 794 ($31A)) open a logical file +asmsub CLOSE (logical: byte @ A) -> clobbers(A,X,Y) -> () = $FFC3 ; (via 796 ($31C)) close a logical file +asmsub CHKIN (logical: byte @ X) -> clobbers(A,X) -> () = $FFC6 ; (via 798 ($31E)) define an input channel +asmsub CHKOUT (logical: byte @ X) -> clobbers(A,X) -> () = $FFC9 ; (via 800 ($320)) define an output channel +asmsub CLRCHN () -> clobbers(A,X) -> () = $FFCC ; (via 802 ($322)) restore default devices +asmsub CHRIN () -> clobbers(Y) -> (byte @ A) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. +asmsub CHROUT (char: byte @ A) -> clobbers() -> () = $FFD2 ; (via 806 ($326)) output a character +asmsub LOAD (verify: byte @ A, address: word @ XY) -> clobbers() -> (byte @Pc, byte @ A, byte @ X, byte @ Y) = $FFD5 ; (via 816 ($330)) load from device +asmsub SAVE (zp_startaddr: byte @ A, endaddr: word @ XY) -> clobbers() -> (byte @ Pc, byte @ A) = $FFD8 ; (via 818 ($332)) save to a device +asmsub SETTIM (low: byte @ A, middle: byte @ X, high: byte @ Y) -> clobbers() -> () = $FFDB ; set the software clock +asmsub RDTIM () -> clobbers() -> (byte @ A, byte @ X, byte @ Y) = $FFDE ; read the software clock +asmsub STOP () -> clobbers(A,X) -> (byte @ Pz, byte @ Pc) = $FFE1 ; (via 808 ($328)) check the STOP key +asmsub GETIN () -> clobbers(X,Y) -> (byte @ A) = $FFE4 ; (via 810 ($32A)) get a character +asmsub CLALL () -> clobbers(A,X) -> () = $FFE7 ; (via 812 ($32C)) close all files +asmsub UDTIM () -> clobbers(A,X) -> () = $FFEA ; update the software clock +asmsub SCREEN () -> clobbers() -> (byte @ X, byte @ Y) = $FFED ; read number of screen rows and columns +asmsub PLOT (dir: byte @ Pc, col: byte @ Y, row: byte @ X) -> clobbers() -> (byte @ X, byte @ Y) = $FFF0 ; read/set position of cursor on screen +asmsub IOBASE () -> clobbers() -> (byte @ X, byte @ Y) = $FFF3 ; read base address of I/O devices ; ---- end of C64 kernal routines ---- - - -; ----- utility functions ---- - -sub init_system () -> (?) { - ; ---- initializes the machine to a sane starting state - ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, - ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. - ; Also a different color scheme is chosen to identify ourselves a little. - %asm {{ - sei - cld - lda #%00101111 - sta $00 - lda #%00100111 - sta $01 - jsr c64.IOINIT - jsr c64.RESTOR - jsr c64.CINT - lda #6 - sta c64.EXTCOL - lda #7 - sta c64.COLOR - lda #0 - sta c64.BGCOL0 - tax - tay - clc - clv - cli - rts - }} } - -} ; ------ end of block c64 - - -~ c64flt { - ; ---- this block contains C-64 floating point related functions ---- - - -sub FREADS32 () -> (?) { - ; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST) - %asm {{ - lda $62 - eor #$ff - asl a - lda #0 - ldx #$a0 - jmp $bc4f ; internal BASIC routine - }} -} - -sub FREADUS32 () -> (?) { - ; ---- fac1 = uint32 from $62-$65 big endian (MSB FIRST) - %asm {{ - sec - lda #0 - ldx #$a0 - jmp $bc4f ; internal BASIC routine - }} -} - -sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (?) { - ; ---- fac1 = signed int24 (A/X/Y contain lo/mid/hi bytes) - ; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead. - %asm {{ - sty $62 - stx $63 - sta $64 - lda $62 - eor #$FF - asl a - lda #0 - sta $65 - ldx #$98 - jmp $bc4f ; internal BASIC routine - }} -} - -sub GIVUAYF (uword: AY) -> (?) { - ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 - %asm {{ - sty $62 - sta $63 - ldx #$90 - sec - jmp $bc49 ; internal BASIC routine - }} -} - -sub GIVAYFAY (sword: AY) -> (?) { - ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 - %asm {{ - sta c64.SCRATCH_ZP1 - tya - ldy c64.SCRATCH_ZP1 - jmp c64.GIVAYF ; this uses the inverse order, Y/A - }} -} - -sub FTOSWRDAY () -> (AY, X?) { - ; ---- fac1 to signed word in A/Y - %asm {{ - jsr c64.FTOSWORDYA ; note the inverse Y/A order - sta c64.SCRATCH_ZP1 - tya - ldy c64.SCRATCH_ZP1 - rts - }} -} - -sub GETADRAY () -> (AY, X?) { - ; ---- fac1 to unsigned word in A/Y - %asm {{ - jsr c64.GETADR ; this uses the inverse order, Y/A - sta c64.SCRATCH_ZP1 - tya - ldy c64.SCRATCH_ZP1 - rts - }} -} - - -sub copy_mflt (source: XY) -> (A?, Y?) { - ; ---- copy a 5 byte MFLT floating point variable to another place - ; input: X/Y = source address, c64.SCRATCH_ZPWORD1 = destination address - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZPWORD1+1 - ldy #0 - lda (c64.SCRATCH_ZP1),y - sta (c64.SCRATCH_ZPWORD1),y - iny - lda (c64.SCRATCH_ZP1),y - sta (c64.SCRATCH_ZPWORD1),y - iny - lda (c64.SCRATCH_ZP1),y - sta (c64.SCRATCH_ZPWORD1),y - iny - lda (c64.SCRATCH_ZP1),y - sta (c64.SCRATCH_ZPWORD1),y - iny - lda (c64.SCRATCH_ZP1),y - sta (c64.SCRATCH_ZPWORD1),y - ldy c64.SCRATCH_ZPWORD1+1 - rts - }} -} - -sub float_add_one (mflt: XY) -> (?) { - ; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - txa - jsr c64.MOVFM ; fac1 = float XY - lda #c64.FL_FONE - jsr c64.FADD ; fac1 += 1 - ldx c64.SCRATCH_ZP1 - ldy c64.SCRATCH_ZP2 - jmp c64.FTOMEMXY ; float XY = fac1 - }} -} - -sub float_sub_one (mflt: XY) -> (?) { - ; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - lda #c64.FL_FONE - jsr c64.MOVFM ; fac1 = 1 - txa - ldy c64.SCRATCH_ZP2 - jsr c64.FSUB ; fac1 = float XY - 1 - ldx c64.SCRATCH_ZP1 - ldy c64.SCRATCH_ZP2 - jmp c64.FTOMEMXY ; float XY = fac1 - }} -} - -sub float_add_SW1_to_XY (mflt: XY) -> (?) { - ; ---- add MFLT pointed to by SCRATCH_ZPWORD1 to the MFLT pointed to by X/Y. Clobbers A, X, Y - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - txa - jsr c64.MOVFM ; fac1 = float XY - lda c64.SCRATCH_ZPWORD1 - ldy c64.SCRATCH_ZPWORD1+1 - jsr c64.FADD ; fac1 += SCRATCH_ZPWORD1 - ldx c64.SCRATCH_ZP1 - ldy c64.SCRATCH_ZP2 - jmp c64.FTOMEMXY ; float XY = fac1 - }} -} - -sub float_sub_SW1_from_XY (mflt: XY) -> (?) { - ; ---- subtract MFLT pointed to by SCRATCH_ZPWORD1 from the MFLT pointed to by X/Y. Clobbers A, X, Y - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - lda c64.SCRATCH_ZPWORD1 - ldy c64.SCRATCH_ZPWORD1+1 - jsr c64.MOVFM ; fac1 = SCRATCH_ZPWORD1 - txa - ldy c64.SCRATCH_ZP2 - jsr c64.FSUB ; fac1 = float XY - SCRATCH_ZPWORD1 - ldx c64.SCRATCH_ZP1 - ldy c64.SCRATCH_ZP2 - jmp c64.FTOMEMXY ; float XY = fac1 - }} -} - -} ; ------ end of block c64flt - - - -~ c64scr { - ; ---- this block contains (character) Screen and text I/O related functions ---- - - -sub clear_screen (char: A, color: Y) -> () { - ; ---- clear the character screen with the given fill character and character color. - ; (assumes screen is at $0400, could be altered in the future with self-modifying code) - ; @todo some byte var to set the SCREEN ADDR HI BYTE - - %asm {{ - sta _loop + 1 ; self-modifying - stx c64.SCRATCH_ZP1 - ldx #0 -_loop lda #0 - sta c64.Screen,x - sta c64.Screen+$0100,x - sta c64.Screen+$0200,x - sta c64.Screen+$02e8,x - tya - sta c64.Colors,x - sta c64.Colors+$0100,x - sta c64.Colors+$0200,x - sta c64.Colors+$02e8,x - inx - bne _loop - - lda _loop+1 ; restore A and X - ldx c64.SCRATCH_ZP1 - rts - }} - -} - - -sub scroll_left_full (alsocolors: Pc) -> (A?, X?, Y?) { - ; ---- scroll the whole screen 1 character to the left - ; contents of the rightmost column are unchanged, you should clear/refill this yourself - ; Carry flag determines if screen color data must be scrolled too - %asm {{ - bcs + - jmp _scroll_screen - -+ ; scroll the color memory - ldx #0 - ldy #38 -- - .for row=0, row<=12, row+=1 - lda c64.Colors + 40*row + 1,x - sta c64.Colors + 40*row,x - .next - inx - dey - bpl - - - ldx #0 - ldy #38 -- - .for row=13, row<=24, row+=1 - lda c64.Colors + 40*row + 1,x - sta c64.Colors + 40*row,x - .next - inx - dey - bpl - - -_scroll_screen ; scroll the screen memory - ldx #0 - ldy #38 -- - .for row=0, row<=12, row+=1 - lda c64.Screen + 40*row + 1,x - sta c64.Screen + 40*row,x - .next - inx - dey - bpl - - - ldx #0 - ldy #38 -- - .for row=13, row<=24, row+=1 - lda c64.Screen + 40*row + 1,x - sta c64.Screen + 40*row,x - .next - inx - dey - bpl - - - rts - }} -} - - -sub scroll_right_full (alsocolors: Pc) -> (A?, X?) { - ; ---- scroll the whole screen 1 character to the right - ; contents of the leftmost column are unchanged, you should clear/refill this yourself - ; Carry flag determines if screen color data must be scrolled too - %asm {{ - bcs + - jmp _scroll_screen - -+ ; scroll the color memory - ldx #38 -- - .for row=0, row<=12, row+=1 - lda c64.Colors + 40*row + 0,x - sta c64.Colors + 40*row + 1,x - .next - dex - bpl - - - ldx #38 -- - .for row=13, row<=24, row+=1 - lda c64.Colors + 40*row,x - sta c64.Colors + 40*row + 1,x - .next - dex - bpl - - -_scroll_screen ; scroll the screen memory - ldx #38 -- - .for row=0, row<=12, row+=1 - lda c64.Screen + 40*row + 0,x - sta c64.Screen + 40*row + 1,x - .next - dex - bpl - - - ldx #38 -- - .for row=13, row<=24, row+=1 - lda c64.Screen + 40*row,x - sta c64.Screen + 40*row + 1,x - .next - dex - bpl - - - rts - }} -} - - -sub scroll_up_full (alsocolors: Pc) -> (A?, X?) { - ; ---- scroll the whole screen 1 character up - ; contents of the bottom row are unchanged, you should refill/clear this yourself - ; Carry flag determines if screen color data must be scrolled too - %asm {{ - bcs + - jmp _scroll_screen - -+ ; scroll the color memory - ldx #39 -- - .for row=1, row<=11, row+=1 - lda c64.Colors + 40*row,x - sta c64.Colors + 40*(row-1),x - .next - dex - bpl - - - ldx #39 -- - .for row=12, row<=24, row+=1 - lda c64.Colors + 40*row,x - sta c64.Colors + 40*(row-1),x - .next - dex - bpl - - -_scroll_screen ; scroll the screen memory - ldx #39 -- - .for row=1, row<=11, row+=1 - lda c64.Screen + 40*row,x - sta c64.Screen + 40*(row-1),x - .next - dex - bpl - - - ldx #39 -- - .for row=12, row<=24, row+=1 - lda c64.Screen + 40*row,x - sta c64.Screen + 40*(row-1),x - .next - dex - bpl - - - rts - }} -} - - -sub scroll_down_full (alsocolors: Pc) -> (A?, X?) { - ; ---- scroll the whole screen 1 character down - ; contents of the top row are unchanged, you should refill/clear this yourself - ; Carry flag determines if screen color data must be scrolled too - %asm {{ - bcs + - jmp _scroll_screen - -+ ; scroll the color memory - ldx #39 -- - .for row=23, row>=12, row-=1 - lda c64.Colors + 40*row,x - sta c64.Colors + 40*(row+1),x - .next - dex - bpl - - - ldx #39 -- - .for row=11, row>=0, row-=1 - lda c64.Colors + 40*row,x - sta c64.Colors + 40*(row+1),x - .next - dex - bpl - - -_scroll_screen ; scroll the screen memory - ldx #39 -- - .for row=23, row>=12, row-=1 - lda c64.Screen + 40*row,x - sta c64.Screen + 40*(row+1),x - .next - dex - bpl - - - ldx #39 -- - .for row=11, row>=0, row-=1 - lda c64.Screen + 40*row,x - sta c64.Screen + 40*(row+1),x - .next - dex - bpl - - - rts - }} -} - - -sub byte2decimal (ubyte: A) -> (Y, X, A) { - ; ---- A to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A) - %asm {{ - ldy #$2f - ldx #$3a - sec -- iny - sbc #100 - bcs - -- dex - adc #10 - bmi - - adc #$2f - rts - }} -} - -sub byte2hex (ubyte: A) -> (X, Y, A?) { - ; ---- A to hex string in XY (first hex char in X, second hex char in Y) - %asm {{ - pha - and #$0f - tax - ldy hex_digits,x - pla - lsr a - lsr a - lsr a - lsr a - tax - lda hex_digits,x - tax - rts - -hex_digits .str "0123456789abcdef" ; can probably be reused for other stuff as well - }} -} - - - str word2hex_output = "1234" ; 0-terminated, to make printing easier -sub word2hex (dataword: XY) -> (?) { - ; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output' - %asm {{ - stx c64.SCRATCH_ZP2 - tya - jsr byte2hex - stx word2hex_output - sty word2hex_output+1 - lda c64.SCRATCH_ZP2 - jsr byte2hex - stx word2hex_output+2 - sty word2hex_output+3 - rts - }} -} - - byte[3] word2bcd_bcdbuff = [0, 0, 0] -sub word2bcd (dataword: XY) -> (A?, X?) { - ; Convert an 16 bit binary value to BCD - ; - ; This function converts a 16 bit binary value in X/Y into a 24 bit BCD. It - ; works by transferring one bit a time from the source and adding it - ; into a BCD value that is being doubled on each iteration. As all the - ; arithmetic is being done in BCD the result is a binary to decimal - ; conversion. - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - sed ; switch to decimal mode - lda #0 ; ensure the result is clear - sta word2bcd_bcdbuff+0 - sta word2bcd_bcdbuff+1 - sta word2bcd_bcdbuff+2 - ldx #16 ; the number of source bits - -- asl c64.SCRATCH_ZP1 ; shift out one bit - rol c64.SCRATCH_ZP2 - lda word2bcd_bcdbuff+0 ; and add into result - adc word2bcd_bcdbuff+0 - sta word2bcd_bcdbuff+0 - lda word2bcd_bcdbuff+1 ; propagating any carry - adc word2bcd_bcdbuff+1 - sta word2bcd_bcdbuff+1 - lda word2bcd_bcdbuff+2 ; ... thru whole result - adc word2bcd_bcdbuff+2 - sta word2bcd_bcdbuff+2 - dex ; and repeat for next bit - bne - - cld ; back to binary - rts - }} -} - - - byte[5] word2decimal_output = 0 -sub word2decimal (dataword: XY) -> (?) { - ; ---- convert 16 bit word in X/Y into decimal string into memory 'word2decimal_output' - %asm {{ - jsr word2bcd - lda word2bcd_bcdbuff+2 - clc - adc #'0' - sta word2decimal_output - ldy #1 - lda word2bcd_bcdbuff+1 - jsr + - lda word2bcd_bcdbuff+0 - -+ pha - lsr a - lsr a - lsr a - lsr a - clc - adc #'0' - sta word2decimal_output,y - iny - pla - and #$0f - adc #'0' - sta word2decimal_output,y - iny - rts - }} -} - - -; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html - - -sub print_string (address: XY) -> (A?, Y?) { - ; ---- print null terminated string from X/Y - ; note: the compiler contains an optimization that will replace - ; a call to this subroutine with a string argument of just one char, - ; by just one call to c64.CHROUT of that single char. - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - ldy #0 -- lda (c64.SCRATCH_ZP1),y - beq + - jsr c64.CHROUT - iny - bne - -+ rts - }} -} - - -sub print_pstring (address: XY) -> (A?, X?, Y) { - ; ---- print pstring (length as first byte) from X/Y, returns str len in Y - %asm {{ - stx c64.SCRATCH_ZP1 - sty c64.SCRATCH_ZP2 - ldy #0 - lda (c64.SCRATCH_ZP1),y - beq + - tax -- iny - lda (c64.SCRATCH_ZP1),y - jsr c64.CHROUT - dex - bne - -+ rts ; output string length is in Y - }} -} - - -sub print_pimmediate () -> () { - ; ---- print pstring in memory immediately following the subroutine fast call instruction - ; note that the clobbered registers (A,X,Y) are not listed ON PURPOSE - %asm {{ - tsx - lda $102,x - tay ; put high byte in y - lda $101,x - tax ; and low byte in x. - inx - bne + - iny -+ jsr print_pstring ; print string in XY, returns string length in y. - tya - tsx - clc - adc $101,x ; add content of 1st (length) byte to return addr. - bcc + ; if that made the low byte roll over to 00, - inc $102,x ; then increment the high byte too. -+ clc - adc #1 ; now add 1 for the length byte itself. - sta $101,x - bne + ; if that made it (the low byte) roll over to 00, - inc $102,x ; increment the high byte of the return addr too. -+ rts - }} -} - - -sub print_byte_decimal0 (ubyte: A) -> (?) { - ; ---- print the byte in A in decimal form, with left padding 0s (3 positions total) - %asm {{ - jsr byte2decimal - pha - tya - jsr c64.CHROUT - txa - jsr c64.CHROUT - pla - jmp c64.CHROUT - }} -} - - -sub print_byte_decimal (ubyte: A) -> (?) { - ; ---- print the byte in A in decimal form, without left padding 0s - %asm {{ - jsr byte2decimal - pha - cpy #'0' - bne _print_hundreds - cpx #'0' - bne _print_tens - pla - jmp c64.CHROUT -_print_hundreds tya - jsr c64.CHROUT -_print_tens txa - jsr c64.CHROUT - pla - jmp c64.CHROUT - }} -} - - -sub print_byte_hex (prefix: Pc, ubyte: A) -> (?) { - ; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) - %asm {{ - bcc + - pha - lda #'$' - jsr c64.CHROUT - pla -+ jsr byte2hex - txa - jsr c64.CHROUT - tya - jmp c64.CHROUT - }} -} - - -sub print_word_hex (prefix: Pc, dataword: XY) -> (?) { - ; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits) - ; (if Carry is set, a radix prefix '$' is printed as well) - %asm {{ - stx c64.SCRATCH_ZP1 - tya - jsr print_byte_hex - lda c64.SCRATCH_ZP1 - clc - jmp print_byte_hex - }} -} - - -sub print_word_decimal0 (dataword: XY) -> (?) { - ; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total) - %asm {{ - jsr word2decimal - lda word2decimal_output - jsr c64.CHROUT - lda word2decimal_output+1 - jsr c64.CHROUT - lda word2decimal_output+2 - jsr c64.CHROUT - lda word2decimal_output+3 - jsr c64.CHROUT - lda word2decimal_output+4 - jmp c64.CHROUT - }} -} - - -sub print_word_decimal (dataword: XY) -> (A?, X?, Y?) { - ; ---- print the word in X/Y in decimal form, without left padding 0s - %asm {{ - jsr word2decimal - ldy #0 - lda word2decimal_output - cmp #'0' - bne _pr_decimal - iny - lda word2decimal_output+1 - cmp #'0' - bne _pr_decimal - iny - lda word2decimal_output+2 - cmp #'0' - bne _pr_decimal - iny - lda word2decimal_output+3 - cmp #'0' - bne _pr_decimal - iny - -_pr_decimal - lda word2decimal_output,y - jsr c64.CHROUT - iny - cpy #5 - bcc _pr_decimal - rts - }} -} - - -sub input_chars (buffer: AX) -> (A?, Y) { - ; ---- Input a string (max. 80 chars) from the keyboard. - ; It assumes the keyboard is selected as I/O channel!! - - %asm {{ - sta c64.SCRATCH_ZP1 - stx c64.SCRATCH_ZP2 - ldy #0 ; char counter = 0 -- jsr c64.CHRIN - cmp #$0d ; return (ascii 13) pressed? - beq + ; yes, end. - sta (c64.SCRATCH_ZP1),y ; else store char in buffer - iny - bne - -+ lda #0 - sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte - rts - - }} -} - -} ; ---- end block c64scr - - - -;sub memcopy_basic () -> (?) { -; ; ---- copy a memory block by using a BASIC ROM routine -; ; it calls a function from the basic interpreter, so: -; ; - BASIC ROM must be banked in -; ; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O) -; ; - the target block must be writable (so no RAM hidden under I/O) -; ; higher addresses are copied first, so: -; ; - moving data to higher addresses works even if areas overlap -; ; - moving data to lower addresses only works if areas do not overlap -; %asm {{ -; lda #src_start -; sta $5f -; stx $60 -; lda #src_end -; sta $5a -; stx $5b -; lda #<(target_start + src_end - src_start) -; ldx #>(target_start + src_end - src_start) -; sta $58 -; stx $59 -; jmp $a3bf -; } -;} - -; macro version of the above memcopy_basic routine: -; MACRO PARAMS src_start, src_end, target_start -; lda #src_start -; sta $5f -; stx $60 -; lda #src_end -; sta $5a -; stx $5b -; lda #<(target_start + src_end - src_start) -; ldx #>(target_start + src_end - src_start) -; sta $58 -; stx $59 -; jsr $a3bf - diff --git a/prog8lib/c64lib_old.p8 b/prog8lib/c64lib_old.p8 new file mode 100644 index 000000000..822b74573 --- /dev/null +++ b/prog8lib/c64lib_old.p8 @@ -0,0 +1,1085 @@ +; Prog8 definitions for the Commodore-64 +; Including memory registers, I/O registers, Basic and Kernal subroutines, utility subroutines. +; +; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 +; ; +; indent format: TABS, size=8 + +%option enable_floats + + +~ c64 { + memory byte SCRATCH_ZP1 = $02 ; scratch register #1 in ZP + memory byte SCRATCH_ZP2 = $03 ; scratch register #2 in ZP + memory word SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) + memory word SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) + + + memory byte TIME_HI = $a0 ; software jiffy clock, hi byte + memory byte TIME_MID = $a1 ; .. mid byte + memory byte TIME_LO = $a2 ; .. lo byte. Updated by IRQ every 1/60 sec + memory byte STKEY = $91 ; various keyboard statuses (updated by IRQ) + memory byte SFDX = $cb ; current key pressed (matrix value) (updated by IRQ) + + memory byte COLOR = $0286 ; cursor color + memory byte HIBASE = $0288 ; screen base address / 256 (hi-byte of screen memory address) + memory word CINV = $0314 ; IRQ vector + memory word NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in + memory word RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in + memory word IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in + + memory byte[40, 25] Screen = $0400 ; default character screen matrix + memory byte[40, 25] Colors = $d800 ; character screen colors + + +; ---- VIC-II registers ---- + + memory byte SP0X = $d000 + memory byte SP0Y = $d001 + memory byte SP1X = $d002 + memory byte SP1Y = $d003 + memory byte SP2X = $d004 + memory byte SP2Y = $d005 + memory byte SP3X = $d006 + memory byte SP3Y = $d007 + memory byte SP4X = $d008 + memory byte SP4Y = $d009 + memory byte SP5X = $d00a + memory byte SP5Y = $d00b + memory byte SP6X = $d00c + memory byte SP6Y = $d00d + memory byte SP7X = $d00e + memory byte SP7Y = $d00f + + memory byte MSIGX = $d010 + memory byte SCROLY = $d011 + memory byte RASTER = $d012 + memory byte LPENX = $d013 + memory byte LPENY = $d014 + memory byte SPENA = $d015 + memory byte SCROLX = $d016 + memory byte YXPAND = $d017 + memory byte VMCSB = $d018 + memory byte VICIRQ = $d019 + memory byte IREQMASK = $d01a + memory byte SPBGPR = $d01b + memory byte SPMC = $d01c + memory byte XXPAND = $d01d + memory byte SPSPCL = $d01e + memory byte SPBGCL = $d01f + + memory byte EXTCOL = $d020 ; border color + memory byte BGCOL0 = $d021 ; screen color + memory byte BGCOL1 = $d022 + memory byte BGCOL2 = $d023 + memory byte BGCOL4 = $d024 + memory byte SPMC0 = $d025 + memory byte SPMC1 = $d026 + memory byte SP0COL = $d027 + memory byte SP1COL = $d028 + memory byte SP2COL = $d029 + memory byte SP3COL = $d02a + memory byte SP4COL = $d02b + memory byte SP5COL = $d02c + memory byte SP6COL = $d02d + memory byte SP7COL = $d02e + +; ---- end of VIC-II registers ---- + +; ---- C64 basic and kernal ROM float constants and functions ---- + + ; note: the fac1 and fac2 are working registers and take 6 bytes each, + ; floats in memory (and rom) are stored in 5-byte MFLPT packed format. + + ; constants in five-byte "mflpt" format in the BASIC ROM + memory float FL_PIVAL = $aea8 ; 3.1415926... + memory float FL_N32768 = $b1a5 ; -32768 + memory float FL_FONE = $b9bc ; 1 + memory float FL_SQRHLF = $b9d6 ; SQR(2) / 2 + memory float FL_SQRTWO = $b9db ; SQR(2) + memory float FL_NEGHLF = $b9e0 ; -.5 + memory float FL_LOG2 = $b9e5 ; LOG(2) + memory float FL_TENC = $baf9 ; 10 + memory float FL_NZMIL = $bdbd ; 1e9 (1 billion) + memory float FL_FHALF = $bf11 ; .5 + memory float FL_LOGEB2 = $bfbf ; 1 / LOG(2) + memory float FL_PIHALF = $e2e0 ; PI / 2 + memory float FL_TWOPI = $e2e5 ; 2 * PI + memory float FL_FR4 = $e2ea ; .25 + + +; note: fac1/2 might get clobbered even if not mentioned in the function's name. +; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. + +; checked functions below: +sub MOVFM (mflpt: AY) -> (A?, Y?) = $bba2 ; load mflpt value from memory in A/Y into fac1 +sub FREADMEM () -> (A?, Y?) = $bba6 ; load mflpt value from memory in $22/$23 into fac1 +sub CONUPK (mflpt: AY) -> (A?, Y?) = $ba8c ; load mflpt value from memory in A/Y into fac2 +sub FAREADMEM () -> (A?, Y?) = $ba90 ; load mflpt value from memory in $22/$23 into fac2 +sub MOVFA () -> (A?, X?) = $bbfc ; copy fac2 to fac1 +sub MOVAF () -> (A?, X?) = $bc0c ; copy fac1 to fac2 (rounded) +sub MOVEF () -> (A?, X?) = $bc0f ; copy fac1 to fac2 +sub FTOMEMXY (mflpt: XY) -> (A?, Y?) = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt + +; fac1-> signed word in Y/A (might throw ILLEGAL QUANTITY) +; (use c64flt.FTOSWRDAY to get A/Y output; lo/hi switched to normal order) +sub FTOSWORDYA () -> (Y, A, X?) = $b1aa + +; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) +; (use c64flt.GETADRAY to get A/Y output; lo/hi switched to normal order) +sub GETADR () -> (Y, A, X?) = $b7f7 + +sub QINT () -> (?) = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST. +sub AYINT () -> (?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) + +; signed word in Y/A -> float in fac1 +; (use c64flt.GIVAYFAY to use A/Y input; lo/hi switched to normal order) +; there is also c64flt.GIVUAYF - unsigned word in A/Y (lo/hi) to fac1 +; there is also c64flt.FREADS32 that reads from 98-101 ($62-$65) MSB FIRST +; there is also c64flt.FREADUS32 that reads from 98-101 ($62-$65) MSB FIRST +; there is also c64flt.FREADS24AXY that reads signed int24 into fac1 from A/X/Y (lo/mid/hi bytes) +sub GIVAYF (lo: Y, hi: A) -> (?) = $b391 + +sub FREADUY (ubyte: Y) -> (?) = $b3a2 ; 8 bit unsigned Y -> float in fac1 +sub FREADSA (sbyte: A) -> (?) = $bc3c ; 8 bit signed A -> float in fac1 +sub FREADSTR (length: A) -> (?) = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length +sub FPRINTLN () -> (?) = $aabc ; print string of fac1, on one line (= with newline) +sub FOUT () -> (AY, X?) = $bddd ; fac1 -> string, address returned in AY ($0100) + +sub FADDH () -> (?) = $b849 ; fac1 += 0.5, for rounding- call this before INT +sub MUL10 () -> (?) = $bae2 ; fac1 *= 10 +sub DIV10 () -> (?) = $bafe ; fac1 /= 10 , CAUTION: result is always positive! +sub FCOMP (mflpt: AY) -> (A, X?, Y?) = $bc5b ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than + +sub FADDT () -> (?) = $b86a ; fac1 += fac2 +sub FADD (mflpt: AY) -> (?) = $b867 ; fac1 += mflpt value from A/Y +sub FSUBT () -> (?) = $b853 ; fac1 = fac2-fac1 mind the order of the operands +sub FSUB (mflpt: AY) -> (?) = $b850 ; fac1 = mflpt from A/Y - fac1 +sub FMULTT () -> (?) = $ba2b ; fac1 *= fac2 +sub FMULT (mflpt: AY) -> (?) = $ba28 ; fac1 *= mflpt value from A/Y +sub FDIVT () -> (?) = $bb12 ; fac1 = fac2/fac1 mind the order of the operands +sub FDIV (mflpt: AY) -> (?) = $bb0f ; fac1 = mflpt in A/Y / fac1 +sub FPWRT () -> (?) = $bf7b ; fac1 = fac2 ** fac1 +sub FPWR (mflpt: AY) -> (?) = $bf78 ; fac1 = fac2 ** mflpt from A/Y + +sub NOTOP () -> (?) = $aed4 ; fac1 = NOT(fac1) +sub INT () -> (?) = $bccc ; INT() truncates, use FADDH first to round instead of trunc +sub LOG () -> (?) = $b9ea ; fac1 = LN(fac1) (natural log) +sub SGN () -> (?) = $bc39 ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +sub SIGN () -> (A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive +sub ABS () -> () = $bc58 ; fac1 = ABS(fac1) +sub SQR () -> (?) = $bf71 ; fac1 = SQRT(fac1) +sub EXP () -> (?) = $bfed ; fac1 = EXP(fac1) (e ** fac1) +sub NEGOP () -> (A?) = $bfb4 ; switch the sign of fac1 +sub RND () -> (?) = $e097 ; fac1 = RND() (use RNDA instead) +sub RNDA (acc: A) -> (?) = $e09a ; fac1 = RND(A) +sub COS () -> (?) = $e264 ; fac1 = COS(fac1) +sub SIN () -> (?) = $e26b ; fac1 = SIN(fac1) +sub TAN () -> (?) = $e2b4 ; fac1 = TAN(fac1) +sub ATN () -> (?) = $e30e ; fac1 = ATN(fac1) + + +; ---- C64 basic routines ---- + +sub CLEARSCR () -> (?) = $E544 ; clear the screen +sub HOMECRSR () -> (?) = $E566 ; cursor to top left of screen + + +; ---- end of C64 basic routines ---- + + + +; ---- C64 kernal routines ---- + +sub IRQDFRT () -> (?) = $EA31 ; default IRQ routine +sub IRQDFEND () -> (?) = $EA81 ; default IRQ end/cleanup +sub CINT () -> (?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip +sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices (CIA, SID, IRQ) +sub RAMTAS () -> (?) = $FF87 ; initialize RAM, tape buffer, screen +sub RESTOR () -> (?) = $FF8A ; restore default I/O vectors +sub VECTOR (dir: Pc, userptr: XY) -> (A?, Y?) = $FF8D ; read/set I/O vector table +sub SETMSG (value: A) -> () = $FF90 ; set Kernal message control flag +sub SECOND (address: A) -> (A?) = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN +sub TKSA (address: A) -> (A?) = $FF96 ; (alias: TALKSA) send secondary address after TALK +sub MEMTOP (dir: Pc, address: XY) -> (XY) = $FF99 ; read/set top of memory pointer +sub MEMBOT (dir: Pc, address: XY) -> (XY) = $FF9C ; read/set bottom of memory pointer +sub SCNKEY () -> (?) = $FF9F ; scan the keyboard +sub SETTMO (timeout: A) -> () = $FFA2 ; set time-out flag for IEEE bus +sub ACPTR () -> (A) = $FFA5 ; (alias: IECIN) input byte from serial bus +sub CIOUT (databyte: A) -> () = $FFA8 ; (alias: IECOUT) output byte to serial bus +sub UNTLK () -> (A?) = $FFAB ; command serial bus device to UNTALK +sub UNLSN () -> (A?) = $FFAE ; command serial bus device to UNLISTEN +sub LISTEN (device: A) -> (A?) = $FFB1 ; command serial bus device to LISTEN +sub TALK (device: A) -> (A?) = $FFB4 ; command serial bus device to TALK +sub READST () -> (A) = $FFB7 ; read I/O status word +sub SETLFS (logical: A, device: X, address: Y) -> () = $FFBA ; set logical file parameters +sub SETNAM (namelen: A, filename: XY) -> () = $FFBD ; set filename parameters +sub OPEN () -> (?) = $FFC0 ; (via 794 ($31A)) open a logical file +sub CLOSE (logical: A) -> (?) = $FFC3 ; (via 796 ($31C)) close a logical file +sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel +sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel +sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices +sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. +sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character +sub LOAD (verify: A, address: XY) -> (Pc, A, X, Y) = $FFD5 ; (via 816 ($330)) load from device +sub SAVE (zp_startaddr: A, endaddr: XY) -> (Pc, A) = $FFD8 ; (via 818 ($332)) save to a device +sub SETTIM (low: A, middle: X, high: Y) -> () = $FFDB ; set the software clock +sub RDTIM () -> (A, X, Y) = $FFDE ; read the software clock +sub STOP () -> (Pz, Pc, A?, X?) = $FFE1 ; (via 808 ($328)) check the STOP key +sub GETIN () -> (A, X?, Y?) = $FFE4 ; (via 810 ($32A)) get a character +sub CLALL () -> (A?, X?) = $FFE7 ; (via 812 ($32C)) close all files +sub UDTIM () -> (A?, X?) = $FFEA ; update the software clock +sub SCREEN () -> (X, Y) = $FFED ; read number of screen rows and columns +sub PLOT (dir: Pc, col: Y, row: X) -> (X, Y) = $FFF0 ; read/set position of cursor on screen +sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices + +; ---- end of C64 kernal routines ---- + + + +; ----- utility functions ---- + +sub init_system () -> (?) { + ; ---- initializes the machine to a sane starting state + ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, + ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. + ; Also a different color scheme is chosen to identify ourselves a little. + %asm {{ + sei + cld + lda #%00101111 + sta $00 + lda #%00100111 + sta $01 + jsr c64.IOINIT + jsr c64.RESTOR + jsr c64.CINT + lda #6 + sta c64.EXTCOL + lda #7 + sta c64.COLOR + lda #0 + sta c64.BGCOL0 + tax + tay + clc + clv + cli + rts + }} +} + +} ; ------ end of block c64 + + +~ c64flt { + ; ---- this block contains C-64 floating point related functions ---- + + +sub FREADS32 () -> (?) { + ; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST) + %asm {{ + lda $62 + eor #$ff + asl a + lda #0 + ldx #$a0 + jmp $bc4f ; internal BASIC routine + }} +} + +sub FREADUS32 () -> (?) { + ; ---- fac1 = uint32 from $62-$65 big endian (MSB FIRST) + %asm {{ + sec + lda #0 + ldx #$a0 + jmp $bc4f ; internal BASIC routine + }} +} + +sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (?) { + ; ---- fac1 = signed int24 (A/X/Y contain lo/mid/hi bytes) + ; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead. + %asm {{ + sty $62 + stx $63 + sta $64 + lda $62 + eor #$FF + asl a + lda #0 + sta $65 + ldx #$98 + jmp $bc4f ; internal BASIC routine + }} +} + +sub GIVUAYF (uword: AY) -> (?) { + ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 + %asm {{ + sty $62 + sta $63 + ldx #$90 + sec + jmp $bc49 ; internal BASIC routine + }} +} + +sub GIVAYFAY (sword: AY) -> (?) { + ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 + %asm {{ + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + jmp c64.GIVAYF ; this uses the inverse order, Y/A + }} +} + +sub FTOSWRDAY () -> (AY, X?) { + ; ---- fac1 to signed word in A/Y + %asm {{ + jsr c64.FTOSWORDYA ; note the inverse Y/A order + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + rts + }} +} + +sub GETADRAY () -> (AY, X?) { + ; ---- fac1 to unsigned word in A/Y + %asm {{ + jsr c64.GETADR ; this uses the inverse order, Y/A + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + rts + }} +} + + +sub copy_mflt (source: XY) -> (A?, Y?) { + ; ---- copy a 5 byte MFLT floating point variable to another place + ; input: X/Y = source address, c64.SCRATCH_ZPWORD1 = destination address + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZPWORD1+1 + ldy #0 + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + ldy c64.SCRATCH_ZPWORD1+1 + rts + }} +} + +sub float_add_one (mflt: XY) -> (?) { + ; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + txa + jsr c64.MOVFM ; fac1 = float XY + lda #c64.FL_FONE + jsr c64.FADD ; fac1 += 1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +sub float_sub_one (mflt: XY) -> (?) { + ; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + lda #c64.FL_FONE + jsr c64.MOVFM ; fac1 = 1 + txa + ldy c64.SCRATCH_ZP2 + jsr c64.FSUB ; fac1 = float XY - 1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +sub float_add_SW1_to_XY (mflt: XY) -> (?) { + ; ---- add MFLT pointed to by SCRATCH_ZPWORD1 to the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + txa + jsr c64.MOVFM ; fac1 = float XY + lda c64.SCRATCH_ZPWORD1 + ldy c64.SCRATCH_ZPWORD1+1 + jsr c64.FADD ; fac1 += SCRATCH_ZPWORD1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +sub float_sub_SW1_from_XY (mflt: XY) -> (?) { + ; ---- subtract MFLT pointed to by SCRATCH_ZPWORD1 from the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + lda c64.SCRATCH_ZPWORD1 + ldy c64.SCRATCH_ZPWORD1+1 + jsr c64.MOVFM ; fac1 = SCRATCH_ZPWORD1 + txa + ldy c64.SCRATCH_ZP2 + jsr c64.FSUB ; fac1 = float XY - SCRATCH_ZPWORD1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +} ; ------ end of block c64flt + + + +~ c64scr { + ; ---- this block contains (character) Screen and text I/O related functions ---- + + +sub clear_screen (char: A, color: Y) -> () { + ; ---- clear the character screen with the given fill character and character color. + ; (assumes screen is at $0400, could be altered in the future with self-modifying code) + ; @todo some byte var to set the SCREEN ADDR HI BYTE + + %asm {{ + sta _loop + 1 ; self-modifying + stx c64.SCRATCH_ZP1 + ldx #0 +_loop lda #0 + sta c64.Screen,x + sta c64.Screen+$0100,x + sta c64.Screen+$0200,x + sta c64.Screen+$02e8,x + tya + sta c64.Colors,x + sta c64.Colors+$0100,x + sta c64.Colors+$0200,x + sta c64.Colors+$02e8,x + inx + bne _loop + + lda _loop+1 ; restore A and X + ldx c64.SCRATCH_ZP1 + rts + }} + +} + + +sub scroll_left_full (alsocolors: Pc) -> (A?, X?, Y?) { + ; ---- scroll the whole screen 1 character to the left + ; contents of the rightmost column are unchanged, you should clear/refill this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #0 + ldy #38 +- + .for row=0, row<=12, row+=1 + lda c64.Colors + 40*row + 1,x + sta c64.Colors + 40*row,x + .next + inx + dey + bpl - + + ldx #0 + ldy #38 +- + .for row=13, row<=24, row+=1 + lda c64.Colors + 40*row + 1,x + sta c64.Colors + 40*row,x + .next + inx + dey + bpl - + +_scroll_screen ; scroll the screen memory + ldx #0 + ldy #38 +- + .for row=0, row<=12, row+=1 + lda c64.Screen + 40*row + 1,x + sta c64.Screen + 40*row,x + .next + inx + dey + bpl - + + ldx #0 + ldy #38 +- + .for row=13, row<=24, row+=1 + lda c64.Screen + 40*row + 1,x + sta c64.Screen + 40*row,x + .next + inx + dey + bpl - + + rts + }} +} + + +sub scroll_right_full (alsocolors: Pc) -> (A?, X?) { + ; ---- scroll the whole screen 1 character to the right + ; contents of the leftmost column are unchanged, you should clear/refill this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #38 +- + .for row=0, row<=12, row+=1 + lda c64.Colors + 40*row + 0,x + sta c64.Colors + 40*row + 1,x + .next + dex + bpl - + + ldx #38 +- + .for row=13, row<=24, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*row + 1,x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #38 +- + .for row=0, row<=12, row+=1 + lda c64.Screen + 40*row + 0,x + sta c64.Screen + 40*row + 1,x + .next + dex + bpl - + + ldx #38 +- + .for row=13, row<=24, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*row + 1,x + .next + dex + bpl - + + rts + }} +} + + +sub scroll_up_full (alsocolors: Pc) -> (A?, X?) { + ; ---- scroll the whole screen 1 character up + ; contents of the bottom row are unchanged, you should refill/clear this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #39 +- + .for row=1, row<=11, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row-1),x + .next + dex + bpl - + + ldx #39 +- + .for row=12, row<=24, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row-1),x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #39 +- + .for row=1, row<=11, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row-1),x + .next + dex + bpl - + + ldx #39 +- + .for row=12, row<=24, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row-1),x + .next + dex + bpl - + + rts + }} +} + + +sub scroll_down_full (alsocolors: Pc) -> (A?, X?) { + ; ---- scroll the whole screen 1 character down + ; contents of the top row are unchanged, you should refill/clear this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #39 +- + .for row=23, row>=12, row-=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row+1),x + .next + dex + bpl - + + ldx #39 +- + .for row=11, row>=0, row-=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row+1),x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #39 +- + .for row=23, row>=12, row-=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row+1),x + .next + dex + bpl - + + ldx #39 +- + .for row=11, row>=0, row-=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row+1),x + .next + dex + bpl - + + rts + }} +} + + +sub byte2decimal (ubyte: A) -> (Y, X, A) { + ; ---- A to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A) + %asm {{ + ldy #$2f + ldx #$3a + sec +- iny + sbc #100 + bcs - +- dex + adc #10 + bmi - + adc #$2f + rts + }} +} + +sub byte2hex (ubyte: A) -> (X, Y, A?) { + ; ---- A to hex string in XY (first hex char in X, second hex char in Y) + %asm {{ + pha + and #$0f + tax + ldy hex_digits,x + pla + lsr a + lsr a + lsr a + lsr a + tax + lda hex_digits,x + tax + rts + +hex_digits .str "0123456789abcdef" ; can probably be reused for other stuff as well + }} +} + + + str word2hex_output = "1234" ; 0-terminated, to make printing easier +sub word2hex (dataword: XY) -> (?) { + ; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output' + %asm {{ + stx c64.SCRATCH_ZP2 + tya + jsr byte2hex + stx word2hex_output + sty word2hex_output+1 + lda c64.SCRATCH_ZP2 + jsr byte2hex + stx word2hex_output+2 + sty word2hex_output+3 + rts + }} +} + + byte[3] word2bcd_bcdbuff = [0, 0, 0] +sub word2bcd (dataword: XY) -> (A?, X?) { + ; Convert an 16 bit binary value to BCD + ; + ; This function converts a 16 bit binary value in X/Y into a 24 bit BCD. It + ; works by transferring one bit a time from the source and adding it + ; into a BCD value that is being doubled on each iteration. As all the + ; arithmetic is being done in BCD the result is a binary to decimal + ; conversion. + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + sed ; switch to decimal mode + lda #0 ; ensure the result is clear + sta word2bcd_bcdbuff+0 + sta word2bcd_bcdbuff+1 + sta word2bcd_bcdbuff+2 + ldx #16 ; the number of source bits + +- asl c64.SCRATCH_ZP1 ; shift out one bit + rol c64.SCRATCH_ZP2 + lda word2bcd_bcdbuff+0 ; and add into result + adc word2bcd_bcdbuff+0 + sta word2bcd_bcdbuff+0 + lda word2bcd_bcdbuff+1 ; propagating any carry + adc word2bcd_bcdbuff+1 + sta word2bcd_bcdbuff+1 + lda word2bcd_bcdbuff+2 ; ... thru whole result + adc word2bcd_bcdbuff+2 + sta word2bcd_bcdbuff+2 + dex ; and repeat for next bit + bne - + cld ; back to binary + rts + }} +} + + + byte[5] word2decimal_output = 0 +sub word2decimal (dataword: XY) -> (?) { + ; ---- convert 16 bit word in X/Y into decimal string into memory 'word2decimal_output' + %asm {{ + jsr word2bcd + lda word2bcd_bcdbuff+2 + clc + adc #'0' + sta word2decimal_output + ldy #1 + lda word2bcd_bcdbuff+1 + jsr + + lda word2bcd_bcdbuff+0 + ++ pha + lsr a + lsr a + lsr a + lsr a + clc + adc #'0' + sta word2decimal_output,y + iny + pla + and #$0f + adc #'0' + sta word2decimal_output,y + iny + rts + }} +} + + +; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html + + +sub print_string (address: XY) -> (A?, Y?) { + ; ---- print null terminated string from X/Y + ; note: the compiler contains an optimization that will replace + ; a call to this subroutine with a string argument of just one char, + ; by just one call to c64.CHROUT of that single char. + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + ldy #0 +- lda (c64.SCRATCH_ZP1),y + beq + + jsr c64.CHROUT + iny + bne - ++ rts + }} +} + + +sub print_pstring (address: XY) -> (A?, X?, Y) { + ; ---- print pstring (length as first byte) from X/Y, returns str len in Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + ldy #0 + lda (c64.SCRATCH_ZP1),y + beq + + tax +- iny + lda (c64.SCRATCH_ZP1),y + jsr c64.CHROUT + dex + bne - ++ rts ; output string length is in Y + }} +} + + +sub print_pimmediate () -> () { + ; ---- print pstring in memory immediately following the subroutine fast call instruction + ; note that the clobbered registers (A,X,Y) are not listed ON PURPOSE + %asm {{ + tsx + lda $102,x + tay ; put high byte in y + lda $101,x + tax ; and low byte in x. + inx + bne + + iny ++ jsr print_pstring ; print string in XY, returns string length in y. + tya + tsx + clc + adc $101,x ; add content of 1st (length) byte to return addr. + bcc + ; if that made the low byte roll over to 00, + inc $102,x ; then increment the high byte too. ++ clc + adc #1 ; now add 1 for the length byte itself. + sta $101,x + bne + ; if that made it (the low byte) roll over to 00, + inc $102,x ; increment the high byte of the return addr too. ++ rts + }} +} + + +sub print_byte_decimal0 (ubyte: A) -> (?) { + ; ---- print the byte in A in decimal form, with left padding 0s (3 positions total) + %asm {{ + jsr byte2decimal + pha + tya + jsr c64.CHROUT + txa + jsr c64.CHROUT + pla + jmp c64.CHROUT + }} +} + + +sub print_byte_decimal (ubyte: A) -> (?) { + ; ---- print the byte in A in decimal form, without left padding 0s + %asm {{ + jsr byte2decimal + pha + cpy #'0' + bne _print_hundreds + cpx #'0' + bne _print_tens + pla + jmp c64.CHROUT +_print_hundreds tya + jsr c64.CHROUT +_print_tens txa + jsr c64.CHROUT + pla + jmp c64.CHROUT + }} +} + + +sub print_byte_hex (prefix: Pc, ubyte: A) -> (?) { + ; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) + %asm {{ + bcc + + pha + lda #'$' + jsr c64.CHROUT + pla ++ jsr byte2hex + txa + jsr c64.CHROUT + tya + jmp c64.CHROUT + }} +} + + +sub print_word_hex (prefix: Pc, dataword: XY) -> (?) { + ; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits) + ; (if Carry is set, a radix prefix '$' is printed as well) + %asm {{ + stx c64.SCRATCH_ZP1 + tya + jsr print_byte_hex + lda c64.SCRATCH_ZP1 + clc + jmp print_byte_hex + }} +} + + +sub print_word_decimal0 (dataword: XY) -> (?) { + ; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total) + %asm {{ + jsr word2decimal + lda word2decimal_output + jsr c64.CHROUT + lda word2decimal_output+1 + jsr c64.CHROUT + lda word2decimal_output+2 + jsr c64.CHROUT + lda word2decimal_output+3 + jsr c64.CHROUT + lda word2decimal_output+4 + jmp c64.CHROUT + }} +} + + +sub print_word_decimal (dataword: XY) -> (A?, X?, Y?) { + ; ---- print the word in X/Y in decimal form, without left padding 0s + %asm {{ + jsr word2decimal + ldy #0 + lda word2decimal_output + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+1 + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+2 + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+3 + cmp #'0' + bne _pr_decimal + iny + +_pr_decimal + lda word2decimal_output,y + jsr c64.CHROUT + iny + cpy #5 + bcc _pr_decimal + rts + }} +} + + +sub input_chars (buffer: AX) -> (A?, Y) { + ; ---- Input a string (max. 80 chars) from the keyboard. + ; It assumes the keyboard is selected as I/O channel!! + + %asm {{ + sta c64.SCRATCH_ZP1 + stx c64.SCRATCH_ZP2 + ldy #0 ; char counter = 0 +- jsr c64.CHRIN + cmp #$0d ; return (ascii 13) pressed? + beq + ; yes, end. + sta (c64.SCRATCH_ZP1),y ; else store char in buffer + iny + bne - ++ lda #0 + sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte + rts + + }} +} + +} ; ---- end block c64scr + + + +;sub memcopy_basic () -> (?) { +; ; ---- copy a memory block by using a BASIC ROM routine +; ; it calls a function from the basic interpreter, so: +; ; - BASIC ROM must be banked in +; ; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O) +; ; - the target block must be writable (so no RAM hidden under I/O) +; ; higher addresses are copied first, so: +; ; - moving data to higher addresses works even if areas overlap +; ; - moving data to lower addresses only works if areas do not overlap +; %asm {{ +; lda #src_start +; sta $5f +; stx $60 +; lda #src_end +; sta $5a +; stx $5b +; lda #<(target_start + src_end - src_start) +; ldx #>(target_start + src_end - src_start) +; sta $58 +; stx $59 +; jmp $a3bf +; } +;} + +; macro version of the above memcopy_basic routine: +; MACRO PARAMS src_start, src_end, target_start +; lda #src_start +; sta $5f +; stx $60 +; lda #src_end +; sta $5a +; stx $5b +; lda #<(target_start + src_end - src_start) +; ldx #>(target_start + src_end - src_start) +; sta $58 +; stx $59 +; jsr $a3bf + diff --git a/prog8lib/c64utils.p8 b/prog8lib/c64utils.p8 new file mode 100644 index 000000000..d2a43e71a --- /dev/null +++ b/prog8lib/c64utils.p8 @@ -0,0 +1,860 @@ +; Prog8 definitions for the Commodore-64 +; These are the utility subroutines. +; +; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 +; +; indent format: TABS, size=8 + + +%import c64lib + + +~ c64utils { + +; ----- utility functions ---- + +asmsub init_system () -> clobbers(A,X,Y) -> () { + ; ---- initializes the machine to a sane starting state + ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, + ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. + ; Also a different color scheme is chosen to identify ourselves a little. + %asm {{ + sei + cld + lda #%00101111 + sta $00 + lda #%00100111 + sta $01 + jsr c64.IOINIT + jsr c64.RESTOR + jsr c64.CINT + lda #6 + sta c64.EXTCOL + lda #7 + sta c64.COLOR + lda #0 + sta c64.BGCOL0 + tax + tay + clc + clv + cli + rts + }} +} + +asmsub byte2decimal (ubyte: byte @ A) -> clobbers() -> (byte @ Y, byte @ X, byte @ A) { + ; ---- A to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A) + %asm {{ + ldy #$2f + ldx #$3a + sec +- iny + sbc #100 + bcs - +- dex + adc #10 + bmi - + adc #$2f + rts + }} +} + +asmsub byte2hex (ubyte: byte @ A) -> clobbers(A) -> (byte @ X, byte @ Y) { + ; ---- A to hex string in XY (first hex char in X, second hex char in Y) + %asm {{ + pha + and #$0f + tax + ldy hex_digits,x + pla + lsr a + lsr a + lsr a + lsr a + tax + lda hex_digits,x + tax + rts + +hex_digits .str "0123456789abcdef" ; can probably be reused for other stuff as well + }} +} + + + str word2hex_output = "1234" ; 0-terminated, to make printing easier +asmsub word2hex (dataword: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output' + %asm {{ + stx c64.SCRATCH_ZP2 + tya + jsr byte2hex + stx word2hex_output + sty word2hex_output+1 + lda c64.SCRATCH_ZP2 + jsr byte2hex + stx word2hex_output+2 + sty word2hex_output+3 + rts + }} +} + + byte[3] word2bcd_bcdbuff = [0, 0, 0] +asmsub word2bcd (dataword: word @ XY) -> clobbers(A,X) -> () { + ; Convert an 16 bit binary value to BCD + ; + ; This function converts a 16 bit binary value in X/Y into a 24 bit BCD. It + ; works by transferring one bit a time from the source and adding it + ; into a BCD value that is being doubled on each iteration. As all the + ; arithmetic is being done in BCD the result is a binary to decimal + ; conversion. + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + sed ; switch to decimal mode + lda #0 ; ensure the result is clear + sta word2bcd_bcdbuff+0 + sta word2bcd_bcdbuff+1 + sta word2bcd_bcdbuff+2 + ldx #16 ; the number of source bits + +- asl c64.SCRATCH_ZP1 ; shift out one bit + rol c64.SCRATCH_ZP2 + lda word2bcd_bcdbuff+0 ; and add into result + adc word2bcd_bcdbuff+0 + sta word2bcd_bcdbuff+0 + lda word2bcd_bcdbuff+1 ; propagating any carry + adc word2bcd_bcdbuff+1 + sta word2bcd_bcdbuff+1 + lda word2bcd_bcdbuff+2 ; ... thru whole result + adc word2bcd_bcdbuff+2 + sta word2bcd_bcdbuff+2 + dex ; and repeat for next bit + bne - + cld ; back to binary + rts + }} +} + + + byte[5] word2decimal_output = 0 +asmsub word2decimal (dataword: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- convert 16 bit word in X/Y into decimal string into memory 'word2decimal_output' + %asm {{ + jsr word2bcd + lda word2bcd_bcdbuff+2 + clc + adc #'0' + sta word2decimal_output + ldy #1 + lda word2bcd_bcdbuff+1 + jsr + + lda word2bcd_bcdbuff+0 + ++ pha + lsr a + lsr a + lsr a + lsr a + clc + adc #'0' + sta word2decimal_output,y + iny + pla + and #$0f + adc #'0' + sta word2decimal_output,y + iny + rts + }} +} + + +; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html + + +} ; ------ end of block c64utils + + +~ c64flt { + ; ---- this block contains C-64 floating point related functions ---- + + +asmsub FREADS32 () -> clobbers(A,X,Y) -> () { + ; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST) + %asm {{ + lda $62 + eor #$ff + asl a + lda #0 + ldx #$a0 + jmp $bc4f ; internal BASIC routine + }} +} + +asmsub FREADUS32 () -> clobbers(A,X,Y) -> () { + ; ---- fac1 = uint32 from $62-$65 big endian (MSB FIRST) + %asm {{ + sec + lda #0 + ldx #$a0 + jmp $bc4f ; internal BASIC routine + }} +} + +asmsub FREADS24AXY (lo: byte @ A, mid: byte @ X, hi: byte @ Y) -> clobbers(A,X,Y) -> () { + ; ---- fac1 = signed int24 (A/X/Y contain lo/mid/hi bytes) + ; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead. + %asm {{ + sty $62 + stx $63 + sta $64 + lda $62 + eor #$FF + asl a + lda #0 + sta $65 + ldx #$98 + jmp $bc4f ; internal BASIC routine + }} +} + +asmsub GIVUAYF (uword: word @ AY) -> clobbers(A,X,Y) -> () { + ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 + %asm {{ + sty $62 + sta $63 + ldx #$90 + sec + jmp $bc49 ; internal BASIC routine + }} +} + +asmsub GIVAYFAY (sword: word @ AY) -> clobbers(A,X,Y) -> () { + ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 + %asm {{ + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + jmp c64.GIVAYF ; this uses the inverse order, Y/A + }} +} + +asmsub FTOSWRDAY () -> clobbers(X) -> (word @ AY) { + ; ---- fac1 to signed word in A/Y + %asm {{ + jsr c64.FTOSWORDYA ; note the inverse Y/A order + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + rts + }} +} + +asmsub GETADRAY () -> clobbers(X) -> (word @ AY) { + ; ---- fac1 to unsigned word in A/Y + %asm {{ + jsr c64.GETADR ; this uses the inverse order, Y/A + sta c64.SCRATCH_ZP1 + tya + ldy c64.SCRATCH_ZP1 + rts + }} +} + + +asmsub copy_mflt (source: word @ XY) -> clobbers(A,Y) -> () { + ; ---- copy a 5 byte MFLT floating point variable to another place + ; input: X/Y = source address, c64.SCRATCH_ZPWORD1 = destination address + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZPWORD1+1 + ldy #0 + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + iny + lda (c64.SCRATCH_ZP1),y + sta (c64.SCRATCH_ZPWORD1),y + ldy c64.SCRATCH_ZPWORD1+1 + rts + }} +} + +asmsub float_add_one (mflt: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + txa + jsr c64.MOVFM ; fac1 = float XY + lda #c64.FL_FONE + jsr c64.FADD ; fac1 += 1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +asmsub float_sub_one (mflt: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + lda #c64.FL_FONE + jsr c64.MOVFM ; fac1 = 1 + txa + ldy c64.SCRATCH_ZP2 + jsr c64.FSUB ; fac1 = float XY - 1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +asmsub float_add_SW1_to_XY (mflt: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- add MFLT pointed to by SCRATCH_ZPWORD1 to the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + txa + jsr c64.MOVFM ; fac1 = float XY + lda c64.SCRATCH_ZPWORD1 + ldy c64.SCRATCH_ZPWORD1+1 + jsr c64.FADD ; fac1 += SCRATCH_ZPWORD1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +asmsub float_sub_SW1_from_XY (mflt: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- subtract MFLT pointed to by SCRATCH_ZPWORD1 from the MFLT pointed to by X/Y. Clobbers A, X, Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + lda c64.SCRATCH_ZPWORD1 + ldy c64.SCRATCH_ZPWORD1+1 + jsr c64.MOVFM ; fac1 = SCRATCH_ZPWORD1 + txa + ldy c64.SCRATCH_ZP2 + jsr c64.FSUB ; fac1 = float XY - SCRATCH_ZPWORD1 + ldx c64.SCRATCH_ZP1 + ldy c64.SCRATCH_ZP2 + jmp c64.FTOMEMXY ; float XY = fac1 + }} +} + +} ; ------ end of block c64flt + + + +~ c64scr { + ; ---- this block contains (character) Screen and text I/O related functions ---- + + +asmsub clear_screen (char: byte @ A, color: byte @ Y) -> clobbers() -> () { + ; ---- clear the character screen with the given fill character and character color. + ; (assumes screen is at $0400, could be altered in the future with self-modifying code) + ; @todo some byte var to set the SCREEN ADDR HI BYTE + + %asm {{ + sta _loop + 1 ; self-modifying + stx c64.SCRATCH_ZP1 + ldx #0 +_loop lda #0 + sta c64.Screen,x + sta c64.Screen+$0100,x + sta c64.Screen+$0200,x + sta c64.Screen+$02e8,x + tya + sta c64.Colors,x + sta c64.Colors+$0100,x + sta c64.Colors+$0200,x + sta c64.Colors+$02e8,x + inx + bne _loop + + lda _loop+1 ; restore A and X + ldx c64.SCRATCH_ZP1 + rts + }} + +} + + +asmsub scroll_left_full (alsocolors: byte @ Pc) -> clobbers(A, X, Y) -> () { + ; ---- scroll the whole screen 1 character to the left + ; contents of the rightmost column are unchanged, you should clear/refill this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #0 + ldy #38 +- + .for row=0, row<=12, row+=1 + lda c64.Colors + 40*row + 1,x + sta c64.Colors + 40*row,x + .next + inx + dey + bpl - + + ldx #0 + ldy #38 +- + .for row=13, row<=24, row+=1 + lda c64.Colors + 40*row + 1,x + sta c64.Colors + 40*row,x + .next + inx + dey + bpl - + +_scroll_screen ; scroll the screen memory + ldx #0 + ldy #38 +- + .for row=0, row<=12, row+=1 + lda c64.Screen + 40*row + 1,x + sta c64.Screen + 40*row,x + .next + inx + dey + bpl - + + ldx #0 + ldy #38 +- + .for row=13, row<=24, row+=1 + lda c64.Screen + 40*row + 1,x + sta c64.Screen + 40*row,x + .next + inx + dey + bpl - + + rts + }} +} + + +asmsub scroll_right_full (alsocolors: byte @ Pc) -> clobbers(A,X) -> () { + ; ---- scroll the whole screen 1 character to the right + ; contents of the leftmost column are unchanged, you should clear/refill this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #38 +- + .for row=0, row<=12, row+=1 + lda c64.Colors + 40*row + 0,x + sta c64.Colors + 40*row + 1,x + .next + dex + bpl - + + ldx #38 +- + .for row=13, row<=24, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*row + 1,x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #38 +- + .for row=0, row<=12, row+=1 + lda c64.Screen + 40*row + 0,x + sta c64.Screen + 40*row + 1,x + .next + dex + bpl - + + ldx #38 +- + .for row=13, row<=24, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*row + 1,x + .next + dex + bpl - + + rts + }} +} + + +asmsub scroll_up_full (alsocolors: byte @ Pc) -> clobbers(A,X) -> () { + ; ---- scroll the whole screen 1 character up + ; contents of the bottom row are unchanged, you should refill/clear this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #39 +- + .for row=1, row<=11, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row-1),x + .next + dex + bpl - + + ldx #39 +- + .for row=12, row<=24, row+=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row-1),x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #39 +- + .for row=1, row<=11, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row-1),x + .next + dex + bpl - + + ldx #39 +- + .for row=12, row<=24, row+=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row-1),x + .next + dex + bpl - + + rts + }} +} + + +asmsub scroll_down_full (alsocolors: byte @ Pc) -> clobbers(A,X) -> () { + ; ---- scroll the whole screen 1 character down + ; contents of the top row are unchanged, you should refill/clear this yourself + ; Carry flag determines if screen color data must be scrolled too + %asm {{ + bcs + + jmp _scroll_screen + ++ ; scroll the color memory + ldx #39 +- + .for row=23, row>=12, row-=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row+1),x + .next + dex + bpl - + + ldx #39 +- + .for row=11, row>=0, row-=1 + lda c64.Colors + 40*row,x + sta c64.Colors + 40*(row+1),x + .next + dex + bpl - + +_scroll_screen ; scroll the screen memory + ldx #39 +- + .for row=23, row>=12, row-=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row+1),x + .next + dex + bpl - + + ldx #39 +- + .for row=11, row>=0, row-=1 + lda c64.Screen + 40*row,x + sta c64.Screen + 40*(row+1),x + .next + dex + bpl - + + rts + }} +} + + + +asmsub print_string (address: word @ XY) -> clobbers(A,Y) -> () { + ; ---- print null terminated string from X/Y + ; note: the compiler contains an optimization that will replace + ; a call to this subroutine with a string argument of just one char, + ; by just one call to c64.CHROUT of that single char. + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + ldy #0 +- lda (c64.SCRATCH_ZP1),y + beq + + jsr c64.CHROUT + iny + bne - ++ rts + }} +} + + +asmsub print_pstring (address: word @ XY) -> clobbers(A,X) -> (byte @ Y) { + ; ---- print pstring (length as first byte) from X/Y, returns str len in Y + %asm {{ + stx c64.SCRATCH_ZP1 + sty c64.SCRATCH_ZP2 + ldy #0 + lda (c64.SCRATCH_ZP1),y + beq + + tax +- iny + lda (c64.SCRATCH_ZP1),y + jsr c64.CHROUT + dex + bne - ++ rts ; output string length is in Y + }} +} + + +asmsub print_pimmediate () -> clobbers() -> () { + ; ---- print pstring in memory immediately following the subroutine fast call instruction + ; note that the clobbered registers (A,X,Y) are not listed ON PURPOSE + %asm {{ + tsx + lda $102,x + tay ; put high byte in y + lda $101,x + tax ; and low byte in x. + inx + bne + + iny ++ jsr print_pstring ; print string in XY, returns string length in y. + tya + tsx + clc + adc $101,x ; add content of 1st (length) byte to return addr. + bcc + ; if that made the low byte roll over to 00, + inc $102,x ; then increment the high byte too. ++ clc + adc #1 ; now add 1 for the length byte itself. + sta $101,x + bne + ; if that made it (the low byte) roll over to 00, + inc $102,x ; increment the high byte of the return addr too. ++ rts + }} +} + + +asmsub print_byte_decimal0 (ubyte: byte @ A) -> clobbers(A,X,Y) -> () { + ; ---- print the byte in A in decimal form, with left padding 0s (3 positions total) + %asm {{ + jsr byte2decimal + pha + tya + jsr c64.CHROUT + txa + jsr c64.CHROUT + pla + jmp c64.CHROUT + }} +} + + +asmsub print_byte_decimal (ubyte: byte @ A) -> clobbers(A,X,Y) -> () { + ; ---- print the byte in A in decimal form, without left padding 0s + %asm {{ + jsr byte2decimal + pha + cpy #'0' + bne _print_hundreds + cpx #'0' + bne _print_tens + pla + jmp c64.CHROUT +_print_hundreds tya + jsr c64.CHROUT +_print_tens txa + jsr c64.CHROUT + pla + jmp c64.CHROUT + }} +} + + +asmsub print_byte_hex (prefix: byte @ Pc, ubyte: byte @ A) -> clobbers(A,X,Y) -> () { + ; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) + %asm {{ + bcc + + pha + lda #'$' + jsr c64.CHROUT + pla ++ jsr byte2hex + txa + jsr c64.CHROUT + tya + jmp c64.CHROUT + }} +} + + +asmsub print_word_hex (prefix: byte @ Pc, dataword: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits) + ; (if Carry is set, a radix prefix '$' is printed as well) + %asm {{ + stx c64.SCRATCH_ZP1 + tya + jsr print_byte_hex + lda c64.SCRATCH_ZP1 + clc + jmp print_byte_hex + }} +} + + +asmsub print_word_decimal0 (dataword: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total) + %asm {{ + jsr word2decimal + lda word2decimal_output + jsr c64.CHROUT + lda word2decimal_output+1 + jsr c64.CHROUT + lda word2decimal_output+2 + jsr c64.CHROUT + lda word2decimal_output+3 + jsr c64.CHROUT + lda word2decimal_output+4 + jmp c64.CHROUT + }} +} + + +asmsub print_word_decimal (dataword: word @ XY) -> clobbers(A,X,Y) -> () { + ; ---- print the word in X/Y in decimal form, without left padding 0s + %asm {{ + jsr word2decimal + ldy #0 + lda word2decimal_output + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+1 + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+2 + cmp #'0' + bne _pr_decimal + iny + lda word2decimal_output+3 + cmp #'0' + bne _pr_decimal + iny + +_pr_decimal + lda word2decimal_output,y + jsr c64.CHROUT + iny + cpy #5 + bcc _pr_decimal + rts + }} +} + + +asmsub input_chars (buffer: word @ AX) -> clobbers(A) -> (byte @ Y) { + ; ---- Input a string (max. 80 chars) from the keyboard. + ; It assumes the keyboard is selected as I/O channel!! + + %asm {{ + sta c64.SCRATCH_ZP1 + stx c64.SCRATCH_ZP2 + ldy #0 ; char counter = 0 +- jsr c64.CHRIN + cmp #$0d ; return (ascii 13) pressed? + beq + ; yes, end. + sta (c64.SCRATCH_ZP1),y ; else store char in buffer + iny + bne - ++ lda #0 + sta (c64.SCRATCH_ZP1),y ; finish string with 0 byte + rts + + }} +} + +} ; ---- end block c64scr + + + +;asmsub memcopy_basic () -> clobbers(A,X,Y) -> () { +; ; ---- copy a memory block by using a BASIC ROM routine +; ; it calls a function from the basic interpreter, so: +; ; - BASIC ROM must be banked in +; ; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O) +; ; - the target block must be writable (so no RAM hidden under I/O) +; ; higher addresses are copied first, so: +; ; - moving data to higher addresses works even if areas overlap +; ; - moving data to lower addresses only works if areas do not overlap +; %asm {{ +; lda #src_start +; sta $5f +; stx $60 +; lda #src_end +; sta $5a +; stx $5b +; lda #<(target_start + src_end - src_start) +; ldx #>(target_start + src_end - src_start) +; sta $58 +; stx $59 +; jmp $a3bf +; } +;} + +; macro version of the above memcopy_basic routine: +; MACRO PARAMS src_start, src_end, target_start +; lda #src_start +; sta $5f +; stx $60 +; lda #src_end +; sta $5a +; stx $5b +; lda #<(target_start + src_end - src_start) +; ldx #>(target_start + src_end - src_start) +; sta $58 +; stx $59 +; jsr $a3bf +