Added basic support for .area and .ds directives to the xa51 assembler.
authorpjs <pjs@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 20 Jan 2002 00:11:13 +0000 (00:11 +0000)
committerpjs <pjs@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 20 Jan 2002 00:11:13 +0000 (00:11 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1820 4a8a32a2-be11-0410-ad9d-d568d2c75423

as/xa51/xa_asm.l
as/xa51/xa_asm.y
as/xa51/xa_main.c
as/xa51/xa_main.h

index 15b5e93a11916acae7f8f5248cecdcc9e3e6156e..d28e86a06277f988ead27158124780da1a163319 100644 (file)
@@ -198,6 +198,25 @@ dw         {LIST; return DW;}
 byte           {LIST; return DB;}
 bit            {LIST; return BITDEF;}
 reg            {LIST; return REGDEF;}
+area           {LIST; return AREA;}
+ds             {LIST; return DS;}
+DSEG           {LIST; yylval = AREA_DSEG; return AREA_NAME;}
+OSEG           {LIST; yylval = AREA_OSEG; return AREA_NAME;}
+ISEG           {LIST; yylval = AREA_ISEG; return AREA_NAME;}
+BSEG           {LIST; yylval = AREA_BSEG; return AREA_NAME;}
+XSEG           {LIST; yylval = AREA_XSEG; return AREA_NAME;}
+XISEG          {LIST; yylval = AREA_XISEG; return AREA_NAME;}
+GSINIT         {LIST; yylval = AREA_GSINIT; return AREA_NAME;}
+GSFINAL                {LIST; yylval = AREA_GSFINAL; return AREA_NAME;}
+HOME           {LIST; yylval = AREA_HOME; return AREA_NAME;}
+CSEG           {LIST; yylval = AREA_CSEG; return AREA_NAME;}
+module         {LIST; return MODULE;}
+globl          {LIST; return GLOBL;}
+\(DATA\)       {LIST; return AREA_DESC;}
+\(OVR,DATA\)   {LIST; return AREA_DESC;}
+\(BIT\)                {LIST; return AREA_DESC;}
+\(XDATA\)      {LIST; return AREA_DESC;}
+\(CODE\)       {LIST; return AREA_DESC;}
 low            {LIST; return LOW;}
 high           {LIST; return HIGH;}
 >>             {LIST; return RSHIFT;}
index aa18e0af83e0ecc82704f74a024b3d85fdeb4cae..2960a1a926db86d004bd703cad585809a659428c 100644 (file)
@@ -56,6 +56,8 @@ static int bitmask[]={1, 2, 4, 8, 16, 32, 64, 128};
 %token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
 %token ORG EQU DB DW BITDEF REGDEF LOW HIGH
 %token RSHIFT LSHIFT
+%token AREA AREA_NAME AREA_DESC DS
+%token MODULE GLOBL 
 
 %left '&' '|' '^'
 %left RSHIFT LSHIFT
@@ -69,10 +71,18 @@ all:           line
              | line all;
 
 line:          linesymbol ':' linenosym {
-                       if (p1) build_sym_list(symbol_name);
-                       if (p2) assign_value(symbol_name, mem);
-                       mem += $3; }
-             | linenosym {mem += $1;}
+                       if (p1) {
+                               build_sym_list(symbol_name);
+                               if (current_area == AREA_BSEG) {
+                                       mk_bit(symbol_name);
+                               }
+                       }
+                       if (p1 || p2) assign_value(symbol_name, MEM_POS);
+                       MEM_POS += $3;
+               }
+             | linenosym {
+                       MEM_POS += $1;
+               }
 
 linenosym:     directive EOL {
                        if (p3) out(op, $1);
@@ -88,12 +98,13 @@ linenosym:     directive EOL {
                }
             | error EOL        /* try to recover from any parse error */
 
+
 directive:     '.' ORG expr {
-                       mem = $3;
+                       MEM_POS = $3;
                        $$ = 0;
                }
             | ORG expr {
-                       mem = $2;
+                       MEM_POS = $2;
                        $$ = 0;
                }
              | '.' EQU symbol ',' expr { 
@@ -145,9 +156,39 @@ directive:     '.' ORG expr {
             | dw_directive words {
                        $$ = dw_count;
                }
+            | '.' AREA AREA_NAME AREA_DESC {
+                       if ($3 < 0 || $3 >= NUM_AREAS) {
+                               error("Illegal Area Directive");
+                       }
+                       symbol_name[0] = '\0';
+                       current_area = $3;
+                       $$ = 0;
+               }
+            | '.' MODULE WORD {
+                       /* ignore module definition */
+                       $$ = 0;
+               }
+            | '.' GLOBL WORD {
+                       /* ignore global symbol declaration */
+                       $$ = 0;
+               }
+            | '.' DS expr {
+                       /* todo: if CSEG, emit some filler bytes */
+                       $$ = $3;
+               }
 
 db_directive:  DB {db_count = 0;}
 
+
+linesymbol:    WORD  { 
+                       strcpy(symbol_name, lex_sym_name);
+                       if (!strchr(lex_sym_name, ':')) {
+                               /* non-local label, remember base name */
+                               strcpy(base_symbol_name, lex_sym_name);
+                       }
+                       if (is_target(symbol_name)) pad_with_nop();
+               }
+
 bytes:           byte_element
                | bytes ',' byte_element
 
@@ -184,14 +225,6 @@ word_element:      expr {
                }
 
 
-linesymbol:    WORD  { 
-                       strcpy(symbol_name, lex_sym_name);
-                       if (!strchr(lex_sym_name, ':')) {
-                               /* non-local label, remember base name */
-                               strcpy(base_symbol_name, lex_sym_name);
-                       }
-                       if (is_target(symbol_name)) pad_with_nop();
-               }
 
 symbol:     WORD  {
                strcpy(symbol_name, lex_sym_name);
@@ -917,20 +950,20 @@ instruction:
 | JMP jmpaddr {
        $$ = 3;
        op[0] = 0xD5;
-       op[1] = msb(rel16(mem + $$, $2));
-       op[2] = lsb(rel16(mem + $$, $2));
+       op[1] = msb(rel16(MEM_POS + $$, $2));
+       op[2] = lsb(rel16(MEM_POS + $$, $2));
   }
 
 | CALL jmpaddr {
         $$ = 3;
         op[0] = 0xC5;
-        op[1] = msb(rel16(mem + $$, $2));
-        op[2] = lsb(rel16(mem + $$, $2));
+        op[1] = msb(rel16(MEM_POS + $$, $2));
+        op[2] = lsb(rel16(MEM_POS + $$, $2));
   }
 | branch_inst jmpaddr {
        $$ = 2;
        op[0] = branch_opcode;
-       op[1] = rel8(mem + $$, $2);
+       op[1] = rel8(MEM_POS + $$, $2);
   }
 | CJNE REG ',' expr ',' jmpaddr {
         $$ = 4;
@@ -938,7 +971,7 @@ instruction:
        op[0] = 0xE2 + size * 8;
        op[1] = reg($2) * 16 + msb(direct_addr($4));
        op[2] = lsb(direct_addr($4));
-       op[3] = rel8(mem + $$, $6);
+       op[3] = rel8(MEM_POS + $$, $6);
   }
 | CJNE REG ',' '#' expr ',' jmpaddr {
        size  = find_size1(inst_size, $2);
@@ -946,13 +979,13 @@ instruction:
                $$ = 4;
                op[0] = 0xE3;
                op[1] = reg($2) * 16;
-               op[2] = rel8(mem + $$, $7);
+               op[2] = rel8(MEM_POS + $$, $7);
                op[3] = imm_data8($5);
        } else {
                $$ = 5;
                op[0] = 0xEB;
                op[1] = reg($2) * 16;
-               op[2] = rel8(mem + $$, $7);
+               op[2] = rel8(MEM_POS + $$, $7);
                op[3] = msb(imm_data16($5));
                op[4] = lsb(imm_data16($5));
        }
@@ -963,13 +996,13 @@ instruction:
                $$ = 4;
                op[0] = 0xE3;
                op[1] = reg_indirect($3) * 16 + 8;
-               op[2] = rel8(mem + $$, $9);
+               op[2] = rel8(MEM_POS + $$, $9);
                op[3] = imm_data8($7);
        } else {
                $$ = 5;
                op[0] = 0xEB;
                op[1] = reg_indirect($3) * 16 + 8;
-               op[2] = rel8(mem + $$, $9);
+               op[2] = rel8(MEM_POS + $$, $9);
                op[3] = msb(imm_data16($7));
                op[4] = lsb(imm_data16($7));
        }
@@ -979,7 +1012,7 @@ instruction:
        size  = find_size1(inst_size, $2);
        op[0] = 0x87 + size * 8;
        op[1] = reg($2) * 16 + 8;
-       op[2] = rel8(mem + $$, $4);
+       op[2] = rel8(MEM_POS + $$, $4);
   }
 
 
@@ -989,7 +1022,7 @@ instruction:
        op[0] = 0xE2 + size * 8;
        op[1] = msb(direct_addr($2)) + 8;
        op[2] = lsb(direct_addr($2));
-       op[3] = rel8(mem + $$, $4);
+       op[3] = rel8(MEM_POS + $$, $4);
   }
 
 | JB bit ',' jmpaddr {
@@ -997,7 +1030,7 @@ instruction:
        op[0] = 0x97;
        op[1] = 0x80 + msb(bit_addr($2));
        op[2] = lsb(bit_addr($2));
-       op[3] = rel8(mem + $$, $4);
+       op[3] = rel8(MEM_POS + $$, $4);
   }
 
 | JBC bit ',' jmpaddr {
@@ -1005,7 +1038,7 @@ instruction:
        op[0] = 0x97;
        op[1] = 0xC0 + msb(bit_addr($2));
        op[2] = lsb(bit_addr($2));
-       op[3] = rel8(mem + $$, $4);
+       op[3] = rel8(MEM_POS + $$, $4);
   }
 
 | JNB bit ',' jmpaddr {
@@ -1013,7 +1046,7 @@ instruction:
        op[0] = 0x97;
        op[1] = 0xA0 + msb(bit_addr($2));
        op[2] = lsb(bit_addr($2));
-       op[3] = rel8(mem + $$, $4);
+       op[3] = rel8(MEM_POS + $$, $4);
   }
 
 
index da706284161df2f86953f57c0b24559411a522ca..c38221d45c611417a3958b2eb372442a343d8199 100644 (file)
@@ -37,13 +37,18 @@ extern char *yytext;
 extern char last_line_text[];
 struct symbol *sym_list=NULL;
 struct target *targ_list=NULL;
-int lineno=1, mem=0;   /* mem is location in memory */
+int lineno=1;
 int p1=0, p2=0, p3=0;
 int expr_result, expr_ok, jump_dest, inst;
 int opcode, operand;
 char symbol_name[1000];
+struct area_struct area[NUM_AREAS];
+int current_area=AREA_CSEG;
 
 
+/* "mem" is replaced by area[current_area].alloc_position */
+/* int mem=0; */   /* mem is location in memory */
+
 /* add symbols to list when we find their definition in pass #1 */
 /* we will evaluate their values in pass #2, and figure out if */
 /* they are branch targets betweem passes 1 and 2.  Every symbol */
@@ -266,11 +271,11 @@ void out(int *byte_list, int num)
 {
        int i, first=1;
 
-       if (num > 0) fprintf(list_fp, "%06X: ", mem);
+       if (num > 0) fprintf(list_fp, "%06X: ", MEM_POS);
        else fprintf(list_fp, "\t");
 
        for (i=0; i<num; i++) {
-               hexout(byte_list[i], mem+i, 0);
+               hexout(byte_list[i], MEM_POS + i, 0);
                if (!first && (i % 4) == 0) fprintf(list_fp, "\t");
                fprintf(list_fp, "%02X", byte_list[i]);
                if ((i+1) % 4 == 0) {
@@ -299,9 +304,9 @@ void pad_with_nop()
 
        last_line_text[0] = '\0';
 
-       for(num=0; (mem + num) % BRANCH_SPACING; num++) ;
+       for(num=0; (MEM_POS + num) % BRANCH_SPACING; num++) ;
        if (p3) out(nops, num);
-       mem += num;
+       MEM_POS += num;
 }
 
 /* print branch out of bounds error */
@@ -314,13 +319,13 @@ void boob_error()
 }
 
 /* output the jump either direction on carry */
-/* jump_dest and mem must have the proper values */
+/* jump_dest and MEM_POS must have the proper values */
 
 /* 
 void do_jump_on_carry()
 {
        if (p3) {
-               operand = REL4(jump_dest, mem);
+               operand = REL4(jump_dest, MEM_POS);
                if (operand < 0) {
                        operand *= -1;
                        operand -= 1;
@@ -349,6 +354,28 @@ int binary2int(char *str)
 
 void print_usage();
 
+
+/* todo: someday this will allow the user to control where the */
+/* various memory areas go, and it will take care of assigning */
+/* positions to area which follow others (such as OSEG getting */
+/* set just after DSEG on the 2nd and 3rd passes when we have */
+/* leared the size needed for each segment */
+
+void init_areas(void)
+{
+       area[AREA_CSEG].alloc_position = 0;
+       area[AREA_DSEG].alloc_position = 0x30;
+       area[AREA_OSEG].alloc_position = 0x80;
+       area[AREA_ISEG].alloc_position = 0;
+       area[AREA_BSEG].alloc_position = 0;
+       area[AREA_XSEG].alloc_position = 0;
+       area[AREA_XISEG].alloc_position = 0;
+       area[AREA_GSINIT].alloc_position = 0;
+       area[AREA_GSFINAL].alloc_position = 0;
+       area[AREA_HOME].alloc_position = 0;
+}
+
+
 /* pass #1 (p1=1) find all symbol defs and branch target names */
 /* pass #2 (p2=1) align branch targets, evaluate all symbols */
 /* pass #3 (p3=1) produce object code */
@@ -398,10 +425,11 @@ int main(int argc, char **argv)
 
        printf("    Building Symbol Table:\n");
        p1 = 1;
-       mem = 0;
+       //mem = 0;
+       init_areas();
        yyparse();
        flag_targets();
-       // print_symbol_table();
+       print_symbol_table();
        check_redefine();
        p1 = 0;
        p2 = 1;
@@ -409,7 +437,8 @@ int main(int argc, char **argv)
        yyrestart(yyin);
        lineno = 1;
        printf("    Aligning Branch Targets:\n");
-       mem = 0;
+       //mem = 0;
+       init_areas();
        yyparse();
        // print_symbol_table();
        p2 = 0;
@@ -418,7 +447,8 @@ int main(int argc, char **argv)
        yyrestart(yyin);
        lineno = 1;
        printf("    Generating Object Code:\n");
-       mem = 0;
+       //mem = 0;
+       init_areas();
        yyparse();
        fclose(yyin);
        hexout(0, 0, 1);  /* flush and close intel hex file output */
index 6b1e30f8579519d870e8ddbc017f555c3bb156fa..51b1445e23e7e885f78967e4b87c651a804c41fe 100644 (file)
@@ -42,6 +42,27 @@ struct target {
         char *name;
         struct target *next; };
 
+struct area_struct {
+       int alloc_position;
+};
+
+extern int current_area;
+
+#define MEM_POS (area[current_area].alloc_position)
+
+#define AREA_CSEG      0
+#define AREA_DSEG      1
+#define AREA_OSEG      2
+#define AREA_ISEG      3
+#define AREA_BSEG      4
+#define AREA_XSEG      5
+#define AREA_XISEG     6
+#define AREA_GSINIT    7
+#define AREA_GSFINAL   8
+#define AREA_HOME      9
+#define NUM_AREAS      10
+
+extern struct area_struct area[NUM_AREAS];
 
 extern FILE *yyin;
 extern char *yytext;