]> granicus.if.org Git - yasm/commitdiff
Add parsing of memory expressions. Currently adds a lot of duplication for
authorPeter Johnson <peter@tortall.net>
Fri, 12 Oct 2001 03:36:10 +0000 (03:36 -0000)
committerPeter Johnson <peter@tortall.net>
Fri, 12 Oct 2001 03:36:10 +0000 (03:36 -0000)
the expressions in the yacc code, but I don't see an easier way right now.
Also, no validity checking is done.

svn path=/trunk/yasm/; revision=279

12 files changed:
libyasm/expr.c
libyasm/expr.h
modules/arch/x86/expr.c
modules/arch/x86/x86expr.c
modules/parsers/nasm/bison.y.in
modules/parsers/nasm/nasm-bison.y
src/arch/x86/expr.c
src/arch/x86/x86expr.c
src/expr.c
src/expr.h
src/parsers/nasm/bison.y.in
src/parsers/nasm/nasm-bison.y

index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 17b0a11a27d452381ae4ed4e6e7202f22418eeda..4bcd4b923105cc8ff80c531f0d96bfb5926be833 100644 (file)
@@ -80,6 +80,7 @@ ExprItem *ExprSym(symrec *);
 ExprItem *ExprExpr(expr *);
 ExprItem *ExprInt(intnum *);
 ExprItem *ExprFloat(floatnum *);
+ExprItem *ExprReg(unsigned char reg, unsigned char size);
 
 #define expr_new_tree(l,o,r) \
     expr_new (ExprExpr(l), (o), ExprExpr(r))
index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 32ebf299881fab9f231914fb6823a0ef00d2d938..1d7e022885accdd3728bf3ee7d1f15a655d8e5ff 100644 (file)
@@ -110,7 +110,7 @@ static bytecode *nasm_parser_temp_bc;
 
 %type <bc> line lineexp exp instr instrbase
 
-%type <int_info> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg rawreg32 reg32 rawreg16 reg16 reg8 segreg
 %type <ea> mem memaddr memfar
 %type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
 %type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
@@ -222,7 +222,7 @@ fpureg: ST0
     | FPUREG_NOTST0
 ;
 
-reg32: REG_EAX
+rawreg32: REG_EAX
     | REG_ECX
     | REG_EDX
     | REG_EBX
@@ -230,10 +230,13 @@ reg32: REG_EAX
     | REG_EBP
     | REG_ESI
     | REG_EDI
+;
+
+reg32: rawreg32
     | DWORD reg32
 ;
 
-reg16: REG_AX
+rawreg16: REG_AX
     | REG_CX
     | REG_DX
     | REG_BX
@@ -241,6 +244,9 @@ reg16: REG_AX
     | REG_BP
     | REG_SI
     | REG_DI
+;
+
+reg16: rawreg16
     | WORD reg16
 ;
 
@@ -265,7 +271,48 @@ segreg:  REG_ES
 ;
 
 /* memory addresses */
