Add support for assemble-time assertions.
authorMichael Buesch <mb@bu3sch.de>
Mon, 9 Jun 2008 15:56:27 +0000 (17:56 +0200)
committerMichael Buesch <mb@bu3sch.de>
Mon, 9 Jun 2008 15:56:27 +0000 (17:56 +0200)
Signed-off-by: Michael Buesch <mb@bu3sch.de>
assembler/parser.y
assembler/scanner.l
assembler/test.asm

index f0151211741a9073e532eb690fbf681dcb2f1d99..e75d9f4d371873ae1d0ab2e7d3f3c757e313ad5f 100644 (file)
@@ -28,6 +28,7 @@ extern int yyparse(void);
 extern int yylex(void);
 
 static struct operand * store_oper_sanity(struct operand *oper);
+static void assembler_assertion_failed(void);
 
 /* The current .section */
 extern int section;
@@ -38,9 +39,9 @@ extern struct initvals_sect *cur_initvals_sect;
 
 %token SECTION_TEXT SECTION_IVALS
 
-%token ASM_ARCH ASM_START SPR GPR OFFR LR COMMA SEMICOLON BRACK_OPEN BRACK_CLOSE PAREN_OPEN PAREN_CLOSE HEXNUM DECNUM ARCH_NEWWORLD ARCH_OLDWORLD LABEL IDENT LABELREF
+%token ASM_ARCH ASM_START ASM_ASSERT SPR GPR OFFR LR COMMA SEMICOLON BRACK_OPEN BRACK_CLOSE PAREN_OPEN PAREN_CLOSE HEXNUM DECNUM ARCH_NEWWORLD ARCH_OLDWORLD LABEL IDENT LABELREF
 
-%token PLUS MINUS MULTIPLY DIVIDE BITW_OR BITW_AND BITW_XOR BITW_NOT LEFTSHIFT RIGHTSHIFT
+%token EQUAL NOT_EQUAL LOGICAL_OR LOGICAL_AND PLUS MINUS MULTIPLY DIVIDE BITW_OR BITW_AND BITW_XOR BITW_NOT LEFTSHIFT RIGHTSHIFT
 
 %token OP_ADD OP_ADDSC OP_ADDC OP_ADDSCC OP_SUB OP_SUBSC OP_SUBC OP_SUBSCC OP_SRA OP_OR OP_AND OP_XOR OP_SR OP_SRX OP_SL OP_RL OP_RR OP_NAND OP_ORX OP_MOV OP_JMP OP_JAND OP_JNAND OP_JS OP_JNS OP_JE OP_JNE OP_JLS OP_JGES OP_JGS OP_JLES OP_JL OP_JGE OP_JG OP_JLE OP_JZX OP_JNZX OP_JEXT OP_JNEXT OP_CALL OP_RET OP_TKIPH OP_TKIPHS OP_TKIPL OP_TKIPLS OP_NAP RAW_CODE
 
@@ -55,10 +56,12 @@ line        : line_terminator {
          }
        | line statement line_terminator {
                struct statement *s = $2;
-               if (section != SECTION_TEXT)
-                       yyerror("Microcode text instruction in non .text section");
-               memcpy(&s->info, &cur_lineinfo, sizeof(struct lineinfo));
-               list_add_tail(&s->list, &infile.sl);
+               if (s) {
+                       if (section != SECTION_TEXT)
+                               yyerror("Microcode text instruction in non .text section");
+                       memcpy(&s->info, &cur_lineinfo, sizeof(struct lineinfo));
+                       list_add_tail(&s->list, &infile.sl);
+               }
          }
        | line section_switch line_terminator {
          }
