From: Shamus Hammons Date: Wed, 13 Feb 2013 02:14:47 +0000 (-0600) Subject: Fixed .cargs problem, more code cleanup/fixup X-Git-Tag: 1.3.0~24 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=commitdiff_plain;h=11a78647f7f170e6ea39dd04a3734a359151debb Fixed .cargs problem, more code cleanup/fixup Thanks to GroovyBee for reporting the .cargs problem! Also, pretty much all of the remaining cruft coming from the misguided "GPU in Main" cult has been removed. Never do in an assembler what you can do with either macros or a good preprocessor! --- diff --git a/direct.c b/direct.c index a14307d..b1c368a 100644 --- a/direct.c +++ b/direct.c @@ -79,10 +79,6 @@ int (*dirtab[])() = { d_equrundef, // 50 .equrundef/.regundef d_ccundef, // 51 .ccundef d_print, // 52 .print -// d_gpumain, // 53 .gpumain -// d_jpad, // 54 .jpad -// d_nojpad, // 55 .nojpad -// d_fail, // 56 .fail }; @@ -355,14 +351,16 @@ int d_incbin(void) // int d_regbank0(void) { - regbank = BANK_0; // Set active register bank zero + // Set active register bank zero + regbank = BANK_0; return 0; } int d_regbank1(void) { - regbank = BANK_1; // Set active register bank one + // Set active register bank one + regbank = BANK_1; return 0; } @@ -649,11 +647,11 @@ int d_include(void) // the "-d" option. if ((j = open(fn, 0)) < 0) { - for(i=0; nthpath("RMACPATH", i, buf1)!=0; ++i) + for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++) { j = strlen(buf1); - if (j > 0 && buf1[j-1] != SLASHCHAR) // Append path char if necessary + if (j > 0 && buf1[j - 1] != SLASHCHAR) // Append path char if necessary strcat(buf1, SLASHSTRING); strcat(buf1, fn); @@ -894,7 +892,7 @@ int d_dc(WORD siz) case SIZB: if (!defined) { - fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); + fixup(FU_BYTE | FU_SEXT, sloc, exprbuf); D_byte(0); } else @@ -913,7 +911,7 @@ int d_dc(WORD siz) case SIZN: if (!defined) { - fixup(FU_WORD|FU_SEXT, sloc, exprbuf); + fixup(FU_WORD | FU_SEXT, sloc, exprbuf); D_word(0); } else @@ -933,7 +931,7 @@ int d_dc(WORD siz) if (!defined) { if (movei) - fixup(FU_LONG|FU_MOVEI, sloc, exprbuf); + fixup(FU_LONG | FU_MOVEI, sloc, exprbuf); else fixup(FU_LONG, sloc, exprbuf); @@ -1081,7 +1079,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) case SIZB: if (!defined) { - fixup(FU_BYTE|FU_SEXT, sloc, exprbuf); + fixup(FU_BYTE | FU_SEXT, sloc, exprbuf); D_byte(0); } else @@ -1100,7 +1098,7 @@ int dep_block(VALUE count, WORD siz, VALUE eval, WORD eattr, TOKEN * exprbuf) case SIZN: if (!defined) { - fixup(FU_WORD|FU_SEXT, sloc, exprbuf); + fixup(FU_WORD | FU_SEXT, sloc, exprbuf); D_word(0); } else @@ -1185,7 +1183,7 @@ int d_comm(void) int d_list(void) { if (list_flag) - ++listing; + listing++; return 0; } @@ -1197,7 +1195,7 @@ int d_list(void) int d_nlist(void) { if (list_flag) - --listing; + listing--; return 0; } @@ -1209,7 +1207,6 @@ int d_nlist(void) int d_68000(void) { rgpu = rdsp = 0; -// in_main = 0; // Switching from gpu/dsp sections should reset any ORG'd Address orgactive = 0; orgwarning = 0; @@ -1237,11 +1234,9 @@ int d_gpu(void) orgwarning = 0; } - rgpu = 1; // Set GPU assembly - rdsp = 0; // Unset DSP assembly - regbank = BANK_N; // Set no default register bank -// in_main = 0; -// jpad = 0; + rgpu = 1; // Set GPU assembly + rdsp = 0; // Unset DSP assembly + regbank = BANK_N; // Set no default register bank return 0; } @@ -1264,11 +1259,9 @@ int d_dsp(void) orgwarning = 0; } - rdsp = 1; // Set DSP assembly - rgpu = 0; // Unset GPU assembly - regbank = BANK_N; // Set no default register bank -// in_main = 0; -// jpad = 0; + rdsp = 1; // Set DSP assembly + rgpu = 0; // Unset GPU assembly + regbank = BANK_N; // Set no default register bank return 0; } @@ -1277,17 +1270,17 @@ int d_dsp(void) // .cargs [#offset], symbol[.size], ... // // Lists of registers may also be mentioned; they just take up space. Good for -// "documentation" purposes. +// "documentation" purposes: // -// .cargs a6,.arg1, .arg2, .arg3... +// .cargs a6, .arg1, .arg2, .arg3... // -// The symbols are ABS and EQUATED. +// Symbols thus created are ABS and EQUATED. // int d_cargs(void) { VALUE eval; WORD rlist; - SYM * sy; + SYM * symbol; char * p; int env; int i; @@ -1297,15 +1290,17 @@ int d_cargs(void) if (*tok == '#') { - ++tok; + tok++; if (abs_expr(&eval) != OK) return 0; - if (*tok == ',') // Eat comma if it's there - ++tok; + // Eat the comma, if it's there + if (*tok == ',') + tok++; } else + // Default to 4 if not specified (because PC is on stack according to GroovyBee) eval = 4; for(;;) @@ -1315,75 +1310,83 @@ int d_cargs(void) // p = (char *)tok[1]; p = string[tok[1]]; +#if 0 if (*p == '.') - env = curenv; + env = curenv; // Label is local else - env = 0; - - sy = lookup(p, LABEL, env); + env = 0; // Label is global +#else + // Set env to either local (dot prefixed) or global scope + env = (*p == '.' ? curenv : 0); +#endif + symbol = lookup(p, LABEL, env); - if (sy == NULL) + if (symbol == NULL) { - sy = NewSymbol(p, LABEL, env); - sy->sattr = 0; + symbol = NewSymbol(p, LABEL, env); + symbol->sattr = 0; } - else if (sy->sattr & DEFINED) + else if (symbol->sattr & DEFINED) return errors("multiply-defined label '%s'", p); // Put symbol in "order of definition" list - if (!(sy->sattr & SDECLLIST)) - sym_decl(sy); + if (!(symbol->sattr & SDECLLIST)) + sym_decl(symbol); - sy->sattr |= ABS|DEFINED|EQUATED; - sy->svalue = eval; + symbol->sattr |= (ABS | DEFINED | EQUATED); + symbol->svalue = eval; tok += 2; - switch((int)*tok) + // What this does is eat any dot suffixes attached to a symbol. If + // it's a .L, it adds 4 to eval; if it's .W or .B, it adds 2. If + // there is no dot suffix, it assumes a size of 2. + switch ((int)*tok) { case DOTL: eval += 2; case DOTB: case DOTW: - ++tok; + tok++; } eval += 2; } - else + else if (*tok >= KW_D0 && *tok <= KW_A7) { - if (*tok >= KW_D0 && *tok <= KW_A7) - { - if (reglist(&rlist) < 0) - return 0; + if (reglist(&rlist) < 0) + return 0; - for(i=0; i++<16; rlist>>=1) - if (rlist & 1) - eval += 4; +// for(i=0; i++<16; rlist>>=1) + for(i=0; i<16; i++, rlist>>=1) + { + if (rlist & 1) + eval += 4; } - else + } + else + { + switch ((int)*tok) { - switch((int)*tok) - { - case KW_USP: - case KW_SSP: - case KW_PC: - eval += 2; - // FALLTHROUGH - case KW_SR: - case KW_CCR: - eval += 2; - ++tok; - break; - case EOL: - return 0; - default: - return error(".cargs syntax"); - } + case KW_USP: + case KW_SSP: + case KW_PC: + eval += 2; + // FALLTHROUGH + case KW_SR: + case KW_CCR: + eval += 2; + tok++; + break; + case EOL: + return 0; + default: + return error(".cargs syntax"); } - - if (*tok == ',') - ++tok; } + + // Eat commas in between each argument, if they exist + if (*tok == ',') + tok++; } } @@ -1393,11 +1396,12 @@ int d_cargs(void) // int undmac1(char * p) { - SYM * sy; + SYM * symbol = lookup(p, MACRO, 0); - // If the macro symbol exists, cause it to dissappear - if ((sy = lookup(p, MACRO, 0)) != NULL) - sy->stype = (BYTE)SY_UNDEF; + // If the macro symbol exists, cause it to disappear +// if ((sy = lookup(p, MACRO, 0)) != NULL) + if (symbol != NULL) + symbol->stype = (BYTE)SY_UNDEF; return OK; } @@ -1408,3 +1412,4 @@ int d_undmac(void) symlist(undmac1); return 0; } + diff --git a/macro.c b/macro.c index 3f3e81b..5c590e4 100644 --- a/macro.c +++ b/macro.c @@ -17,8 +17,6 @@ #include "token.h" -//static void SetupDefaultMacros(void); - LONG curuniq; // Current macro's unique number //TOKEN ** argp; // Free spot in argptrs[] int macnum; // Unique number for macro definition @@ -44,7 +42,6 @@ void InitMacro(void) macnum = 1; // argp = NULL; argp = 0; -// SetupDefaultMacros(); } @@ -84,7 +81,6 @@ of another (nested macros). Need to fix that somehow. DEBUG printf("%d (nargs = %d)\n", argp, imacro->im_nargs); fpop(); -// mjump_align = 0; return 0; } @@ -451,14 +447,6 @@ int InvokeMacro(SYM * mac, WORD siz) // argp = 0; DEBUG printf("InvokeMacro: argp: %d -> ", argp); -#if 0 - if ((!strcmp(mac->sname, "mjump") || !strcmp(mac->sname, "mpad")) && !in_main) - { - error("macro cannot be used outside of .gpumain"); - return ERROR; - } -#endif - INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO IMACRO * imacro = inobj->inobj.imacro; imacro->im_siz = siz; @@ -625,49 +613,3 @@ alleviate this problem.] return OK; } - -#if 0 -// -// Setup inbuilt macros (SubQMod) -// -static void SetupDefaultMacros(void) -{ - curmac = NewSymbol("mjump", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); - defmac2("jreg"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" nop", -1); - defmac1(" movei #\\addr,\\jreg", -1); - defmac1(" jump \\cc,(\\jreg)", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = NewSymbol("mjr", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" jr \\cc,\\addr", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = NewSymbol("mpad", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("size"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" .rept (\\size/2)", -1); - defmac1(" nop", -1); - defmac1(" .endr", -1); -} -#endif diff --git a/mark.c b/mark.c index d3b827a..11fde4f 100644 --- a/mark.c +++ b/mark.c @@ -11,6 +11,7 @@ #include "object.h" #include "risca.h" + MCHUNK * firstmch; // First mark chunk MCHUNK * curmch; // Current mark chunk PTR markptr; // Deposit point in current mark chunk diff --git a/mark.h b/mark.h index 230a77b..5e5fe35 100644 --- a/mark.h +++ b/mark.h @@ -12,7 +12,7 @@ #include "rmac.h" #include "sect.h" -#define MARK_ALLOC_INCR 1024 // #bytes to alloc for more mark space +#define MARK_ALLOC_INCR 1024 // # bytes to alloc for more mark space #define MIN_MARK_MEM (3*sizeof(WORD)+2*sizeof(LONG)) // Globals, Externals etc diff --git a/procln.c b/procln.c index 5e84c41..ab9d53a 100644 --- a/procln.c +++ b/procln.c @@ -29,6 +29,7 @@ #define DECL_MR #include "risckw.h" + IFENT * ifent; // Current ifent static IFENT ifent0; // Root ifent static IFENT * f_ifent; // Freelist of ifents @@ -627,7 +628,7 @@ do_label: // Call RISC code generator if we found a mnemonic if (state >= 3000) { - risccg(state); + GenerateRISCCode(state); goto loop; } } diff --git a/risca.c b/risca.c index 7786beb..868e1c5 100644 --- a/risca.c +++ b/risca.c @@ -15,18 +15,17 @@ #include "mark.h" #include "amode.h" -#define DEF_MR // Declar keyword values -#include "risckw.h" // Incl generated risc keywords +#define DEF_MR // Declar keyword values +#include "risckw.h" // Incl generated risc keywords -#define DEF_KW // Declare keyword values -#include "kwtab.h" // Incl generated keyword tables & defs +#define DEF_KW // Declare keyword values +#include "kwtab.h" // Incl generated keyword tables & defs -unsigned altbankok = 0; // Ok to use alternate register bank -unsigned orgactive = 0; // RISC org directive active -unsigned orgaddr = 0; // Org'd address -unsigned orgwarning = 0; // Has an ORG warning been issued -//unsigned previousop = 0; // Used for NOP padding checks -//unsigned currentop = 0; // Used for NOP padding checks + +unsigned altbankok = 0; // Ok to use alternate register bank +unsigned orgactive = 0; // RISC org directive active +unsigned orgaddr = 0; // Org'd address +unsigned orgwarning = 0; // Has an ORG warning been issued char reg_err[] = "missing register R0...R31"; @@ -38,8 +37,10 @@ char condname[MAXINTERNCC][5] = { }; // Jaguar Jump Condition Numbers -char condnumber[] = { 1, 2, 4, 5, 6, 8, 9, 10, 20, 21, 22, 24, 25, 26, - 0, 0, 1, 2, 4, 4, 5, 8, 8, 20, 24, 31}; +char condnumber[] = { + 1, 2, 4, 5, 6, 8, 9, 10, 20, 21, 22, 24, 25, 26, + 0, 0, 1, 2, 4, 4, 5, 8, 8, 20, 24, 31 +}; struct opcoderecord roptbl[] = { { MR_ADD, RI_TWO, 0 }, @@ -112,85 +113,43 @@ struct opcoderecord roptbl[] = { // void strtoupper(char * s) { +#if 0 while (*s) { *s = (char)(toupper(*s)); s++; } +#else + while (*s) + *s++ &= 0xDF; +#endif } // -// Build RISC Instruction Word +// Function to return "malformed expression" error +// This is done mainly to remove a bunch of GOTO statements in the parser // -void risc_instruction_word(unsigned short parm, int reg1, int reg2) +static inline int MalformedOpcode(void) { -// int value = 0xE400; + error("Malformed opcode"); + return ERROR; +} - // Opcode tracking for nop padding -// previousop = currentop; -// currentop = parm; +// +// Build RISC Instruction Word +// +void BuildRISCIntructionWord(unsigned short opcode, int reg1, int reg2) +{ + // Check for absolute address setting if (!orgwarning && !orgactive) { - // Check for absolute address setting -// if (!orgactive && !in_main) -// { - warn("GPU/DSP code outside of absolute section"); - orgwarning = 1; -// } - } - -#if 0 - if (jpad) - { // JPAD directive - // JUMP JR NOP - if (((previousop == 52) || (previousop == 53)) && (currentop != 57)) - D_word(value); // Insert NOP - } - else -// { - // JUMP JR - if ((previousop == 52) || (previousop == 53)) - { - switch (currentop) - { - case 38: - warn("NOP inserted before MOVEI instruction."); - D_word(value); - break; - case 53: - warn("NOP inserted before JR instruction."); - D_word(value); - break; - case 52: - warn("NOP inserted before JUMP instruction."); - D_word(value); - break; - case 51: - warn("NOP inserted before MOVE PC instruction."); - D_word(value); - break; - default: - break; - } - } -// } - - if (currentop == 20) - { // IMACN checks - if ((previousop != 18) && (previousop != 20)) - error("IMULTN/IMACN instruction must preceed IMACN instruction"); - } - - if (currentop == 19) - { // RESMAC checks - if (previousop != 20) - error("IMACN instruction must preceed RESMAC instruction"); + warn("GPU/DSP code outside of absolute section"); + orgwarning = 1; } -#endif - int value = ((parm & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F); + int value = ((opcode & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F); D_word(value); } @@ -198,7 +157,7 @@ void risc_instruction_word(unsigned short parm, int reg1, int reg2) // // Get a RISC Register // -int getregister(WORD rattr) +int GetRegister(WORD rattr) { VALUE eval; // Expression value WORD eattr; // Expression attributes @@ -207,10 +166,7 @@ int getregister(WORD rattr) // Evaluate what's in the global "tok" buffer if (expr(r_expr, &eval, &eattr, &esym) != OK) - { - error("Malformed opcode"); - return ERROR; - } + return MalformedOpcode(); if ((challoc - ch_size) < 4) chcheck(4L); @@ -234,28 +190,24 @@ int getregister(WORD rattr) // // Do RISC Code Generation // -int risccg(int state) +int GenerateRISCCode(int state) { -// unsigned short parm; // Opcode parameters -// unsigned type; // Opcode type int reg1; // Register 1 int reg2; // Register 2 int val = 0; // Constructed value char scratch[80]; SYM * ccsym; SYM * sy; - int i; // Iterator - int t, c; + int i, commaFound; + TOKEN * t; WORD tdb; - unsigned locptr = 0; // Address location pointer - unsigned page_jump = 0; // Memory page jump flag + WORD attrflg; + int indexed; // Indexed register flag + VALUE eval; // Expression value WORD eattr; // Expression attributes SYM * esym; // External symbol involved in expr. TOKEN r_expr[EXPRSIZE]; // Expression token list - WORD defined; // Symbol defined flag - WORD attrflg; - int indexed; // Indexed register flag // Get opcode parameter and type unsigned short parm = (WORD)(roptbl[state - 3000].parm); @@ -263,7 +215,7 @@ int risccg(int state) // Detect whether the opcode parmeter passed determines that the opcode is // specific to only one of the RISC processors and ensure it is legal in - // the current code section. If not then error and return. + // the current code section. If not then show error and return. if (((parm & GPUONLY) && rdsp) || ((parm & DSPONLY) && rgpu)) { error("Opcode is not valid in this code section"); @@ -276,15 +228,15 @@ int risccg(int state) // No operand instructions // NOP case RI_NONE: - risc_instruction_word(parm, 0, 0); + BuildRISCIntructionWord(parm, 0, 0); break; // Single operand instructions (Rd) // ABS, MIRROR, NEG, NOT, PACK, RESMAC, SAT8, SAT16, SAT16S, SAT24, SAT32S, UNPACK case RI_ONE: - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, parm >> 6, reg2); + BuildRISCIntructionWord(parm, parm >> 6, reg2); break; // Two operand instructions (Rs,Rd) @@ -294,28 +246,28 @@ int risccg(int state) if (parm == 37) altbankok = 1; // MOVEFA - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); CHECK_COMMA; if (parm == 36) altbankok = 1; // MOVETA - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, reg1, reg2); + BuildRISCIntructionWord(parm, reg1, reg2); break; // Numeric operand (n,Rd) where n = -16..+15 // CMPQ - case RI_NUM_15: + case RI_NUM_15: // Numeric operand (n,Rd) where n = 0..31 // BCLR, BSET, BTST, MOVEQ - case RI_NUM_31: + case RI_NUM_31: // Numeric operand (n,Rd) where n = 1..32 // ADDQ, ADDQMOD, ADDQT, SHARQ, SHLQ, SHRQ, SUBQ, SUBQMOD, SUBQT, ROLQ, RORQ - case RI_NUM_32: + case RI_NUM_32: switch (type) { case RI_NUM_15: @@ -330,139 +282,99 @@ int risccg(int state) break; } - if (parm & SUB32) attrflg |= FU_SUB32; - { - if (*tok == '#') - { - tok++; + if (parm & SUB32) + attrflg |= FU_SUB32; - if (expr(r_expr, &eval, &eattr, &esym) != OK) - goto malformed; - else - { - defined = (WORD)(eattr & DEFINED); + if (*tok != '#') + return MalformedOpcode(); - if ((challoc - ch_size) < 4) - chcheck(4L); + tok++; - if (!defined) - { - fixup((WORD)(FU_WORD | attrflg), sloc, r_expr); - reg1 = 0; - } - else - { - if ((int)eval < reg1 || (int)eval > reg2) - { - error("constant out of range"); - return ERROR; - } + if (expr(r_expr, &eval, &eattr, &esym) != OK) + return MalformedOpcode(); - if (parm & SUB32) - reg1 = 32 - eval; - else if (type == RI_NUM_32) - reg1 = (reg1 == 32 ? 0 : eval); - else - reg1 = eval; - } - } + if ((challoc - ch_size) < 4) + chcheck(4L); + + if (!(eattr & DEFINED)) + { + fixup((WORD)(FU_WORD | attrflg), sloc, r_expr); + reg1 = 0; + } + else + { + if ((int)eval < reg1 || (int)eval > reg2) + { + error("constant out of range"); + return ERROR; } + + if (parm & SUB32) + reg1 = 32 - eval; + else if (type == RI_NUM_32) + reg1 = (reg1 == 32 ? 0 : eval); else - goto malformed; + reg1 = eval; } CHECK_COMMA; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, reg1, reg2); + BuildRISCIntructionWord(parm, reg1, reg2); break; // Move Immediate--n,Rn--n in Second Word case RI_MOVEI: if (*tok != '#') - goto malformed; - -// { - tok++; - - if (expr(r_expr, &eval, &eattr, &esym) != OK) - { - malformed: - error("malformed opcode"); - return ERROR; - } - else - { - // Opcode tracking for nop padding -// previousop = currentop; -// currentop = parm; + return MalformedOpcode(); -#if 0 - // JUMP or JR - if ((previousop == 52) || (previousop == 53) && !jpad) - { - warn("NOP inserted before MOVEI instruction."); - D_word(0xE400); - } -#endif + tok++; - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); + if (expr(r_expr, &eval, &eattr, &esym) != OK) + return MalformedOpcode(); - if ((challoc - ch_size) < 4) - chcheck(4L); + if ((challoc - ch_size) < 4) + chcheck(4L); - if (!defined) - { - fixup(FU_LONG | FU_MOVEI, sloc + 2, r_expr); - eval = 0; - } - else - { - if (tdb) - rmark(cursect, sloc + 2, tdb, MLONG | MMOVEI, NULL); - } - - val = eval; - -#if 0 - // Store the defined flags and value of the movei when used in mjump - if (mjump_align) - { - mjump_defined = defined; - mjump_dest = val; - } -#endif - } -// } -// else -// goto malformed; + if (!(eattr & DEFINED)) + { + fixup(FU_LONG | FU_MOVEI, sloc + 2, r_expr); + eval = 0; + } + else + { + if (eattr & TDB) + rmark(cursect, sloc + 2, tdb, MLONG | MMOVEI, NULL); + } - tok++; - reg2 = getregister(FU_REGTWO); +// val = eval; + val = ((eval >> 16) & 0x0000FFFF) | ((eval << 16) & 0xFFFF0000); +// tok++; // assuming a comma here? tsk tsk + CHECK_COMMA; + reg2 = GetRegister(FU_REGTWO); at_eol(); D_word((((parm & 0x3F) << 10) + reg2)); - val = ((val >> 16) & 0x0000FFFF) | ((val << 16) & 0xFFFF0000); D_long(val); break; - case RI_MOVE: // PC,Rd or Rs,Rd + // PC,Rd or Rs,Rd + case RI_MOVE: if (*tok == KW_PC) { parm = 51; reg1 = 0; - ++tok; + tok++; } else { parm = 34; - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); } CHECK_COMMA; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, reg1, reg2); + BuildRISCIntructionWord(parm, reg1, reg2); break; // (Rn),Rn = 41 / (R14/R15+n),Rn = 43/44 / (R14/R15+Rn),Rn = 58/59 @@ -471,11 +383,11 @@ int risccg(int state) parm = 41; if (*tok != '(') - goto malformed; + return MalformedOpcode(); tok++; - if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok+1) != ')')) + if ((*tok == KW_R14 || *tok == KW_R15) && (*(tok + 1) != ')')) indexed = (*tok - KW_R0); if (*tok == SYMBOL) @@ -492,23 +404,23 @@ int risccg(int state) if (sy->sattre & EQUATEDREG) { if (((sy->svalue & 0x1F) == 14 || (sy->svalue & 0x1F) == 15) - && (*(tok+2) != ')')) + && (*(tok + 2) != ')')) { indexed = (sy->svalue & 0x1F); - ++tok; + tok++; } } } if (!indexed) { - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); } else { reg1 = indexed; indexed = 0; - ++tok; + tok++; if (*tok == '+') { @@ -516,9 +428,7 @@ int risccg(int state) tok++; if (*tok >= KW_R0 && *tok <= KW_R31) - { indexed = 1; - } if (*tok == SYMBOL) { @@ -532,86 +442,74 @@ int risccg(int state) } if (sy->sattre & EQUATEDREG) - { indexed = 1; - } } if (indexed) { - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); } else { if (expr(r_expr, &eval, &eattr, &esym) != OK) + return MalformedOpcode(); + + if ((challoc - ch_size) < 4) + chcheck(4L); + + if (!(eattr & DEFINED)) { - goto malformed; + error("constant expected"); + return ERROR; } - else - { - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); - if ((challoc - ch_size) < 4) - chcheck(4L); + reg1 = eval; - if (!defined) + if (reg1 == 0) + { + reg1 = 14 + (parm - 58); + parm = 41; + warn("NULL offset removed"); + } + else + { + if (reg1 < 1 || reg1 > 32) { - error("constant expected"); + error("constant out of range"); return ERROR; - //fixup(FU_WORD|FU_REGONE, sloc, r_expr); - reg1 = 0; } - else - { - reg1 = eval; - - if (reg1 == 0) - { - reg1 = 14 + (parm - 58); - parm = 41; - warn("NULL offset removed"); - } - else - { - if (reg1 < 1 || reg1 > 32) - { - error("constant out of range"); - return ERROR; - } - if (reg1 == 32) - reg1 = 0; + if (reg1 == 32) + reg1 = 0; - parm = (WORD)(parm - 58 + 43); - } - } + parm = (WORD)(parm - 58 + 43); } } } else { - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); } } if (*tok != ')') - goto malformed; + return MalformedOpcode(); tok++; CHECK_COMMA; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, reg1, reg2); + BuildRISCIntructionWord(parm, reg1, reg2); break; // Rn,(Rn) = 47 / Rn,(R14/R15+n) = 49/50 / Rn,(R14/R15+Rn) = 60/61 case RI_STORE: parm = 47; - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); CHECK_COMMA; - if (*tok != '(') goto malformed; + if (*tok != '(') + return MalformedOpcode(); tok++; indexed = 0; @@ -643,7 +541,7 @@ int risccg(int state) if (!indexed) { - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); } else { @@ -657,9 +555,7 @@ int risccg(int state) tok++; if (*tok >= KW_R0 && *tok <= KW_R31) - { indexed = 1; - } if (*tok == SYMBOL) { @@ -673,131 +569,123 @@ int risccg(int state) } if (sy->sattre & EQUATEDREG) - { indexed = 1; - } } if (indexed) { - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); } else { if (expr(r_expr, &eval, &eattr, &esym) != OK) + return MalformedOpcode(); + + if ((challoc - ch_size) < 4) + chcheck(4L); + + if (!(eattr & DEFINED)) { - goto malformed; + fixup(FU_WORD | FU_REGTWO, sloc, r_expr); + reg2 = 0; } else { - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); - - if ((challoc - ch_size) < 4) - chcheck(4L); + reg2 = eval; - if (!defined) + if (reg2 == 0) { - fixup(FU_WORD | FU_REGTWO, sloc, r_expr); - reg2 = 0; + reg2 = 14 + (parm - 60); + parm = 47; + warn("NULL offset removed"); } else { - reg2 = eval; - - if (reg2 == 0 ) + if (reg2 < 1 || reg2 > 32) { - reg2 = 14 + (parm - 60); - parm = 47; - warn("NULL offset removed"); + error("constant out of range"); + return ERROR; } - else - { - if (reg2 < 1 || reg2 > 32) - { - error("constant out of range"); - return ERROR; - } - if (reg2 == 32) - reg2 = 0; + if (reg2 == 32) + reg2 = 0; - parm = (WORD)(parm - 60 + 49); - } - } + parm = (WORD)(parm - 60 + 49); + } } } } else { - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); } } if (*tok != ')') - goto malformed; + return MalformedOpcode(); tok++; at_eol(); - risc_instruction_word(parm, reg2, reg1); + BuildRISCIntructionWord(parm, reg2, reg1); break; // LOADB/LOADP/LOADW (Rn),Rn case RI_LOADN: if (*tok != '(') - goto malformed; + return MalformedOpcode(); tok++; - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); if (*tok != ')') - goto malformed; + return MalformedOpcode(); tok++; CHECK_COMMA; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); at_eol(); - risc_instruction_word(parm, reg1, reg2); + BuildRISCIntructionWord(parm, reg1, reg2); break; // STOREB/STOREP/STOREW Rn,(Rn) case RI_STOREN: - reg1 = getregister(FU_REGONE); + reg1 = GetRegister(FU_REGONE); CHECK_COMMA; if (*tok != '(') - goto malformed; + return MalformedOpcode(); tok++; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); if (*tok != ')') - goto malformed; + return MalformedOpcode(); tok++; at_eol(); - risc_instruction_word(parm, reg2, reg1); + BuildRISCIntructionWord(parm, reg2, reg1); break; - case RI_JR: // Jump Relative - cc,n - n=-16..+15 words, reg2=cc - case RI_JUMP: // Jump Absolute - cc,(Rs) - reg2=cc + // Jump Relative - cc,n - n=-16..+15 words, reg2=cc + case RI_JR: + + // Jump Absolute - cc,(Rs) - reg2=cc + case RI_JUMP: // Check to see if there is a comma in the token string. If not then // the JR or JUMP should default to 0, Jump Always - t = i = c = 0; + commaFound = 0; - while (t != EOL) + for(t=tok; *t!=EOL; t++) { - t = *(tok + i); - - if (t == ',') - c = 1; - - i++; + if (*t == ',') + { + commaFound = 1; + break; + } } - if (c) + if (commaFound) { - // Comma present in token string if (*tok == CONST) { // CC using a constant number @@ -845,13 +733,13 @@ int risccg(int state) } else if (*tok == '(') { - // Jump always + // Set CC to "Jump Always" val = 0; } } else { - // Jump always + // Set CC to "Jump Always" val = 0; } @@ -860,175 +748,66 @@ int risccg(int state) error("condition constant out of range"); return ERROR; } - else - { - // Store condition code - reg1 = val; - } + + // Store condition code + reg1 = val; if (type == RI_JR) { // JR cc,n if (expr(r_expr, &eval, &eattr, &esym) != OK) - goto malformed; - else - { - tdb = (WORD)(eattr & TDB); - defined = (WORD)(eattr & DEFINED); + return MalformedOpcode(); - if ((challoc - ch_size) < 4) - chcheck(4L); + if ((challoc - ch_size) < 4) + chcheck(4L); - if (!defined) - { + if (!(eattr & DEFINED)) + { + fixup(FU_WORD | FU_JR, sloc, r_expr); + reg2 = 0; + } + else + { #if 0 - if (in_main) - { - fixup(FU_WORD|FU_MJR, sloc, r_expr); - } - else -#endif -// { - fixup(FU_WORD | FU_JR, sloc, r_expr); -// } + val = eval; - reg2 = 0; - } + if (orgactive) + reg2 = ((int)(val - (orgaddr + 2))) / 2; else - { - val = eval; - - if (orgactive) - { - reg2 = ((int)(val - (orgaddr + 2))) / 2; - - if ((reg2 < -16) || (reg2 > 15)) - error("PC relative overflow"); - - locptr = orgaddr; - } - else - { - reg2 = ((int)(val - (sloc + 2))) / 2; - - if ((reg2 < -16) || (reg2 > 15)) - error("PC relative overflow"); - - locptr = sloc; - } - } - -#if 0 - if (in_main) - { - if (defined) - { - if (((locptr >= 0xF03000) && (locptr < 0xF04000) - && (val < 0xF03000)) || ((val >= 0xF03000) - && (val < 0xF04000) && (locptr < 0xF03000))) - { - warn("* cannot jump relative between main memory and local gpu ram"); - } - else - { - page_jump = (locptr & 0xFFFFFF00) - (val & 0xFFFFFF00); - - if (page_jump) - { - if (val % 4) - { - warn("* destination address not aligned for long page jump relative, " - "insert a \'nop\' before the destination label/address"); - } - } - else - { - if ((val - 2) % 4) - { - warn("* destination address not aligned for short page jump relative, " - "insert a \'nop\' before the destination label/address"); - } - } - } - } - } + reg2 = ((int)(val - (sloc + 2))) / 2; +#else + reg2 = ((int)(eval - (orgactive ? orgaddr : sloc) + 2)) / 2; #endif + + if ((reg2 < -16) || (reg2 > 15)) + error("PC relative overflow"); } - risc_instruction_word(parm, reg2, reg1); + BuildRISCIntructionWord(parm, reg2, reg1); } else { // JUMP cc, (Rn) if (*tok != '(') - goto malformed; + return MalformedOpcode(); tok++; - reg2 = getregister(FU_REGTWO); + reg2 = GetRegister(FU_REGTWO); if (*tok != ')') - goto malformed; + return MalformedOpcode(); tok++; at_eol(); - -#if 0 - if (in_main) - { - if (!mjump_align) - { - warn("* \'jump\' is not recommended for .gpumain as destination addresses " - "cannot be validated for alignment, use \'mjump\'"); - locptr = (orgactive) ? orgaddr : sloc; - - if (locptr % 4) - { - warn("* source address not aligned for long or short jump, " - "insert a \'nop\' before the \'jump\'"); - } - } - else - { - if (mjump_defined) - { - locptr = (orgactive) ? orgaddr : sloc; - page_jump = (locptr & 0xFFFFFF00) - (mjump_dest & 0xFFFFFF00); - - if (page_jump) - { - if (mjump_dest % 4) - { - warn("* destination address not aligned for long page jump, " - "insert a \'nop\' before the destination label/address"); - } - } - else - { - if (!(mjump_dest & 0x0000000F) || ((mjump_dest - 2) % 4)) - { - warn("* destination address not aligned for short page jump, " - "insert a \'nop\' before the destination label/address"); - } - } - } - else - { - locptr = (orgactive) ? orgaddr : sloc; - fwdjump[fwindex++] = locptr; - } - } - } -#endif - - risc_instruction_word(parm, reg2, reg1); + BuildRISCIntructionWord(parm, reg2, reg1); } break; - // Should never get here :D - default: - error("unknown risc opcode type"); + + // Should never get here :-D + default: + error("Unknown risc opcode type"); return ERROR; - break; } return 0; diff --git a/risca.h b/risca.h index 0ebff2f..6c64a94 100644 --- a/risca.h +++ b/risca.h @@ -12,37 +12,36 @@ #include "rmac.h" #include "procln.h" -#define MAXINTERNCC 26 // Maximum internal condition codes +#define MAXINTERNCC 26 // Maximum internal condition codes // RISC Instruction Types -#define RI_NONE 0x0000 // No Operands - NOP -#define RI_ONE 0x0001 // One Operand - Rd - ABS/NEG/etc -#define RI_TWO 0x0002 // Two Operands - Rs,Rd - Most Instructions -#define RI_NUM_15 0x0003 // Numeric Operand - n,Rd - n=-16..+15 - CMPQ -#define RI_NUM_31 0x0004 // Numeric Operand - n,Rd - n=0..31 - BCLR/BSET/BTST/MOVEQ -#define RI_NUM_32 0x0005 // Numeric Operand - n,Rd - n=1..32 - ADDQ/SUBQ -#define RI_JR 0x0006 // Jump Relative - cc,n - n=-16..+15 words, reg2=cc -#define RI_JUMP 0x0007 // Jump Absolute - cc,(Rs) - reg2=cc -#define RI_MOVEI 0x0008 // Move Immediate - n,Rn - n in second word -#define RI_MOVE 0x0009 // MOVE Instruction - PC,Rn / Rn,Rn -#define RI_LOAD 0x000A // LOAD Instruction - Various Forms -#define RI_LOADN 0x000B // LOADB/LOADP/LOADW - (Rs),Rd -#define RI_STORE 0x000C // STORE Instruction - Various Forms -#define RI_STOREN 0x000D // STOREB/STOREP/STOREM - Rs,(Rd) -#define RI_MJMP 0x000E // MJMP psuedo instruction +#define RI_NONE 0x0000 // No Operands - NOP +#define RI_ONE 0x0001 // One Operand - Rd - ABS/NEG/etc +#define RI_TWO 0x0002 // Two Operands - Rs,Rd - Most Instructions +#define RI_NUM_15 0x0003 // Numeric Operand - n,Rd - n=-16..+15 - CMPQ +#define RI_NUM_31 0x0004 // Numeric Operand - n,Rd - n=0..31 - BCLR/BSET/BTST/MOVEQ +#define RI_NUM_32 0x0005 // Numeric Operand - n,Rd - n=1..32 - ADDQ/SUBQ +#define RI_JR 0x0006 // Jump Relative - cc,n - n=-16..+15 words, reg2=cc +#define RI_JUMP 0x0007 // Jump Absolute - cc,(Rs) - reg2=cc +#define RI_MOVEI 0x0008 // Move Immediate - n,Rn - n in second word +#define RI_MOVE 0x0009 // MOVE Instruction - PC,Rn / Rn,Rn +#define RI_LOAD 0x000A // LOAD Instruction - Various Forms +#define RI_LOADN 0x000B // LOADB/LOADP/LOADW - (Rs),Rd +#define RI_STORE 0x000C // STORE Instruction - Various Forms +#define RI_STOREN 0x000D // STOREB/STOREP/STOREM - Rs,(Rd) // Supplementry Instruction Flags -#define SUB32 0x2000 // (n = 32-n) -#define GPUONLY 0x4000 // Opcode is for the GPU Only -#define DSPONLY 0x8000 // Opcode is for the DSP Only +#define SUB32 0x2000 // (n = 32-n) +#define GPUONLY 0x4000 // Opcode is for the GPU Only +#define DSPONLY 0x8000 // Opcode is for the DSP Only -#define CHECK_COMMA if(*tok++ != ',') { error(comma_error); return(ERROR); } +#define CHECK_COMMA if(*tok++ != ',') { error(comma_error); return(ERROR); } // Opcode Specific Data struct opcoderecord { - short state; // Opcode Name - unsigned short typ; // Opcode Type - unsigned parm; // Opcode Parameter + short state; // Opcode Name + unsigned short typ; // Opcode Type + unsigned parm; // Opcode Parameter }; // Globals, externals etc @@ -50,10 +49,8 @@ extern unsigned orgactive; extern unsigned orgaddr; extern unsigned orgwarning; extern unsigned altbankok; -//extern int jpad; // Prototypes -int risccg(int); -int d_orgrisc(void); +int GenerateRISCCode(int); #endif // __RISCA_H__ diff --git a/rmac.c b/rmac.c index 9d7522d..9afb10a 100644 --- a/rmac.c +++ b/rmac.c @@ -37,7 +37,6 @@ int rgpu, rdsp; // Assembling Jaguar GPU or DSP code int list_fd; // File to write listing to int regbank; // RISC register bank int segpadsize; // Segment padding size -//int in_main; // In main memory flag for GPUMAIN int endian; // Host processor endianess char * objfname; // Object filename pointer char * firstfname; // First source filename @@ -560,7 +559,6 @@ int process(int argc, char ** argv) orgwarning = 0; // No ORG warning issued a_amount = 0; segpadsize = 2; // Initialise segment padding size -// in_main = 0; // Initialise modules InitSymbolTable(); // Symbol table diff --git a/rmac.h b/rmac.h index 822b4d2..7d8b526 100644 --- a/rmac.h +++ b/rmac.h @@ -183,7 +183,6 @@ extern int lsym_flag; extern int sbra_flag; extern int obj_format; extern LONG amemtot; -//extern int in_main; // Prototypes void init_sym(void); @@ -196,6 +195,5 @@ int nthpath(char *, int, char *); void clear(char *, LONG); char * copy(char *, char *, LONG); int rmac_qsort(char *, int, int, int (*)()); -//char * amem(LONG); #endif // __RMAC_H__ diff --git a/sect.c b/sect.c index 7edbfb6..f797300 100644 --- a/sect.c +++ b/sect.c @@ -17,52 +17,53 @@ #include "symbol.h" #include "token.h" + // Section descriptors -SECT sect[NSECTS]; // All sections... -int cursect; // Current section number +SECT sect[NSECTS]; // All sections... +int cursect; // Current section number // These are copied from the section descriptor, the current code chunk // descriptor and the current fixup chunk descriptor when a switch is made into // a section. They are copied back to the descriptors when the section is left. -WORD scattr; // Section attributes -LONG sloc; // Current loc in section +WORD scattr; // Section attributes +LONG sloc; // Current loc in section -CHUNK * scode; // Current (last) code chunk -LONG challoc; // # bytes alloc'd to code chunk -LONG ch_size; // # bytes used in code chunk -char * chptr; // Deposit point in code chunk buffer +CHUNK * scode; // Current (last) code chunk +LONG challoc; // # bytes alloc'd to code chunk +LONG ch_size; // # bytes used in code chunk +char * chptr; // Deposit point in code chunk buffer -CHUNK * sfix; // Current (last) fixup chunk -LONG fchalloc; // # bytes alloc'd to fixup chunk -LONG fchsize; // # bytes used in fixup chunk -PTR fchptr; // Deposit point in fixup chunk buffer +CHUNK * sfix; // Current (last) fixup chunk +LONG fchalloc; // # bytes alloc'd to fixup chunk +LONG fchsize; // # bytes used in fixup chunk +PTR fchptr; // Deposit point in fixup chunk buffer -unsigned fwdjump[MAXFWDJUMPS]; // forward jump check table -unsigned fwindex = 0; // forward jump index +unsigned fwdjump[MAXFWDJUMPS]; // forward jump check table +unsigned fwindex = 0; // forward jump index // Return a size (SIZB, SIZW, SIZL) or 0, depending on what kind of fixup is // associated with a location. static char fusiztab[] = { - 0, // FU_QUICK - 1, // FU_BYTE - 2, // FU_WORD - 2, // FU_WBYTE - 4, // FU_LONG - 1, // FU_BBRA - 0, // (unused) - 1, // FU_6BRA + 0, // FU_QUICK + 1, // FU_BYTE + 2, // FU_WORD + 2, // FU_WBYTE + 4, // FU_LONG + 1, // FU_BBRA + 0, // (unused) + 1, // FU_6BRA }; // Offset to REAL fixup location static char fusizoffs[] = { - 0, // FU_QUICK - 0, // FU_BYTE - 0, // FU_WORD - 1, // FU_WBYTE - 0, // FU_LONG - 1, // FU_BBRA - 0, // (unused) - 0, // FU_6BRA + 0, // FU_QUICK + 0, // FU_BYTE + 0, // FU_WORD + 1, // FU_WBYTE + 0, // FU_LONG + 1, // FU_BBRA + 0, // (unused) + 0, // FU_6BRA }; diff --git a/symbol.c b/symbol.c index b13ef3c..f10c55a 100644 --- a/symbol.c +++ b/symbol.c @@ -11,6 +11,7 @@ #include "procln.h" #include "error.h" + // Macros #define NBUCKETS 256 // Number of hash buckets (power of 2) diff --git a/token.c b/token.c index a1d3be8..53f76a9 100644 --- a/token.c +++ b/token.c @@ -16,6 +16,7 @@ #define DEF_KW // Declare keyword values #include "kwtab.h" // Incl generated keyword tables & defs + int lnsave; // 1; strcpy() text of current line int curlineno; // Current line number int totlines; // Total # of lines @@ -116,61 +117,6 @@ static char * riscregname[] = { }; -// Removing this, provided it doesn't cause unwanted side-effects :-P -#if 0 -// -// Make `fnum' the Current `curfname' -// NOTE: This is currently only called from error() in error.c -// -void setfnum(WORD fnum) -{ -#if 0 - // NOTE: fnum is ZERO based, this can cause problems if you're not careful! - FILEREC * fr = filerec; - - DEBUG printf("[setfnum: fnum=%u]\n", fnum); - - // Advance to the correct record... - while (fr != NULL && fnum != 0) - { - fr = fr->frec_next; - fnum--; - } - - if (fr == NULL) - curfname = "(*top*)"; - else - curfname = fr->frec_name; - - DEBUG printf("[setfnum: curfname=%s]\n", curfname); -#else - // Check for absolute top filename (this should never happen) - if (fnum == -1) - { - curfname = "(*top*)"; - return; - } - - FILEREC * fr = filerec; - - // Advance to the correct record... - while (fr != NULL && fnum != 0) - { - fr = fr->frec_next; - fnum--; - } - - // Check for file # record not found (this should never happen either) - if (fr == NULL) - { - curfname = "(*NOT FOUND*)"; - return; - } - - curfname = fr->frec_name; -#endif -} -#else void SetFilenameForErrorReporting(void) { WORD fnum = cfileno; @@ -200,7 +146,6 @@ void SetFilenameForErrorReporting(void) curfname = fr->frec_name; } -#endif // @@ -634,6 +579,8 @@ char * getmln(void) // ExpandMacro((char *)(strp + 1), imacro->im_lnbuf, LNSIZ); ExpandMacro(strp->line, imacro->im_lnbuf, LNSIZ); +// bollocks +#if 0 if (!strcmp(imacro->im_macro->sname, "mjump") && !mjump_align) { // if we need to adjust the alignment of the jump source address to @@ -657,6 +604,7 @@ char * getmln(void) mjump_align = 1; } +#endif return imacro->im_lnbuf; } @@ -683,7 +631,7 @@ char * getrln(void) return NULL; } - strp = irept->ir_nextln; //strp + strp = irept->ir_nextln; } strcpy(irbuf, (char *)(irept->ir_nextln + 1)); @@ -1610,6 +1558,7 @@ int d_goto(WORD unused) return error("goto label not found"); } + void DumpTokenBuffer(void) { TOKEN * t; @@ -1698,3 +1647,4 @@ void DumpTokenBuffer(void) printf("[EOL]\n"); } +