-memexpr: expr
+/* FIXME: Is there any way this redundancy can be eliminated?  This is almost
+ * identical to expr: the only difference is that FLTNUM is replaced by
+ * rawreg16 and rawreg32.
+ *
+ * Note that the two can't be just combined because of conflicts caused by imm
+ * vs. reg.  I don't see a simple solution right now to this.
+ *
+ * We don't attempt to check memory expressions for validity here.
+ */
+memexpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | rawreg16                 { $$ = expr_new_ident(ExprReg($1, 16)); }
+    | rawreg32                 { $$ = expr_new_ident(ExprReg($1, 32)); }
+    | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
+    /*| memexpr '||' memexpr   { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
+    | memexpr '|' memexpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | memexpr '^' memexpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    /*| expr '&&' memexpr      { $$ = expr_new_tree($1, EXPR_LAND, $3); }*/
+    | memexpr '&' memexpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    /*| memexpr '==' memexpr   { $$ = expr_new_tree($1, EXPR_EQUALS, $3); }*/
+    /*| memexpr '>' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '<' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '>=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '<=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '!=' memexpr   { $$ = expr_new_tree($1, EXPR_NE, $3); }*/
+    | memexpr LEFT_OP memexpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | memexpr RIGHT_OP memexpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | memexpr '+' memexpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | memexpr '-' memexpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | memexpr '*' memexpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | memexpr '/' memexpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | memexpr SIGNDIV memexpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | memexpr '%' memexpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | memexpr SIGNMOD memexpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    | '+' memexpr %prec UNARYOP        { $$ = $2; }
+    | '-' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NEG, $2); }
+    /*| '!' memexpr            { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' memexpr ')'          { $$ = $2; }
+    | STRING                   {
+       $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1)));
+    }
+    | error                    { Error(_("invalid effective address")); }
 ;
 
 memaddr: memexpr           { $$ = effaddr_new_expr($1); SetEASegment($$, 0); }
index 32ebf299881fab9f231914fb6823a0ef00d2d938..1d7e022885accdd3728bf3ee7d1f15a655d8e5ff 100644 (file)
@@ -110,7 +110,7 @@ static bytecode *nasm_parser_temp_bc;
 
 %type <bc> line lineexp exp instr instrbase
 
-%type <int_info> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg rawreg32 reg32 rawreg16 reg16 reg8 segreg
 %type <ea> mem memaddr memfar
 %type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
 %type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
@@ -222,7 +222,7 @@ fpureg: ST0
     | FPUREG_NOTST0
 ;
 
-reg32: REG_EAX
+rawreg32: REG_EAX
     | REG_ECX
     | REG_EDX
     | REG_EBX
@@ -230,10 +230,13 @@ reg32: REG_EAX
     | REG_EBP
     | REG_ESI
     | REG_EDI
+;
+
+reg32: rawreg32
     | DWORD reg32
 ;
 
-reg16: REG_AX
+rawreg16: REG_AX
     | REG_CX
     | REG_DX
     | REG_BX
@@ -241,6 +244,9 @@ reg16: REG_AX
     | REG_BP
     | REG_SI
     | REG_DI
+;
+
+reg16: rawreg16
     | WORD reg16
 ;
 
@@ -265,7 +271,48 @@ segreg:  REG_ES
 ;
 
 /* memory addresses */
-memexpr: expr
+/* FIXME: Is there any way this redundancy can be eliminated?  This is almost
+ * identical to expr: the only difference is that FLTNUM is replaced by
+ * rawreg16 and rawreg32.
+ *
+ * Note that the two can't be just combined because of conflicts caused by imm
+ * vs. reg.  I don't see a simple solution right now to this.
+ *
+ * We don't attempt to check memory expressions for validity here.
+ */
+memexpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | rawreg16                 { $$ = expr_new_ident(ExprReg($1, 16)); }
+    | rawreg32                 { $$ = expr_new_ident(ExprReg($1, 32)); }
+    | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
+    /*| memexpr '||' memexpr   { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
+    | memexpr '|' memexpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | memexpr '^' memexpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    /*| expr '&&' memexpr      { $$ = expr_new_tree($1, EXPR_LAND, $3); }*/
+    | memexpr '&' memexpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    /*| memexpr '==' memexpr   { $$ = expr_new_tree($1, EXPR_EQUALS, $3); }*/
+    /*| memexpr '>' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '<' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '>=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '<=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '!=' memexpr   { $$ = expr_new_tree($1, EXPR_NE, $3); }*/
+    | memexpr LEFT_OP memexpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | memexpr RIGHT_OP memexpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | memexpr '+' memexpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | memexpr '-' memexpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | memexpr '*' memexpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | memexpr '/' memexpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | memexpr SIGNDIV memexpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | memexpr '%' memexpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | memexpr SIGNMOD memexpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    | '+' memexpr %prec UNARYOP        { $$ = $2; }
+    | '-' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NEG, $2); }
+    /*| '!' memexpr            { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' memexpr ')'          { $$ = $2; }
+    | STRING                   {
+       $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1)));
+    }
+    | error                    { Error(_("invalid effective address")); }
 ;
 
 memaddr: memexpr           { $$ = effaddr_new_expr($1); SetEASegment($$, 0); }
index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 077a45ab96684fe27b79dbf831b1c2aa75625a69..aeb600418fc5e1c18f1db900ba68237d124e433d 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
     EXPR_SYM,
     EXPR_EXPR,
     EXPR_INT,
-    EXPR_FLOAT
+    EXPR_FLOAT,
+    EXPR_REG
 } ExprType;
 
 struct ExprItem {
@@ -66,6 +67,10 @@ struct ExprItem {
        expr *expn;
        intnum *intn;
        floatnum *flt;
+       struct reg {
+           unsigned char num;
+           unsigned char size; /* in bits, eg AX=16, EAX=32 */
+       } reg;
     } data;
 };
 