@@ -149,11 +152,15 @@ ivals_write       : IVAL_MMIO16 imm_value COMMA imm_value {
                ;
 
 statement      : asmdir {
-                       struct statement *s = xmalloc(sizeof(struct statement));
-                       INIT_LIST_HEAD(&s->list);
-                       s->type = STMT_ASMDIR;
-                       s->u.asmdir = $1;
-                       $$ = s;
+                       struct asmdir *ad = $1;
+                       if (ad) {
+                               struct statement *s = xmalloc(sizeof(struct statement));
+                               INIT_LIST_HEAD(&s->list);
+                               s->type = STMT_ASMDIR;
+                               s->u.asmdir = $1;
+                               $$ = s;
+                       } else
+                               $$ = NULL;
                  }
                | label {
                        struct statement *s = xmalloc(sizeof(struct statement));
@@ -509,6 +516,43 @@ asmdir             : ASM_ARCH hexnum_decnum {
                        ad->u.start = label;
                        $$ = ad;
                  }
+               | ASM_ASSERT assertion {
+                       unsigned int ok = (unsigned int)(unsigned long)$2;
+                       if (!ok)
+                               assembler_assertion_failed();
+                       $$ = NULL;
+                 }
+               ;
+
+assertion      : PAREN_OPEN assert_expr PAREN_CLOSE {
+                       $$ = $2;
+                 }
+               | PAREN_OPEN assertion LOGICAL_OR assertion PAREN_CLOSE {
+                       unsigned int a = (unsigned int)(unsigned long)$2;
+                       unsigned int b = (unsigned int)(unsigned long)$4;
+                       unsigned int result = (a || b);
+                       $$ = (void *)(unsigned long)result;
+                 }
+               | PAREN_OPEN assertion LOGICAL_AND assertion PAREN_CLOSE {
+                       unsigned int a = (unsigned int)(unsigned long)$2;
+                       unsigned int b = (unsigned int)(unsigned long)$4;
+                       unsigned int result = (a && b);
+                       $$ = (void *)(unsigned long)result;
+                 }
+               ;
+
+assert_expr    : imm_value EQUAL imm_value {
+                       unsigned int a = (unsigned int)(unsigned long)$1;
+                       unsigned int b = (unsigned int)(unsigned long)$3;
+                       unsigned int result = (a == b);
+                       $$ = (void *)(unsigned long)result;
+                 }
+               | imm_value NOT_EQUAL imm_value {
+                       unsigned int a = (unsigned int)(unsigned long)$1;
+                       unsigned int b = (unsigned int)(unsigned long)$3;
+                       unsigned int result = (a != b);
+                       $$ = (void *)(unsigned long)result;
+                 }
                ;
 
 label          : LABEL {
@@ -1308,3 +1352,8 @@ static struct operand * store_oper_sanity(struct operand *oper)
        }
        return oper;
 }
+
+static void assembler_assertion_failed(void)
+{
+       yyerror("Assembler %assert failed");
+}
index 16f375ca2d0fa974268b70ab6770d47a6312a213..6fb3599c0ac16586568ed71cceee80990d8d79ec 100644 (file)
@@ -51,6 +51,7 @@ NEWLINE               ((\r)|(\n)|(\r\n))
 
 ^{WS}*"%"{WS}*arch     { update_lineinfo(); return ASM_ARCH; }
 ^{WS}*"%"{WS}*start    { update_lineinfo(); return ASM_START; }
+^{WS}*"%"{WS}*assert   { update_lineinfo(); return ASM_ASSERT; }
 
 ^{WS}*\.text{WS}*$                     { update_lineinfo(); return SECTION_TEXT; }
 ^{WS}*\.initvals/\({IDENTIFIER}\)      { update_lineinfo(); return SECTION_IVALS; }
@@ -67,6 +68,10 @@ lr/[0-3]             { update_lineinfo(); return LR; }
 \(                     { update_lineinfo(); return PAREN_OPEN; }
 \)                     { update_lineinfo(); return PAREN_CLOSE; }
 
+==                     { update_lineinfo(); return EQUAL; }
+!=                     { update_lineinfo(); return NOT_EQUAL; }
+\|\|                   { update_lineinfo(); return LOGICAL_OR; }
+\&\&                   { update_lineinfo(); return LOGICAL_AND; }
 \+                     { update_lineinfo(); return PLUS; }
 \-                     { update_lineinfo(); return MINUS; }
 \*                     { update_lineinfo(); return MULTIPLY; }
index 54dafed419445b9f360c82fe5be076f6e1b4f1ea..ecbc2732179a202efa7e275bf3924d038d261333 100644 (file)
 
 #define ECOND_MAC_ON   (0x20 | 4)
 
+%assert ((((1))) == ((((2 - 1) & 0xFF))))
+%assert ((1 == 2) || (1 == (0xFF & 1)))
+%assert (1 != (~1))
+%assert ((1 == (2 - 1)) && (2 == 2))
 
 .text