home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / vbcc / pasm / directives.c next >
Encoding:
C/C++ Source or Header  |  1998-02-17  |  24.8 KB  |  1,089 lines

  1. /* $VER: pasm directives.c V0.8 (14.02.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.8 (14.02.98) phx
  16.  *      Alignment list for each section. This fixes the problems
  17.  *      with optimizations.
  18.  * v0.6 (30.10.97) phx
  19.  *      The names of macros will be converted to lower case (otherwise,
  20.  *      they would remain inaccessible ;)
  21.  * v0.5 (12.10.97) phx
  22.  *      .set directive is allowed multiple times on the same symbol.
  23.  *      If a .set-assignment can't be resolved in pass 1, the symbol
  24.  *      is no longer undefined, but defined with an absolute default
  25.  *      value of '1'. So .ifdef will work correctly.
  26.  *      .globl directive declares unknown symbols in pass 1 as
  27.  *      externally defined. If the symbol is defined later in the
  28.  *      source, it will be made global by add_symbol()/tables.c.
  29.  * v0.4 (29.04.97) phx
  30.  *      .new_section sets type of section-symbol to SYMI_SECTION.
  31.  *      New directives: .baserel
  32.  * v0.3 (10.04.97) phx
  33.  *      Some vbcc-specific changes.
  34.  * v0.2 (25.03.97) phx
  35.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  36.  *      or ELF output format may be selected. ELF is default for all
  37.  *      currently supported platforms. PPCasm supports nine different
  38.  *      relocation types (there are much more...).
  39.  *      Compiles and works also under NetBSD/amiga (68k).
  40.  *      Changed function declaration to 'new style' in all sources
  41.  *      (to avoid problems with '...' for example).
  42.  *      Floating pointer support. New directives: .fail, .ident, .file,
  43.  *      .float, .ufloat, .double, .udouble, .local.
  44.  * v0.1 (11.03.97) phx
  45.  *      First test version with all PowerPC instructions and most
  46.  *      important directives. Only raw, absolute output.
  47.  *      .ident and .file directives are supported, but have no effect.
  48.  *      Especially floating point directives are missing.
  49.  * v0.0 (21.02.97) phx
  50.  *      File created.
  51.  */
  52.  
  53.  
  54. #define DIRECTIVES_C
  55. #include "ppcasm.h"
  56.  
  57.  
  58. void activate_section(struct GlobalVars *,struct Section *);
  59. void alignment(struct GlobalVars *,unsigned long);
  60. char escchar(char);
  61.  
  62. static void start_section(struct GlobalVars *,struct ParsedLine *pl,bool);
  63. static char *section_attributes(struct GlobalVars *,char *,uint8 *,
  64.                                 uint8 *,uint8 *,uint8 *);
  65. static void _uahalf(struct GlobalVars *,struct ParsedLine *);
  66. static void _uaword(struct GlobalVars *,struct ParsedLine *);
  67. static void uafloat(struct GlobalVars *,struct ParsedLine *,bool);
  68. static void ifeqs(struct GlobalVars *,struct ParsedLine *,int);
  69. static void ifdef(struct GlobalVars *,struct ParsedLine *,bool);
  70.  
  71.  
  72.  
  73. static void _new_section(struct GlobalVars *gv,struct ParsedLine *pl)
  74. {
  75.   start_section(gv,pl,1);
  76. }
  77.  
  78.  
  79. static void _section(struct GlobalVars *gv,struct ParsedLine *pl)
  80. {
  81.   start_section(gv,pl,0);
  82. }
  83.  
  84.  
  85. static void start_section(struct GlobalVars *gv,struct ParsedLine *pl,
  86.                           bool force_new)
  87. /* define a new section with new attributes or reactivate a */
  88. /* previously defined one */
  89. {
  90.   struct Section *nexts,*sec = (struct Section *)gv->sectionlist.first;
  91.   struct Symbol *sym;
  92.   struct AlignPoint *ap;
  93.   char *s,*name;
  94.   uint8 type,flags,protection,alignment;
  95.  
  96.   s = getarg(gv,pl->operand);  /* section's name */
  97.   name = remquotes(gv->strbuf);
  98.  
  99.   while (nexts = (struct Section *)sec->n.next) {
  100.     if (!strcmp(name,sec->name)) {
  101.  
  102.       if (force_new) {  /* overwrite an old section with the same name? */
  103.         sprintf(gv->strbuf,"%s_%08lx",sec->name,(unsigned long)sec);
  104.         name = sec->name;
  105.         sec->name = allocstring(gv->strbuf);
  106.         break;
  107.       }
  108.  
  109.       else {  /* reactivate old section with the same name */
  110.         s = section_attributes(gv,s,&type,&flags,&protection,&alignment);
  111.         if (type != ST_UNDEFINED)  /* attributes specified? */
  112.           if (sec->type!=type || sec->flags!=flags ||
  113.               sec->protection!=protection || sec->alignment!=alignment)
  114.             error(16);  /* section attributes don't match */
  115.         pl->type = OT_SECTION;
  116.         pl->opcode = (void *)sec;
  117.         activate_section(gv,sec);
  118.         checkEOL(s);
  119.         return;
  120.       }
  121.  
  122.     }
  123.     sec = nexts;
  124.   }
  125.  
  126.   /* create a new section */
  127.   sec = alloczero(sizeof(struct Section));
  128.   sec->name = allocstring(name);
  129.   s = section_attributes(gv,s,&sec->type,&sec->flags,&sec->protection,
  130.                          &sec->alignment);
  131.   if (sec->type == ST_UNDEFINED) {  /* set default attributes */
  132.     sec->type = ST_DATA;
  133.     sec->protection = SP_READ|SP_WRITE;
  134.     sec->alignment = 2;
  135.   }
  136.   initlist(&sec->reloclist);
  137.   initlist(&sec->xreflist);
  138.   ap = alloc(sizeof(struct AlignPoint));
  139.   ap->next = NULL;
  140.   ap->offset = ap->gap = 0;
  141.   ap->val = 1 << sec->alignment;
  142.   sec->first_align = sec->current_align = ap;
  143.   addtail(&gv->sectionlist,&sec->n);
  144.   pl->type = OT_SECTION;
  145.   pl->opcode = (void *)sec;
  146.   activate_section(gv,sec);
  147.   sym = add_symbol(gv,sec->name,SYM_RELOC,0);
  148.   sym->info = SYMI_SECTION;
  149.   checkEOL(s);
  150. }
  151.  
  152.  
  153. void activate_section(struct GlobalVars *gv,struct Section *sec)
  154. {
  155.   gv->csect = sec;  /* set active section */
  156.   gv->lcsym->relsect = sec;
  157.   gv->lcsym->value = sec->pc;
  158. }
  159.  
  160.  
  161. static char *section_attributes(struct GlobalVars *gv,char *s,uint8 *t,
  162.                                 uint8 *f,uint8 *p,uint8 *a)
  163. /* fill in section attributes, if specified */
  164. {
  165.   char c,*attr;
  166.  
  167.   *t = ST_UNDEFINED;
  168.   *f = *p = *a = 0;
  169.   s = skipspaces(s);
  170.   if (*s) {
  171.     if (*s == ',') {
  172.       s = skipspaces(++s);
  173.       s = getarg(gv,s);
  174.       c = *gv->strbuf;
  175.       if (c=='\"' || c=='\'') {
  176.         attr = remquotes(gv->strbuf);
  177.         while (c = *attr++) {
  178.           switch (c) {
  179.             /* contents type */
  180.             case 'c':
  181.               *t = ST_CODE;
  182.               break;
  183.             case 'd':
  184.               *t = ST_DATA;
  185.               break;
  186.             case 'u':
  187.               *t = ST_UDATA;
  188.               *f |= SF_UNINITIALIZED;
  189.               break;
  190.             case 'i':
  191.               *t = ST_STRUCT;
  192.               *f |= SF_DISCARD|SF_UNINITIALIZED;
  193.               break;
  194.             /* protection */
  195.             case 'r':
  196.               *p |= SP_READ;
  197.               break;
  198.             case 'w':
  199.               *p |= SP_WRITE;
  200.               break;
  201.             case 'x':
  202.               *p |= SP_EXEC;
  203.               break;
  204.             case 's':
  205.               *p |= SP_SHARE;
  206.               break;
  207.             case 'n': /* remove and discard currently not supported */
  208.             case 'R':
  209.               break;
  210.             default:
  211.               if (c>='0' && c <='6')
  212.                 *a = (uint8)(c-'0');  /* alignment */
  213.               else
  214.                 error(15,c);  /* illegal section attribute */
  215.               break;
  216.           }
  217.         }
  218.       }
  219.       else
  220.         error(14);  /* string constant expected */
  221.     }
  222.     else if (*s != '#')
  223.       error(12);  /* colon expected */
  224.   }
  225.   return (s);
  226. }
  227.  
  228.  
  229. static void _set(struct GlobalVars *gv,struct ParsedLine *pl)
  230. {
  231.   char *s = getsymbol(gv,pl->operand);
  232.   struct Expression exp;
  233.   struct Section *cs;
  234.   char setname[STRBUFSIZE];
  235.   struct Symbol *sym;
  236.  
  237.   if (*gv->strbuf) {
  238.     strcpy(setname,gv->strbuf);
  239.     if (s = check_comma(s)) {
  240.       s = eval_expression(gv,&exp,s);
  241.       if (exp.type != SYM_UNDEF) {
  242.         if (exp.type != SYM_EXTERN) {
  243.           if (exp.type == SYM_RELOC) {
  244.             if (exp.reloctype == R_PPC_ADDR32) {
  245.               if (sym = search_symbol(gv,setname)) {
  246.                 sym->value = exp.value;
  247.                 sym->type = SYM_RELOC;
  248.                 sym->relsect = exp.symbol->relsect;
  249.               }
  250.               else {
  251.                 cs = gv->csect;
  252.                 gv->csect = exp.symbol->relsect;
  253.                 add_symbol(gv,setname,SYM_RELOC,exp.value);
  254.                 gv->csect = cs;
  255.               }
  256.             }
  257.             else
  258.               error(29);  /* can't assign relocatable half word */
  259.           }
  260.           else {
  261.             if (sym = search_symbol(gv,setname)) {
  262.               sym->value = exp.value;
  263.               sym->type = SYM_ABS;
  264.             }
  265.             else
  266.               add_symbol(gv,setname,SYM_ABS,exp.value);
  267.           }
  268.         }
  269.         else
  270.           error(28);  /* can't assign external symbol */
  271.       }
  272.       else {
  273.         if (gv->pass)  /* expression still undefined in pass 2 ? */
  274.           error(19);  /* undefined symbol */
  275.         else if (!search_symbol(gv,setname))
  276.           /* set value to 1 if unknown in first pass */
  277.           add_symbol(gv,setname,SYM_ABS,1);
  278.       }
  279.       checkEOL(s);
  280.       return;
  281.     }
  282.   }
  283.   else
  284.     error(17);  /* missing argument */
  285. }
  286.  
  287.  
  288. static void _macro(struct GlobalVars *gv,struct ParsedLine *pl)
  289. {
  290.   struct Macro *mac = alloczero(sizeof(struct Macro));
  291.   char *s = getsymbol(gv,pl->operand);
  292.  
  293.   mac->name = allocstring(gv->strbuf);
  294.   lower_case(mac->name);  /* convert macro name to lower case */
  295.   mac->text = gv->cthread->srcptr;
  296.   mac->nlines = gv->absline + 1;
  297.   gv->cthread->macskip = mac;
  298.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  299.   checkEOL(s);
  300. }
  301.  
  302.  
  303. static void _include(struct GlobalVars *gv,struct ParsedLine *pl)
  304. {
  305.   char *s;
  306.  
  307.   if (!gv->pass) {  /* pass 1 */
  308.     s = getarg(gv,pl->operand);  /* include file's name */
  309.  
  310.     /* recursively call pass 1 and create new SourceThread */
  311.     pass1(gv,include_source(gv,remquotes(gv->strbuf)),NULL,gv->cthread);
  312.     checkEOL(s);
  313.   }
  314.  
  315.   else  /* recursively call pass 2 */
  316.     pass2(gv,get_source(gv),NULL,gv->cthread);
  317. }
  318.  
  319.  
  320. void alignment(struct GlobalVars *gv,unsigned long a)
  321. {
  322.   unsigned long x = (1<<a) - 1;
  323.   unsigned long pc, oldpc = gv->csect->pc;
  324.   struct AlignPoint *ap = gv->csect->current_align;
  325.  
  326.   pc = (oldpc + x) & ~x;
  327.   if (!gv->pass) {
  328.     if (ap->next)
  329.       ierror("Current alignment point is not the last one!");
  330.     ap->next = alloc(sizeof(struct AlignPoint));
  331.     ap = ap->next;
  332.     ap->next = NULL;
  333.     ap->offset = oldpc;
  334.     ap->val = 1 << a;
  335.     ap->gap = pc - oldpc;
  336.     gv->csect->current_align = ap;
  337.     gv->csect->pc = pc;
  338.   }
  339.   else {
  340.     if (!(gv->csect->current_align = ap->next))  /* next alignment section */
  341.       ierror("No more alignments in list!");
  342.     store_space(gv,pc-oldpc);
  343.   }
  344. }
  345.  
  346.  
  347. static void _align(struct GlobalVars *gv,struct ParsedLine *pl)
  348. {
  349.   char *s;
  350.   uint32 a=2;
  351.   static uint8 na=0;
  352.  
  353.   if (pl->flags & PLF_ALIGN) {
  354.     if (++na > 2)
  355.       gv->vc = TRUE;
  356.   }
  357.   else
  358.     na = 0;
  359.   s = getintexp(gv,pl->operand,&a);
  360.   alignment(gv,a);
  361.   gv->alignflag = TRUE;
  362.   if (!gv->pass)
  363.     checkEOL(s);
  364. }
  365.  
  366.  
  367. static void _space(struct GlobalVars *gv,struct ParsedLine *pl)
  368. {
  369.   char *s;
  370.   uint32 n=0;
  371.  
  372.   s = getintexp(gv,pl->operand,&n);
  373.   if (!gv->pass) {
  374.     pcadd(gv,n);
  375.     checkEOL(s);
  376.   }
  377.   else
  378.     store_space(gv,n);
  379. }
  380.  
  381.  
  382. char escchar(char c)
  383. /* convert escape code */
  384. {
  385.   switch (c) {
  386.     case 'b':
  387.       c = 8;
  388.       break;
  389.     case 'f':
  390.       c = 12;
  391.       break;
  392.     case 'n':
  393.       c = 10;
  394.       break;
  395.     case 'r':
  396.       c = 13;
  397.       break;
  398.     case 't':
  399.       c = 8;
  400.       break;
  401.   }
  402.   return (c);
  403. }
  404.  
  405.  
  406. static void _byte(struct GlobalVars *gv,struct ParsedLine *pl)
  407. {
  408.   char *s = pl->operand;
  409.   char *sb,c;
  410.   uint8 pass = gv->pass;
  411.   uint32 i;
  412.  
  413.   for (;;) {
  414.     if ((c = *s) == '\"') {  /* read string */
  415.       s = getarg(gv,s);
  416.       sb = remquotes(gv->strbuf);
  417.       if (!pass)
  418.         while (c = *sb++) {
  419.           if (c=='\\' || c=='\"')
  420.             if (*sb++ == 0)
  421.               break;
  422.           pcadd(gv,1);
  423.         }
  424.       else
  425.         while (c = *sb++) {
  426.           if (c == '\\') {
  427.             if (!(c = escchar(*sb++)))
  428.               break;
  429.           }
  430.           else if (c == '\"') {
  431.             if (!(c = *sb++))
  432.               break;
  433.           }
  434.           store_byte(gv,(uint8)c);
  435.         }
  436.     }
  437.  
  438.     else {  /* get integer expression */
  439.       if (c==0 || c=='#') {
  440.         error(17);  /* missing argument */
  441.         break;
  442.       }
  443.       if (!pass) {
  444.         s = skipexpression(gv,s);
  445.         pcadd(gv,1);
  446.       }
  447.       else {
  448.         s = getintexp(gv,s,&i);
  449.         store_byte(gv,(uint8)i);
  450.         s = skipspaces(s);
  451.       }
  452.     }
  453.  
  454.     c = *s++;
  455.     if (c==0 || c=='#')  /* no more arguments? */
  456.       break;
  457.     if (c != ',') {
  458.       error(12);  /* colon expected */
  459.       break;
  460.     }
  461.     s = skipspaces(s);
  462.   }
  463. }
  464.  
  465.  
  466. static void _string(struct GlobalVars *gv,struct ParsedLine *pl)
  467. {
  468.   char *s = pl->operand;
  469.   char *sb,c;
  470.   uint8 pass = gv->pass;
  471.  
  472.   for (;;) {
  473.     if ((c = *s) == '\"') {  /* read string */
  474.       s = getarg(gv,s);
  475.       sb = remquotes(gv->strbuf);
  476.       if (!pass) {
  477.         while (c = *sb++) {
  478.           if (c=='\\' || c=='\"')
  479.             if (*sb++ == 0)
  480.               break;
  481.           pcadd(gv,1);
  482.         }
  483.         pcadd(gv,1);
  484.       }
  485.       else {
  486.         while (c = *sb++) {
  487.           if (c == '\\') {
  488.             if (!(c = escchar(*sb++)))
  489.               break;
  490.           }
  491.           else if (c == '\"') {
  492.             if (!(c = *sb++))
  493.               break;
  494.           }
  495.           store_byte(gv,(uint8)c);
  496.         }
  497.         store_byte(gv,0);
  498.       }
  499.     }
  500.     else {
  501.       error(14);  /* string constant expected */
  502.       break;
  503.     }
  504.  
  505.     c = *s++;
  506.     if (c==0 || c=='#')  /* no more arguments? */
  507.       break;
  508.     if (c != ',') {
  509.       error(12);  /* colon expected */
  510.       break;
  511.     }
  512.     s = skipspaces(s);
  513.   }
  514. }
  515.  
  516.  
  517. static void _half(struct GlobalVars *gv,struct ParsedLine *pl)
  518. {
  519.   alignment(gv,1);
  520.   _uahalf(gv,pl);
  521. }
  522.  
  523.  
  524. static void _uahalf(struct GlobalVars *gv,struct ParsedLine *pl)
  525. {
  526.   char *s = pl->operand;
  527.   char *sb,c;
  528.   uint8 pass = gv->pass;
  529.   uint32 i;
  530.  
  531.   for (;;) {
  532.     c = *s;
  533.     if (c==0 || c=='#') {
  534.       error(17);  /* missing argument */
  535.       break;
  536.     }
  537.     if (!pass) {
  538.       s = skipexpression(gv,s);
  539.       pcadd(gv,2);
  540.     }
  541.     else {
  542.       s = getexp(gv,s,&i,2);
  543.       store_half(gv,(uint16)i);
  544.       s = skipspaces(s);
  545.     }
  546.  
  547.     c = *s++;
  548.     if (c==0 || c=='#')  /* no more arguments? */
  549.       break;
  550.     if (c != ',') {
  551.       error(12);  /* colon expected */
  552.       break;
  553.     }
  554.     s = skipspaces(s);
  555.   }
  556. }
  557.  
  558.  
  559. static void _word(struct GlobalVars *gv,struct ParsedLine *pl)
  560. {
  561.   alignment(gv,2);
  562.   _uaword(gv,pl);
  563. }
  564.  
  565.  
  566. static void _uaword(struct GlobalVars *gv,struct ParsedLine *pl)
  567. {
  568.   char *s = pl->operand;
  569.   char *sb,c;
  570.   uint8 pass = gv->pass;
  571.   uint32 i;
  572.  
  573.   for (;;) {
  574.     c = *s;
  575.     if (c==0 || c=='#') {
  576.       error(17);  /* missing argument */
  577.       break;
  578.     }
  579.     if (!pass) {
  580.       s = skipexpression(gv,s);
  581.       pcadd(gv,4);
  582.     }
  583.     else {
  584.       s = getexp(gv,s,&i,4);
  585.       store_word(gv,i);
  586.       s = skipspaces(s);
  587.     }
  588.  
  589.     c = *s++;
  590.     if (c==0 || c=='#')  /* no more arguments? */
  591.       break;
  592.     if (c != ',') {
  593.       error(12);  /* colon expected */
  594.       break;
  595.     }
  596.     s = skipspaces(s);
  597.   }
  598. }
  599.  
  600.  
  601. static void _float(struct GlobalVars *gv,struct ParsedLine *pl)
  602. {
  603.   alignment(gv,2);
  604.   uafloat(gv,pl,FALSE);
  605. }
  606.  
  607.  
  608. static void _uafloat(struct GlobalVars *gv,struct ParsedLine *pl)
  609. {
  610.   uafloat(gv,pl,FALSE);
  611. }
  612.  
  613.  
  614. static void _double(struct GlobalVars *gv,struct ParsedLine *pl)
  615. {
  616.   alignment(gv,3);
  617.   uafloat(gv,pl,TRUE);
  618. }
  619.  
  620.  
  621. static void _uadouble(struct GlobalVars *gv,struct ParsedLine *pl)
  622. {
  623.   uafloat(gv,pl,TRUE);
  624. }
  625.  
  626.  
  627. static void uafloat(struct GlobalVars *gv,struct ParsedLine *pl,bool dbl)
  628. {
  629.   char *s = pl->operand;
  630.   char *sb,c;
  631.   uint8 pass = gv->pass;
  632.   double f;
  633.  
  634.   for (;;) {
  635.     c = *s;
  636.     if (c==0 || c=='#') {
  637.       error(17);  /* missing argument */
  638.       break;
  639.     }
  640.     if (!pass) {
  641.       s = skipexpression(gv,s);
  642.       pcadd(gv,dbl?8:4);
  643.     }
  644.     else {
  645.       sscanf(s,"%lf",&f);
  646.       if (dbl)
  647.         store_double(gv,f);
  648.       else
  649.         store_float(gv,f);
  650.       s = skipexpression(gv,s);
  651.     }
  652.  
  653.     c = *s++;
  654.     if (c==0 || c=='#')  /* no more arguments? */
  655.       break;
  656.     if (c != ',') {
  657.       error(12);  /* colon expected */
  658.       break;
  659.     }
  660.     s = skipspaces(s);
  661.   }
  662. }
  663.  
  664.  
  665. static void _globl(struct GlobalVars *gv,struct ParsedLine *pl)
  666. {
  667.   char *s;
  668.   struct Symbol *sym;
  669.  
  670.   s = getsymbol(gv,pl->operand);
  671.   if (*gv->strbuf) {
  672.     if (!(sym = search_symbol(gv,gv->strbuf))) {
  673.       /* unknown in pass 1, then declare as externally defined first */
  674.       sym = add_symbol(gv,gv->strbuf,SYM_EXTERN,0);
  675.     }
  676.     sym->bind = SYMB_GLOBAL;
  677.     checkEOL(s);
  678.   }
  679.   else
  680.     error(17);  /* missing argument */
  681.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  682. }
  683.  
  684.  
  685. static void _local(struct GlobalVars *gv,struct ParsedLine *pl)
  686. {
  687.   char *s;
  688.   struct Symbol *sym;
  689.  
  690.   if (gv->pass) {
  691.     s = getsymbol(gv,pl->operand);
  692.     if (*gv->strbuf) {
  693.       if (!(sym = search_symbol(gv,gv->strbuf)))
  694.         error(19);  /* undefined symbol */
  695.       else
  696.         sym->bind = SYMB_LOCAL;
  697.       checkEOL(s);
  698.     }
  699.     else
  700.       error(17);  /* missing argument */
  701.   }
  702. }
  703.  
  704.  
  705. static void _bss(struct GlobalVars *gv,struct ParsedLine *pl)
  706. {
  707.   static char *bssname=".bss";
  708.   char *s;
  709.   struct Section *bss,*old=gv->csect;
  710.   uint32 size,align;
  711.   char symbname[STRBUFSIZE];
  712.   struct Symbol *sym;
  713.  
  714.   s = getsymbol(gv,pl->operand);
  715.   if (*gv->strbuf) {
  716.     if (!gv->pass)
  717.       strcpy(symbname,gv->strbuf);
  718.     if (!(s = check_comma(s)))
  719.       return;
  720.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  721.     align = (size>=8)? 3 : 2;
  722.     s = skipspaces(s);
  723.     if (*s == ',') {
  724.       s = getintexp(gv,++s,&align);  /* optional aligment */
  725.       if (align < 2)
  726.         align = 2;
  727.     }
  728.     if (bss = search_section(gv,bssname)) {
  729.       activate_section(gv,bss);
  730.       alignment(gv,align);
  731.       if (!gv->pass) {
  732.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  733.         sym->info = SYMI_OBJECT;
  734.         sym->size = size;
  735.         sym->bind = SYMB_LOCAL;
  736.         pcadd(gv,size);
  737.         checkEOL(s);
  738.       }
  739.       else
  740.         store_space(gv,size);
  741.       activate_section(gv,old);
  742.     }
  743.     else
  744.       error(47,bssname);  /* section .bss was never defined */
  745.   }
  746.   else
  747.     error(17);  /* missing argument */
  748. }
  749.  
  750.  
  751. static void _comm(struct GlobalVars *gv,struct ParsedLine *pl)
  752. {
  753.   static char *bssname=".bss";
  754.   char *s;
  755.   struct Section *bss,*old=gv->csect;
  756.   uint32 size;
  757.   char symbname[STRBUFSIZE];
  758.   struct Symbol *sym;
  759.  
  760.   s = getsymbol(gv,pl->operand);
  761.   if (*gv->strbuf) {
  762.     if (!gv->pass)
  763.       strcpy(symbname,gv->strbuf);
  764.     if (!(s = check_comma(s)))
  765.       return;
  766.     s = getintexp(gv,s,&size);  /* size of bss symbol */
  767.     if (bss = search_section(gv,bssname)) {
  768.       activate_section(gv,bss);
  769.       alignment(gv,(size>=8)? 3:2);
  770.       if (!gv->pass) {
  771.         sym = add_symbol(gv,symbname,SYM_RELOC,bss->pc);
  772.         sym->info = SYMI_OBJECT;
  773.         sym->size = size;
  774.         sym->bind = SYMB_GLOBAL;  /* or SYMB_WEAK ?? */
  775.         pcadd(gv,size);
  776.         checkEOL(s);
  777.       }
  778.       else
  779.         store_space(gv,size);
  780.       activate_section(gv,old);
  781.     }
  782.     else
  783.       error(47,bssname);  /* section .bss was never defined */
  784.   }
  785.   else
  786.     error(17);  /* missing argument */
  787. }
  788.  
  789.  
  790. static void _type(struct GlobalVars *gv,struct ParsedLine *pl)
  791. {
  792.   char *s;
  793.   struct Symbol *sym;
  794.   uint32 type;
  795.  
  796.   if (gv->pass) {
  797.     s = getsymbol(gv,pl->operand);
  798.     if (*gv->strbuf) {
  799.       if (sym = search_symbol(gv,gv->strbuf)) {
  800.         if (s = check_comma(s)) {
  801.           s = getintexp(gv,s,&type);
  802.           sym->info = (uint8)type;
  803.           checkEOL(s);
  804.         }
  805.       }
  806.       else
  807.         error(19);  /* undefined symbol */
  808.     }
  809.     else
  810.       error(17);  /* missing argument */
  811.   }
  812. }
  813.  
  814.  
  815. static void _size(struct GlobalVars *gv,struct ParsedLine *pl)
  816. {
  817.   char *s;
  818.   struct Symbol *sym;
  819.   uint32 size;
  820.  
  821.   if (gv->pass) {
  822.     s = getsymbol(gv,pl->operand);
  823.     if (*gv->strbuf) {
  824.       if (sym = search_symbol(gv,gv->strbuf)) {
  825.         if (s = check_comma(s)) {
  826.           s = getintexp(gv,s,&size);
  827.           sym->size = size;
  828.           checkEOL(s);
  829.         }
  830.       }
  831.       else
  832.         error(19);  /* undefined symbol */
  833.     }
  834.     else
  835.       error(17);  /* missing argument */
  836.   }
  837. }
  838.  
  839.  
  840. static void _ifeq(struct GlobalVars *gv,struct ParsedLine *pl)
  841. {
  842.   ifeqs(gv,pl,0);
  843. }
  844.  
  845.  
  846. static void _ifne(struct GlobalVars *gv,struct ParsedLine *pl)
  847. {
  848.   ifeqs(gv,pl,1);
  849. }
  850.  
  851.  
  852. static void _ifgt(struct GlobalVars *gv,struct ParsedLine *pl)
  853. {
  854.   ifeqs(gv,pl,2);
  855. }
  856.  
  857.  
  858. static void _ifge(struct GlobalVars *gv,struct ParsedLine *pl)
  859. {
  860.   ifeqs(gv,pl,3);
  861. }
  862.  
  863.  
  864. static void _iflt(struct GlobalVars *gv,struct ParsedLine *pl)
  865. {
  866.   ifeqs(gv,pl,4);
  867. }
  868.  
  869.  
  870. static void _ifle(struct GlobalVars *gv,struct ParsedLine *pl)
  871. {
  872.   ifeqs(gv,pl,5);
  873. }
  874.  
  875.  
  876. static void ifeqs(struct GlobalVars *gv,struct ParsedLine *pl,int cond)
  877. {
  878.   char *s;
  879.   int32 val;
  880.   bool *condptr;
  881.  
  882.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  883.     condptr = &gv->ifcond[++gv->iflevel];
  884.     *condptr = FALSE;
  885.     s = getintexp(gv,pl->operand,&val);
  886.     switch (cond) {
  887.       case 0: /* eq */
  888.         if (val==0)
  889.           *condptr = TRUE;
  890.         break;
  891.       case 1: /* ne */
  892.         if (val!=0)
  893.           *condptr = TRUE;
  894.         break;
  895.       case 2: /* gt */
  896.         if (val>0)
  897.           *condptr = TRUE;
  898.         break;
  899.       case 3: /* ge */
  900.         if (val>=0)
  901.           *condptr = TRUE;
  902.         break;
  903.       case 4: /* lt */
  904.         if (val<0)
  905.           *condptr = TRUE;
  906.         break;
  907.       case 5: /* le */
  908.         if (val<=0)
  909.           *condptr = TRUE;
  910.         break;
  911.     }
  912.     checkEOL(s);
  913.   }
  914.   else
  915.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  916.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  917. }
  918.  
  919.  
  920. static void _ifdef(struct GlobalVars *gv,struct ParsedLine *pl)
  921. {
  922.   ifdef(gv,pl,TRUE);
  923. }
  924.  
  925.  
  926. static void _ifndef(struct GlobalVars *gv,struct ParsedLine *pl)
  927. {
  928.   ifdef(gv,pl,FALSE);
  929. }
  930.  
  931.  
  932. static void ifdef(struct GlobalVars *gv,struct ParsedLine *pl,bool c)
  933. {
  934.   char *s;
  935.   bool *condptr;
  936.  
  937.   if (gv->iflevel < (MAX_IFLEVELS-1)) {
  938.     condptr = &gv->ifcond[++gv->iflevel];
  939.     *condptr = c ? FALSE:TRUE;
  940.     s = getsymbol(gv,pl->operand);
  941.     if (*gv->strbuf)
  942.       if (search_symbol(gv,gv->strbuf))
  943.         *condptr = c;
  944.     checkEOL(s);
  945.   }
  946.   else
  947.     error(43);  /* maximum nesting depth for conditional assembly exceeded */
  948.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  949. }
  950.  
  951.  
  952. static void _else(struct GlobalVars *gv,struct ParsedLine *pl)
  953. {
  954.   if (gv->iflevel > 0) {
  955.     gv->ifcond[gv->iflevel] = FALSE;
  956.     checkEOL(pl->operand);
  957.   }
  958.   else
  959.     error(44,".else");  /* .else without matching .if */
  960.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  961. }
  962.  
  963.  
  964. static void _endif(struct GlobalVars *gv,struct ParsedLine *pl)
  965. {
  966.   if (gv->iflevel > 0) {
  967.     gv->iflevel--;
  968.     checkEOL(pl->operand);
  969.   }
  970.   else
  971.     error(44,".endif");  /* .endif without matching .if */
  972.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  973. }
  974.  
  975.  
  976. static void _fail(struct GlobalVars *gv,struct ParsedLine *pl)
  977. {
  978.   error(45);  /* fail directive encountered */
  979. }
  980.  
  981.  
  982. static void _noop(struct GlobalVars *gv,struct ParsedLine *pl)
  983. {
  984. }
  985.  
  986.  
  987. static void _ident(struct GlobalVars *gv,struct ParsedLine *pl)
  988. {
  989.   char *s = getarg(gv,pl->operand);  /* identification / comment */
  990.  
  991.   gv->ident = allocstring(remquotes(gv->strbuf));
  992.   checkEOL(s);
  993.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  994. }
  995.  
  996.  
  997. static void _file(struct GlobalVars *gv,struct ParsedLine *pl)
  998. {
  999.   char *s = getarg(gv,pl->operand);  /* source file name */
  1000.  
  1001.   gv->file = allocstring(remquotes(gv->strbuf));
  1002.   checkEOL(s);
  1003.   pl->type = OT_IGNORE;  /* ignore in pass 2 */
  1004. }
  1005.  
  1006.  
  1007. static void _baserel(struct GlobalVars *gv,struct ParsedLine *pl)
  1008. {
  1009.   char *s;
  1010.   struct Symbol *sym;
  1011.   uint32 tocreg;
  1012.  
  1013.   if (gv->pass) {
  1014.     s = getsymbol(gv,pl->operand);
  1015.     if (*gv->strbuf) {
  1016.       if (sym = search_symbol(gv,gv->strbuf)) {
  1017.         if (s = check_comma(s)) {
  1018.           s = getintexp(gv,s,&tocreg);
  1019.           if (sym->info == SYMI_SECTION) {
  1020.             /* activate new base relative addressing mode */
  1021.             gv->tocsect = sym->relsect;
  1022.             gv->rtoc = (int)tocreg;
  1023.           }
  1024.           else
  1025.             error(50,sym->name);  /* symbol is not a section base address */
  1026.           checkEOL(s);
  1027.         }
  1028.       }
  1029.       else
  1030.         error(19);  /* undefined symbol */
  1031.     }
  1032.     else
  1033.       error(17);  /* missing argument */
  1034.   }
  1035. }
  1036.  
  1037.  
  1038.  
  1039. struct Directive directives[] = {
  1040.   0,".new_section",_new_section,
  1041.   0,".section",_section,
  1042.   0,".set",_set,
  1043.   0,".macro",_macro,
  1044.   0,".include",_include,
  1045.   0,".align",_align,
  1046.   0,".space",_space,
  1047.   0,".byte",_byte,
  1048.   0,".ascii",_byte,
  1049.   0,".string",_string,
  1050.   0,".asciiz",_string,
  1051.   0,".half",_half,
  1052.   0,".short",_half,
  1053.   0,".word",_word,
  1054.   0,".long",_word,
  1055.   0,".float",_float,
  1056.   0,".double",_double,
  1057.   0,".uahalf",_uahalf,
  1058.   0,".uashort",_uahalf,
  1059.   0,".uaword",_uaword,
  1060.   0,".ualong",_uaword,
  1061.   0,".uafloat",_uafloat,
  1062.   0,".uadouble",_uadouble,
  1063.   0,".globl",_globl,
  1064.   0,".global",_globl,
  1065.   0,".extern",_globl,
  1066.   0,".local",_local,
  1067.   0,".bss",_bss,
  1068.   0,".lcomm",_bss,
  1069.   0,".comm",_comm,
  1070.   0,".type",_type,
  1071.   0,".size",_size,
  1072.   0,".if",_ifne,
  1073.   0,".ifeq",_ifeq,
  1074.   0,".ifne",_ifne,
  1075.   0,".ifgt",_ifgt,
  1076.   0,".ifge",_ifge,
  1077.   0,".iflt",_iflt,
  1078.   0,".ifle",_ifle,
  1079.   0,".ifdef",_ifdef,
  1080.   0,".ifndef",_ifndef,
  1081.   0,".else",_else,
  1082.   0,".endif",_endif,
  1083.   0,".fail",_fail,
  1084.   0,".ident",_ident,
  1085.   0,".file",_file,
  1086.   0,".baserel",_baserel,
  1087.   0,0 /* end mark */
  1088. };
  1089.