@@ -142,6 +147,16 @@ ExprFloat(floatnum *f)
     return e;
 }
 
+ExprItem *
+ExprReg(unsigned char reg, unsigned char size)
+{
+    ExprItem *e = xmalloc(sizeof(ExprItem));
+    e->type = EXPR_REG;
+    e->data.reg.num = reg;
+    e->data.reg.size = size;
+    return e;
+}
+
 int
 expr_contains_float(const expr *e)
 {
@@ -159,6 +174,7 @@ expr_contains_float(const expr *e)
            break;
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -171,6 +187,7 @@ expr_contains_float(const expr *e)
            return expr_contains_float(e->right.data.expn);
        case EXPR_FLOAT:
            return 1;
+       case EXPR_REG:
        case EXPR_INT:
        case EXPR_NONE:
            break;
@@ -277,6 +294,8 @@ expr_simplify(expr *e)
 void
 expr_print(expr *e)
 {
+    static const char *regs[] = {"ax","cx","dx","bx","sp","bp","si","di"};
+
     if (e->op != EXPR_IDENT) {
        switch (e->left.type) {
            case EXPR_SYM:
@@ -293,6 +312,11 @@ expr_print(expr *e)
            case EXPR_FLOAT:
                floatnum_print(e->left.data.flt);
                break;
+           case EXPR_REG:
+               if (e->left.data.reg.size == 32)
+                   printf("e");
+               printf("%s", regs[e->left.data.reg.num]);
+               break;
            case EXPR_NONE:
                break;
        }
@@ -385,6 +409,11 @@ expr_print(expr *e)
        case EXPR_FLOAT:
            floatnum_print(e->right.data.flt);
            break;
+       case EXPR_REG:
+           if (e->right.data.reg.size == 32)
+               printf("e");
+           printf("%s", regs[e->right.data.reg.num]);
+           break;
        case EXPR_NONE:
            break;
     }
index 17b0a11a27d452381ae4ed4e6e7202f22418eeda..4bcd4b923105cc8ff80c531f0d96bfb5926be833 100644 (file)
@@ -80,6 +80,7 @@ ExprItem *ExprSym(symrec *);
 ExprItem *ExprExpr(expr *);
 ExprItem *ExprInt(intnum *);
 ExprItem *ExprFloat(floatnum *);
+ExprItem *ExprReg(unsigned char reg, unsigned char size);
 
 #define expr_new_tree(l,o,r) \
     expr_new (ExprExpr(l), (o), ExprExpr(r))
index 32ebf299881fab9f231914fb6823a0ef00d2d938..1d7e022885accdd3728bf3ee7d1f15a655d8e5ff 100644 (file)
@@ -110,7 +110,7 @@ static bytecode *nasm_parser_temp_bc;
 
 %type <bc> line lineexp exp instr instrbase
 
-%type <int_info> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg rawreg32 reg32 rawreg16 reg16 reg8 segreg
 %type <ea> mem memaddr memfar
 %type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
 %type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
@@ -222,7 +222,7 @@ fpureg: ST0
     | FPUREG_NOTST0
 ;
 
-reg32: REG_EAX
+rawreg32: REG_EAX
     | REG_ECX
     | REG_EDX
     | REG_EBX
@@ -230,10 +230,13 @@ reg32: REG_EAX
     | REG_EBP
     | REG_ESI
     | REG_EDI
+;
+
+reg32: rawreg32
     | DWORD reg32
 ;
 
-reg16: REG_AX
+rawreg16: REG_AX
     | REG_CX
     | REG_DX
     | REG_BX
@@ -241,6 +244,9 @@ reg16: REG_AX
     | REG_BP
     | REG_SI
     | REG_DI
+;
+
+reg16: rawreg16
     | WORD reg16
 ;
 
@@ -265,7 +271,48 @@ segreg:  REG_ES
 ;
 
 /* memory addresses */
-memexpr: expr
+/* FIXME: Is there any way this redundancy can be eliminated?  This is almost
+ * identical to expr: the only difference is that FLTNUM is replaced by
+ * rawreg16 and rawreg32.
+ *
+ * Note that the two can't be just combined because of conflicts caused by imm
+ * vs. reg.  I don't see a simple solution right now to this.
+ *
+ * We don't attempt to check memory expressions for validity here.
+ */
+memexpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | rawreg16                 { $$ = expr_new_ident(ExprReg($1, 16)); }
+    | rawreg32                 { $$ = expr_new_ident(ExprReg($1, 32)); }
+    | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
+    /*| memexpr '||' memexpr   { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
+    | memexpr '|' memexpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | memexpr '^' memexpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    /*| expr '&&' memexpr      { $$ = expr_new_tree($1, EXPR_LAND, $3); }*/
+    | memexpr '&' memexpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    /*| memexpr '==' memexpr   { $$ = expr_new_tree($1, EXPR_EQUALS, $3); }*/
+    /*| memexpr '>' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '<' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '>=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '<=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '!=' memexpr   { $$ = expr_new_tree($1, EXPR_NE, $3); }*/
+    | memexpr LEFT_OP memexpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | memexpr RIGHT_OP memexpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | memexpr '+' memexpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | memexpr '-' memexpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | memexpr '*' memexpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | memexpr '/' memexpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | memexpr SIGNDIV memexpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | memexpr '%' memexpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | memexpr SIGNMOD memexpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    | '+' memexpr %prec UNARYOP        { $$ = $2; }
+    | '-' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NEG, $2); }
+    /*| '!' memexpr            { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' memexpr ')'          { $$ = $2; }
+    | STRING                   {
+       $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1)));
+    }
+    | error                    { Error(_("invalid effective address")); }
 ;
 
 memaddr: memexpr           { $$ = effaddr_new_expr($1); SetEASegment($$, 0); }
index 32ebf299881fab9f231914fb6823a0ef00d2d938..1d7e022885accdd3728bf3ee7d1f15a655d8e5ff 100644 (file)
@@ -110,7 +110,7 @@ static bytecode *nasm_parser_temp_bc;
 
 %type <bc> line lineexp exp instr instrbase
 
-%type <int_info> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg rawreg32 reg32 rawreg16 reg16 reg8 segreg
 %type <ea> mem memaddr memfar
 %type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
 %type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
@@ -222,7 +222,7 @@ fpureg: ST0
     | FPUREG_NOTST0
 ;
 
-reg32: REG_EAX
+rawreg32: REG_EAX
     | REG_ECX
     | REG_EDX
     | REG_EBX
@@ -230,10 +230,13 @@ reg32: REG_EAX
     | REG_EBP
     | REG_ESI
     | REG_EDI
+;
+
+reg32: rawreg32
     | DWORD reg32
 ;
 
-reg16: REG_AX
+rawreg16: REG_AX
     | REG_CX
     | REG_DX
     | REG_BX
@@ -241,6 +244,9 @@ reg16: REG_AX
     | REG_BP
     | REG_SI
     | REG_DI
+;
+
+reg16: rawreg16
     | WORD reg16
 ;
 
@@ -265,7 +271,48 @@ segreg:  REG_ES
 ;
 
 /* memory addresses */
