From 17cd7246c440d6b6a20d05a86bd9f06e029573b6 Mon Sep 17 00:00:00 2001 From: michaelh Date: Sat, 19 Aug 2000 19:05:26 +0000 Subject: [PATCH] Got rid of gc_strdup, added prototype for alt lexer git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@325 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/SDCCerr.c | 12 +- src/altlex.c | 485 +++++++++++++++++++++++++++++++++++++++++++++++ src/asm.c | 68 ++++--- src/z80/gen.c | 79 +++++++- src/z80/ralloc.c | 31 +++ 5 files changed, 637 insertions(+), 38 deletions(-) create mode 100644 src/altlex.c diff --git a/src/SDCCerr.c b/src/SDCCerr.c index eb464c6f..0ad85971 100644 --- a/src/SDCCerr.c +++ b/src/SDCCerr.c @@ -2,6 +2,14 @@ #include "common.h" +#define USE_STDOUT_FOR_ERRORS 0 + +#if USE_STDOUT_FOR_ERRORS +#define ERRSINK stdout +#else +#define ERRSINK stderr +#endif + #define ERROR 0 #define WARNING 1 extern FILE *lstFile; @@ -163,10 +171,10 @@ void werror (int errNum, ... ) fatalError++ ; if ( filename && lineno ) { - fprintf(stderr,"%s(%d):",filename,lineno); + fprintf(ERRSINK, "%s(%d):",filename,lineno); } va_start(marker,errNum); - vfprintf(stderr,ErrTab[errNum].errText,marker); + vfprintf(ERRSINK, ErrTab[errNum].errText,marker); va_end( marker ); } diff --git a/src/altlex.c b/src/altlex.c new file mode 100644 index 00000000..da1862bd --- /dev/null +++ b/src/altlex.c @@ -0,0 +1,485 @@ +/** @file altlex.c + An alternate lexer to SDCC.lex. + In development - ie messy and just plain wrong. +*/ +#include "common.h" +#include + +FILE *yyin; + +int yylineno; +int column; +char *currFname; +char *yytext; + +/* Right. What are the parts of the C stream? From SDCC.lex: + D = [0..9] digits + L = [a..z A..Z _] alphanumerics and _ + H = [a..f A..F 0-9] Hex digits + E = [eE+-0-9] Digits in a float + FS = [fFlL] Specifiers for a float + IS = [uUlL] Specifiers for a int + + L[LD]* A 'token' - cant think of a good name + Check tokens against the reserved words. + If match + return the token id. + else + If in the typedef table, do stuff... + Blah. See check_type() + 0[xX]{H}+ Hex number - PENDING: specifiers + 0{D}+ Octal number - PENDING: specifiers + {D}+ Decimal - PENDING: specifiers + Floats PENDING + + Exceptions: + Comment start Strip until end of comment. + ... Ellipses + + So the inputs are: + Skip whitespace + switch class + L Try to read a token + D Try to read a number + Punct Try to read punct +*/ + +char linebuf[10000]; +int linepos, linelen; + +#define INLINE inline + +static int underflow(void) +{ + linelen = fread(linebuf, 1, sizeof(linebuf), yyin); + if (linelen <= 0) + return EOF; + linepos = 0; + return linebuf[linepos++]; +} + +static int INLINE ygetc(void) +{ + if (linepos < linelen) + return linebuf[linepos++]; + else + return underflow(); +}; + +static int INLINE yungetc(int c) +{ + linebuf[--linepos] = c; + return 0; +} + +#define GETC() ygetc() +#define UNGETC(_a) yungetc(_a) + +//#define GETC() fgetc(yyin); +//#define UNGETC(_a) ungetc(_a, yyin) +#define ISL(_a) (isalnum(_a) || _a == '_') +#define ISALNUM(_a) isalnum(_a) +#define ISHEX(_a) isalnum(_a) + +char *stringLiteral (void) +{ + static char line[1000]; + int ch; + char *str = line; + + *str++ = '\"' ; + /* put into the buffer till we hit the */ + /* first \" */ + while (1) { + + ch = GETC(); + if (!ch) break ; /* end of input */ + /* if it is a \ then everything allowed */ + if (ch == '\\') { + *str++ = ch ; /* backslash in place */ + *str++ = GETC() ; /* following char in place */ + continue ; /* carry on */ + } + + /* if new line we have a new line break */ + if (ch == '\n') break ; + + /* if this is a quote then we have work to do */ + /* find the next non whitespace character */ + /* if that is a double quote then carry on */ + if (ch == '\"') { + + while ((ch = GETC()) && isspace(ch)) ; + if (!ch) break ; + if (ch != '\"') { + UNGETC(ch) ; + break ; + } + + continue ; + } + *str++ = ch; + } + *str++ = '\"' ; + *str = '\0'; + return line; +} + +void discard_comments(int type) +{ + int c; + if (type == '*') { + do { + c = GETC(); + if (c == '*') { + c = GETC(); + if (c == '/') + return; + } + else if (c == EOF) + return; + } while (1); + } + else if (type == '/') { + while (c != '\n' && c != EOF) { + c = GETC(); + } + } + else { + assert(0); + } +} + +#define TKEYWORD(_a) return _a + +int check_token(const char *sz) +{ + if (!strcmp(sz, "at")) { + TKEYWORD(AT) ; } + + else if (!strcmp(sz, "auto")) { + return(AUTO); } + + else if (!strcmp(sz, "bit")) { + TKEYWORD(BIT) ; } + + else if (!strcmp(sz, "break")) { + return(BREAK); } + + else if (!strcmp(sz, "case")) { + return(CASE); } + + else if (!strcmp(sz, "char")) { + return(CHAR); } + + else if (!strcmp(sz, "code")) { + TKEYWORD(CODE); } + + else if (!strcmp(sz, "const")) { + return(CONST); } + + else if (!strcmp(sz, "continue")) { + return(CONTINUE); } + + else if (!strcmp(sz, "critical")) { + TKEYWORD(CRITICAL); } + + else if (!strcmp(sz, "data")) { + TKEYWORD(DATA); } + + else if (!strcmp(sz, "default")) { + return(DEFAULT); } + + else if (!strcmp(sz, "do")) { + return(DO); } + + else if (!strcmp(sz, "double")) { + werror(W_DOUBLE_UNSUPPORTED);return(FLOAT); } + + else if (!strcmp(sz, "else")) { + return(ELSE); } + + else if (!strcmp(sz, "enum")) { + return(ENUM); } + + else if (!strcmp(sz, "extern")) { + return(EXTERN); } + + else if (!strcmp(sz, "far")) { + TKEYWORD(XDATA); } + + else if (!strcmp(sz, "eeprom")) { + TKEYWORD(EEPROM); } + + else if (!strcmp(sz, "float")) { + return(FLOAT); } + + else if (!strcmp(sz, "flash")) { + TKEYWORD(CODE);} + + else if (!strcmp(sz, "for")) { + return(FOR); } + + else if (!strcmp(sz, "goto")) { + return(GOTO); } + + else if (!strcmp(sz, "idata")) { + TKEYWORD(IDATA);} + + else if (!strcmp(sz, "if")) { + return(IF); } + + else if (!strcmp(sz, "int")) { + return(INT); } + + else if (!strcmp(sz, "interrupt")) { + return(INTERRUPT);} + + else if (!strcmp(sz, "nonbanked")) { + TKEYWORD(NONBANKED);} + + else if (!strcmp(sz, "banked")) { + TKEYWORD(BANKED);} + + else if (!strcmp(sz, "long")) { + return(LONG); } + + else if (!strcmp(sz, "near")) { + TKEYWORD(DATA);} + + else if (!strcmp(sz, "pdata")) { + TKEYWORD(PDATA); } + + else if (!strcmp(sz, "reentrant")) { + TKEYWORD(REENTRANT);} + + else if (!strcmp(sz, "register")) { + return(REGISTER); } + + else if (!strcmp(sz, "return")) { + return(RETURN); } + + else if (!strcmp(sz, "sfr")) { + TKEYWORD(SFR) ; } + + else if (!strcmp(sz, "sbit")) { + TKEYWORD(SBIT) ; } + + else if (!strcmp(sz, "short")) { + return(SHORT); } + + else if (!strcmp(sz, "signed")) { + return(SIGNED); } + + else if (!strcmp(sz, "sizeof")) { + return(SIZEOF); } + + else if (!strcmp(sz, "sram")) { + TKEYWORD(XDATA);} + + else if (!strcmp(sz, "static")) { + return(STATIC); } + + else if (!strcmp(sz, "struct")) { + return(STRUCT); } + + else if (!strcmp(sz, "switch")) { + return(SWITCH); } + + else if (!strcmp(sz, "typedef")) { + return(TYPEDEF); } + + else if (!strcmp(sz, "union")) { + return(UNION); } + + else if (!strcmp(sz, "unsigned")) { + return(UNSIGNED); } + + else if (!strcmp(sz, "void")) { + return(VOID); } + + else if (!strcmp(sz, "volatile")) { + return(VOLATILE); } + + else if (!strcmp(sz, "using")) { + TKEYWORD(USING); } + + else if (!strcmp(sz, "while")) { + return(WHILE); } + + else if (!strcmp(sz, "xdata")) { + TKEYWORD(XDATA); } + + else if (!strcmp(sz, "_data")) { + TKEYWORD(_NEAR); } + + else if (!strcmp(sz, "_code")) { + TKEYWORD(_CODE); } + + else if (!strcmp(sz, "_eeprom")) { + TKEYWORD(_EEPROM); } + + else if (!strcmp(sz, "_flash")) { + TKEYWORD(_CODE); } + + else if (!strcmp(sz, "_generic")) { + TKEYWORD(_GENERIC); } + + else if (!strcmp(sz, "_near")) { + TKEYWORD(_NEAR); } + + else if (!strcmp(sz, "_sram")) { + TKEYWORD(_XDATA);} + + else if (!strcmp(sz, "_xdata")) { + TKEYWORD(_XDATA);} + + else if (!strcmp(sz, "_pdata")) { + TKEYWORD(_PDATA); } + + else if (!strcmp(sz, "_idata")) { + TKEYWORD(_IDATA); } + + /* check if it is in the typedef table */ + if (findSym(TypedefTab,NULL,sz)) { + strcpy(yylval.yychar,sz); + return (TYPE_NAME) ; + } + else { + strcpy (yylval.yychar,sz); + return(IDENTIFIER); + } +} + +int yylex(void) +{ + int c; + char line[128]; + char *p; + + c = GETC(); + while (1) { + /* Handle comments first */ + if (c == '/') { + int c2 = GETC(); + if (c2 == '*' || c2 == '/') { + discard_comments(c2); + c = GETC(); + continue; + } + else + UNGETC(c2); + } + switch (c) { + case EOF: + return 0; + case ' ': + case '\t': + case '\r': + case '\n': + /* Skip whitespace */ + break; + case 'a': case 'b': case 'c': case 'd': + case 'e': case 'f': case 'g': case 'h': + case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': + case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': + case 'E': case 'F': case 'G': case 'H': + case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': + case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '_': + /* Start of a token. Parse. */ + p = line; + *p++ = c; + c = GETC(); + while (ISL(c)) { + *p++ = c; + c = GETC(); + } + *p = '\0'; + UNGETC(c); + return check_token(line); + case '0': case '1': + case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + p = line; + *p++ = c; + c = GETC(); + if (c == 'x' || c == 'X') { + *p++ = c; + c = GETC(); + } + while (ISHEX(c)) { + *p++ = c; + c = GETC(); + } + *p = '\0'; + UNGETC(c); + yylval.val = constVal(line); + return CONSTANT; + case '\"': + /* A string */ + p = stringLiteral(); + yylval.val = strVal(p); + return(STRING_LITERAL); + case '\'': + /* ie '\n' */ + break; + case '#': + /* Assume a pragma and toast the rest of the line. */ + c = GETC(); + while (c != '\n') { + c = GETC(); + } + break; + case '=': + case '&': + case '!': + case '-': + case '+': + case '*': + case '/': + case '%': + case '<': + case '>': + case '^': + case '|': + /* Cases which can be compounds */ + return c; + case '{': + NestLevel++; + return c; + case '}': + NestLevel--; + return c; + case '.': + c = GETC(); + if (c == '.') { + c = GETC(); + if (c == '.') { + return VAR_ARGS; + } + } + UNGETC(c); + /* Fall through */ + case ',': + case ':': + case '(': case ')': + case '[': case ']': + case '~': + case '?': + /* Special characters that cant be part of a composite */ + return c; + default: + printf("Unhandled char %c\n", c); + } + c = GETC(); + } + return 0; +} diff --git a/src/asm.c b/src/asm.c index 3d2195a7..1e0dd64b 100644 --- a/src/asm.c +++ b/src/asm.c @@ -1,6 +1,18 @@ +/** @file asm.c + Provides output functions that modify the output string + based on the input tokens and the assembler token mapping + specification loaded. + + Note that the functions below only handle digit format modifiers. + eg %02X is ok, but %lu and %.4u will fail. +*/ #include "common.h" #include "asm.h" +/* A 'token' is like !blah or %24f and is under the programmers + control. */ +#define MAX_TOKEN_LEN 64 + static hTab *_h; static const char *_findMapping(const char *szKey) @@ -8,10 +20,10 @@ static const char *_findMapping(const char *szKey) return shash_find(_h, szKey); } -static va_list _iprintf(char *pInto, const char *szFormat, va_list ap) +static va_list _iprintf(char *pInto, const char *sz, va_list ap) { + char format[MAX_TOKEN_LEN]; char *pStart = pInto; - char *sz = gc_strdup(szFormat); static int count; while (*sz) { @@ -40,16 +52,15 @@ static va_list _iprintf(char *pInto, const char *szFormat, va_list ap) default: { /* Scan out the arg and pass it on to sprintf */ - char *p = sz-1, tmp; + char *p = format; + *p++ = '%'; while (isdigit(*sz)) - sz++; - /* Skip the format */ - tmp = *++sz; - *sz = '\0'; - vsprintf(pInto, p, ap); + *p++ = *sz++; + *p++ = *sz++; + *p = '\0'; + vsprintf(pInto, format, ap); /* PENDING: Assume that the arg length was an int */ va_arg(ap, int); - *sz = tmp; } } pInto = pStart + strlen(pStart); @@ -63,10 +74,11 @@ static va_list _iprintf(char *pInto, const char *szFormat, va_list ap) return ap; } -void tvsprintf(char *buffer, const char *szFormat, va_list ap) +void tvsprintf(char *buffer, const char *sz, va_list ap) { - char *sz = gc_strdup(szFormat); - char *pInto = buffer, *p; + char *pInto = buffer; + char *p; + char token[MAX_TOKEN_LEN]; buffer[0] = '\0'; @@ -74,37 +86,33 @@ void tvsprintf(char *buffer, const char *szFormat, va_list ap) if (*sz == '!') { /* Start of a token. Search until the first [non alplha, *] and call it a token. */ - char old; const char *t; - p = ++sz; + p = token; + sz++; while (isalpha(*sz) || *sz == '*') { - sz++; + *p++ = *sz++; } - old = *sz; - *sz = '\0'; + *p = '\0'; /* Now find the token in the token list */ - if ((t = _findMapping(p))) { + if ((t = _findMapping(token))) { ap = _iprintf(pInto, t, ap); pInto = buffer + strlen(buffer); } else { - fprintf(stderr, "Cant find token \"%s\"\n", p); + fprintf(stderr, "Cant find token \"%s\"\n", token); wassert(0); } - *sz = old; } else if (*sz == '%') { - char *pFormat = sz; - char old; - sz++; - while (!isalpha(*sz)) - sz++; - sz++; - old = *sz; - *sz = '\0'; - vsprintf(pInto, pFormat, ap); + p = token; + *p++ = *sz++; + while (!isalpha(*sz)) { + *p++ = *sz++; + } + *p++ = *sz++; + *p = '\0'; + vsprintf(pInto, token, ap); pInto = buffer + strlen(buffer); - *sz = old; va_arg(ap, int); } else { diff --git a/src/z80/gen.c b/src/z80/gen.c index e33f3281..003f5946 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -723,8 +723,10 @@ char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash) /* otherwise it is fairly simple */ if (!IS_FLOAT(val->type)) { unsigned long v = floatFromVal(val); + if (offset == 2) v >>= 16; + if (with_hash) tsprintf(buffer, "!immedword", v); else @@ -802,6 +804,26 @@ static bool requiresHL(asmop *aop) } } +static char *fetchLitSpecial(asmop *aop, bool negate, bool xor) +{ + unsigned long v; + value * val = aop->aopu.aop_lit; + + wassert(aop->type == AOP_LIT); + wassert(!IS_FLOAT(val->type)); + + v = floatFromVal(val); + + if (xor) + v ^= 0x8000; + if (negate) + v = -v; + v &= 0xFFFF; + + tsprintf(buffer, "!immedword", v); + return gc_strdup(buffer); +} + static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset) { const char *l; @@ -1274,7 +1296,7 @@ void outAcc(operand *result) /** Take the value in carry and put it into a register */ -void outBitC(operand *result) +void outBitCLong(operand *result, bool swap_sense) { /* if the result is bit */ if (AOP_TYPE(result) == AOP_CRY) { @@ -1284,10 +1306,17 @@ void outBitC(operand *result) else { emit2("ld a,!zero"); emit2("rla"); + if (swap_sense) + emit2("xor a,!immedbyte", 1); outAcc(result); } } +void outBitC(operand *result) +{ + outBitCLong(result, FALSE); +} + /*-----------------------------------------------------------------*/ /* toBoolean - emit code for orl a,operator(sizeop) */ /*-----------------------------------------------------------------*/ @@ -2546,7 +2575,7 @@ static void genIfxJump (iCode *ic, char *jval) /* if true label then we jump if condition supplied is true */ - if ( IC_TRUE(ic) ) { + if (IC_TRUE(ic)) { jlbl = IC_TRUE(ic); if (!strcmp(jval, "a")) { inst = "nz"; @@ -2554,6 +2583,9 @@ static void genIfxJump (iCode *ic, char *jval) else if (!strcmp(jval, "c")) { inst = "c"; } + else if (!strcmp(jval, "nc")) { + inst = "nc"; + } else { /* The buffer contains the bit on A that we should test */ inst = "nz"; @@ -2568,6 +2600,9 @@ static void genIfxJump (iCode *ic, char *jval) else if (!strcmp(jval, "c")) { inst = "nc"; } + else if (!strcmp(jval, "nc")) { + inst = "c"; + } else { /* The buffer contains the bit on A that we should test */ inst = "z"; @@ -2579,6 +2614,8 @@ static void genIfxJump (iCode *ic, char *jval) } else if (!strcmp(jval, "c")) { } + else if (!strcmp(jval, "nc")) { + } else { emitcode("bit", "%s,a", jval); } @@ -2588,6 +2625,11 @@ static void genIfxJump (iCode *ic, char *jval) ic->generated = 1; } +const char *getPairIdName(PAIR_ID id) +{ + return _pairs[id].name; +} + /** Generic compare for > or < */ static void genCmp (operand *left,operand *right, @@ -2595,6 +2637,7 @@ static void genCmp (operand *left,operand *right, { int size, offset = 0 ; unsigned long lit = 0L; + bool swap_sense = FALSE; /* if left & right are bit variables */ if (AOP_TYPE(left) == AOP_CRY && @@ -2619,6 +2662,30 @@ static void genCmp (operand *left,operand *right, emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE)); } else { + /* Special cases: + On the GB: + If the left or the right is a lit: + Load -lit into HL, add to right via, check sense. + */ + if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) { + asmop *lit = AOP(right); + asmop *op = AOP(left); + swap_sense = TRUE; + if (AOP_TYPE(left) == AOP_LIT) { + swap_sense = FALSE; + lit = AOP(left); + op = AOP(right); + } + if (sign) { + emit2("ld e,%s", aopGet(op, 0, 0)); + emit2("ld a,%s", aopGet(op, 1, 0)); + emit2("xor a,!immedbyte", 0x80); + emit2("ld d,a"); + } + emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign)); + emit2("add hl,de"); + goto release; + } if(AOP_TYPE(right) == AOP_LIT) { lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); /* optimize if(x < 0) or if(x >= 0) */ @@ -2692,15 +2759,15 @@ static void genCmp (operand *left,operand *right, release: if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { - outBitC(result); + outBitCLong(result, swap_sense); } else { /* if the result is used in the next ifx conditional branch then generate code a little differently */ - if (ifx ) - genIfxJump (ifx,"c"); + if (ifx) + genIfxJump(ifx, swap_sense ? "nc" : "c"); else - outBitC(result); + outBitCLong(result, swap_sense); /* leave the result in acc */ } } diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index 90d6f6fb..75127f84 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -1899,6 +1899,36 @@ bool opPreservesA(iCode *ic, iCode *uic) return FALSE; } +static void joinPushes(iCode *ic) +{ +#if 0 + if (ic->op == IPUSH && + isOperandLiteral(IC_LEFT(ic)) && + getSize(operandType(IC_LEFT(ic))) == 1 && + ic->next->op == IPUSH && + isOperandLiteral(IC_LEFT(ic->next)) && + getSize(operandType(IC_LEFT(ic->next))) == 1) { + /* This is a bit tricky as michaelh doesnt know what he's doing. + */ + /* First upgrade the size of (first) to int */ + SPEC_NOUN(operandType(IC_LEFT(ic))) = V_INT; + SPEC_SHORT(operandType(IC_LEFT(ic))) = 0; + + floatFromVal(AOP + /* Now get and join the values */ + value * val = aop->aopu.aop_lit; + /* if it is a float then it gets tricky */ + /* otherwise it is fairly simple */ + if (!IS_FLOAT(val->type)) { + unsigned long v = floatFromVal(val); + + floatFrom + printf("Size %u\n", getSize(operandType(IC_LEFT(ic)))); + ic->next = ic->next->next; + } +#endif +} + /** Pack registers for acc use. When the result of this operation is small and short lived it may be able to be stored in the accumulator. @@ -2222,6 +2252,7 @@ static void packRegisters (eBBlock *ebp) packRegsForAccUse2(ic); } #endif + joinPushes(ic); } } -- 2.39.5