-memexpr: expr
+/* FIXME: Is there any way this redundancy can be eliminated?  This is almost
+ * identical to expr: the only difference is that FLTNUM is replaced by
+ * rawreg16 and rawreg32.
+ *
+ * Note that the two can't be just combined because of conflicts caused by imm
+ * vs. reg.  I don't see a simple solution right now to this.
+ *
+ * We don't attempt to check memory expressions for validity here.
+ */
+memexpr: INTNUM                        { $$ = expr_new_ident(ExprInt($1)); }
+    | rawreg16                 { $$ = expr_new_ident(ExprReg($1, 16)); }
+    | rawreg32                 { $$ = expr_new_ident(ExprReg($1, 32)); }
+    | explabel                 { $$ = expr_new_ident(ExprSym($1)); }
+    /*| memexpr '||' memexpr   { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/
+    | memexpr '|' memexpr      { $$ = expr_new_tree($1, EXPR_OR, $3); }
+    | memexpr '^' memexpr      { $$ = expr_new_tree($1, EXPR_XOR, $3); }
+    /*| expr '&&' memexpr      { $$ = expr_new_tree($1, EXPR_LAND, $3); }*/
+    | memexpr '&' memexpr      { $$ = expr_new_tree($1, EXPR_AND, $3); }
+    /*| memexpr '==' memexpr   { $$ = expr_new_tree($1, EXPR_EQUALS, $3); }*/
+    /*| memexpr '>' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '<' memexpr    { $$ = expr_new_tree($1, EXPR_GT, $3); }*/
+    /*| memexpr '>=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '<=' memexpr   { $$ = expr_new_tree($1, EXPR_GE, $3); }*/
+    /*| memexpr '!=' memexpr   { $$ = expr_new_tree($1, EXPR_NE, $3); }*/
+    | memexpr LEFT_OP memexpr  { $$ = expr_new_tree($1, EXPR_SHL, $3); }
+    | memexpr RIGHT_OP memexpr { $$ = expr_new_tree($1, EXPR_SHR, $3); }
+    | memexpr '+' memexpr      { $$ = expr_new_tree($1, EXPR_ADD, $3); }
+    | memexpr '-' memexpr      { $$ = expr_new_tree($1, EXPR_SUB, $3); }
+    | memexpr '*' memexpr      { $$ = expr_new_tree($1, EXPR_MUL, $3); }
+    | memexpr '/' memexpr      { $$ = expr_new_tree($1, EXPR_DIV, $3); }
+    | memexpr SIGNDIV memexpr  { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); }
+    | memexpr '%' memexpr      { $$ = expr_new_tree($1, EXPR_MOD, $3); }
+    | memexpr SIGNMOD memexpr  { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); }
+    | '+' memexpr %prec UNARYOP        { $$ = $2; }
+    | '-' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NEG, $2); }
+    /*| '!' memexpr            { $$ = expr_new_branch(EXPR_LNOT, $2); }*/
+    | '~' memexpr %prec UNARYOP        { $$ = expr_new_branch(EXPR_NOT, $2); }
+    | '(' memexpr ')'          { $$ = $2; }
+    | STRING                   {
+       $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1)));
+    }
+    | error                    { Error(_("invalid effective address")); }
 ;
 
 memaddr: memexpr           { $$ = effaddr_new_expr($1); SetEASegment($$, 0); }