home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / vbcc / pasm / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-17  |  20.4 KB  |  807 lines

  1. /* $VER: pasm eval.c V0.7 (01.01.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.7 (01.01.98) phx
  16.  *      @ha, @h, @l are only allowed at the end of an operand, according
  17.  *      to GNU-as notation. '@' is only allowed as the first character in
  18.  *      a symbol (for @function and @object, for example).
  19.  *      Don't waste memory in makereloc() and makexref() by adding new
  20.  *      nodes to the current section if another pass is required
  21.  *      anyway.
  22.  * v0.5 (11.10.97) phx
  23.  *      getarg() works with \' and \" now.
  24.  * v0.4 (05.07.97) phx
  25.  *      R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
  26.  *      "(<term>)@l/h/ha" was not recognized.
  27.  *      A comment introducer '#' was erroneously treated as a macro
  28.  *      parameter in read_macro_params().
  29.  *      Undefined symbols are only automatically declared as externally
  30.  *      defined, if the -x option was given. Otherwise display an
  31.  *      error message.
  32.  *      Implementing backwards-evaluation of an expression in v0.3 was not
  33.  *      very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
  34.  * v0.3 (20.04.97) phx
  35.  *      Bug in eval_expression() fixed, which sometimes caused the loss
  36.  *      of the last argument of an expression.
  37.  * v0.2 (25.03.97) phx
  38.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  39.  *      or ELF output format may be selected. ELF is default for all
  40.  *      currently supported platforms. PPCasm supports nine different
  41.  *      relocation types (there are much more...).
  42.  *      Compiles and works also under NetBSD/amiga (68k).
  43.  *      Changed function declaration to 'new style' in all sources
  44.  *      (to avoid problems with '...' for example).
  45.  *      makexref() and makereloc() used wrong offset.
  46.  * v0.1 (11.03.97) phx
  47.  *      First test version with all PowerPC instructions and most
  48.  *      important directives. Only raw, absolute output.
  49.  * v0.0 (21.02.97) phx
  50.  *      File created.
  51.  */
  52.  
  53.  
  54. #define EVAL_C
  55. #include "ppcasm.h"
  56.  
  57.  
  58. char *getsymbol(struct GlobalVars *,char *);
  59. char *getarg(struct GlobalVars *,char *);
  60. char *skipspaces(char *);
  61. char *remquotes(char *);
  62. void checkEOL(char *);
  63. char *skipexpression(struct GlobalVars *,char *);
  64. void read_macro_params(struct GlobalVars *,struct ParsedLine *,
  65.                        struct MacroParams *,char *);
  66. char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
  67. uint32 makereloc(struct GlobalVars *,struct Expression *);
  68. uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
  69. char *getintexp(struct GlobalVars *,char *,uint32 *);
  70. char *eval_expression(struct GlobalVars *,struct Expression *,char *);
  71.  
  72. static uint32 hihalf(struct GlobalVars *,uint32);
  73. static uint32 lohalf(struct GlobalVars *,uint32);
  74. static uint32 read_hex(char *);
  75. static uint32 read_dec(char *);
  76. static uint32 read_oct(char *);
  77. static uint32 read_bin(char *);
  78. static uint32 read_str(char *);
  79.  
  80.  
  81.  
  82. /* table of valid symbol characters, 
  83.    0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
  84. static uint8 valid_symchars[256] = {
  85.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  86.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  87.   0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,  /* $ . */
  88.   2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1,  /* 0-9 ? */
  89.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  90.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  91.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  92.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  93.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  94.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  95.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  96.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  98.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  99.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  100.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  101. };
  102.  
  103. /* table of valid argument characters, 
  104.    0=invalid, 1=valid, 2=valid, but indicates string */
  105. static uint8 valid_argchars[256] = {
  106.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.   0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0,  /* " $ ' . */
  109.   1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,  /* 0-9 ? */
  110.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  111.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  112.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  113.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  114.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  115.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  116.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  117.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  120.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  121.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  122. };
  123.  
  124. /* valid operators */
  125. #define NUMOPS 10
  126. static char valid_operators[NUMOPS] = {
  127.   '+','-','*','/','%','<','>','&','|','^'
  128. };
  129. #define MAXOPPRI 5
  130. static uint8 op_priority[NUMOPS] = {
  131.   4,4,5,5,5,3,3,2,0,1
  132. };
  133.  
  134.  
  135. char *getsymbol(struct GlobalVars *gv,char *s)
  136. /* read a symbol string into gv->strbuf */
  137. {
  138.   uint8 *vsc = valid_symchars;
  139.   char *b = gv->strbuf;
  140.   int bsize = STRBUFSIZE-2;
  141.  
  142.   if (*s == '@') {  /* '@' is allowed as first character */
  143.     *b++ = *s++;
  144.     bsize--;
  145.   }
  146.   if (vsc[(unsigned char)*s] == 1) {  /* first character valid? */
  147.     *b++ = *s++;
  148.     while (vsc[(unsigned char)*s] && bsize--)
  149.       *b++ = *s++;
  150.   }
  151.   *b = 0;
  152.   return (s);
  153. }
  154.  
  155.  
  156. char *getarg(struct GlobalVars *gv,char *s)
  157. /* read next argument into gv->strbuf */
  158. {
  159.   uint8 v,*vac = valid_argchars;
  160.   char c,*b = gv->strbuf;
  161.   int bsize = STRBUFSIZE-1;
  162.  
  163.   if (*s == '@') {  /* '@' is allowed as first character */
  164.     *b++ = *s++;
  165.     bsize--;
  166.   }
  167.   while ((v = vac[(unsigned char)*s]) && bsize--) {
  168.     *b++ = *s++;
  169.     if (v==2) {  /* string? */
  170.       c = *(s-1);
  171.       for (;;) {
  172.         if (bsize--) {
  173.           if (!(*b++ = *s))  /* string can only be terminated by EOL */
  174.             return (s);
  175.         }
  176.         else
  177.           return (s);
  178.         if (*s++ == c) {
  179.           if (*s==c || *(s-2)=='\\') {
  180.             if (bsize--)  /* "", '' \" or \' don't terminate the string */
  181.               *b++ = *s++;
  182.              else
  183.               return (s);
  184.           }
  185.           else
  186.             break;
  187.         }
  188.       }
  189.     }
  190.   }
  191.   *b = 0;
  192.   return (s);
  193. }
  194.  
  195.  
  196. char *skipspaces(char *s)
  197. /* advance string pointer to the first character, which is no white space */
  198. {
  199.   while (*s==' ' || *s=='\t')
  200.     ++s;
  201.   return (s);
  202. }
  203.  
  204.  
  205. char *remquotes(char *s)
  206. /* remove " or ', if present and return new strbuf-pointer */
  207. {
  208.   int len;
  209.   char c = *s;
  210.  
  211.   if (c=='\"' || c=='\'')  /* string is in quotes */
  212.     if (len = strlen(++s) - 1)
  213.       if (s[len] == c)
  214.         s[len] = 0;
  215.   return (s);
  216. }
  217.  
  218.  
  219. void checkEOL(char *s)
  220. /* check for illegal extra characters on line */
  221. {
  222.   s = skipspaces(s);
  223.   if (*s && *s!='#')  /* only comment is allowed as an extra character */
  224.     error(18);  /* extra characters on line */
  225. }
  226.  
  227.  
  228. char *skipexpression(struct GlobalVars *gv,char *s)
  229. {
  230.   char c;
  231.  
  232.   do {
  233.     s = getarg(gv,s);
  234.     s = skipspaces(s);
  235.     c = *s++;
  236.   }
  237.   while (c!=0 && c!='#' && c!=',');
  238.   return (--s);
  239. }
  240.  
  241.  
  242. void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  243.                        struct MacroParams *mp,char *op)
  244. /* read parameters and store pointers to their first character */
  245. {
  246.   char c;
  247.  
  248.   mp->param[0] = mp->param0;
  249.   if (pl->branch_hint)
  250.     mp->param0[0] = pl->branch_hint>0 ? '+' : '-';
  251.   for (;;) {
  252.     op = skipspaces(op);
  253.     c = *op;
  254.     if (c!=0 && c!='#') {  /* another parameter? */
  255.       if (mp->narg < (MAX_MACPARAMS-1)) {
  256.         mp->param[++mp->narg] = op;
  257.         op = skipexpression(gv,op);
  258.         c = *op;
  259.         if (c==0 || c=='#') {
  260.           *op = 0;  /* end of line / start of comment */
  261.           return;
  262.         }
  263.         *op++ = 0;  /* next parameter */
  264.       }
  265.       else {
  266.         error(11);  /* too many macro parameters */
  267.         return;
  268.       } 
  269.     }
  270.     else
  271.       return;
  272.   }
  273. }
  274.  
  275.  
  276. char *getexp(struct GlobalVars *gv,char *s,uint32 *val,uint8 size)
  277. /* evaluate expression, create relocations or x-references, if required */
  278. {
  279.   struct Expression exp;
  280.  
  281.   s = eval_expression(gv,&exp,s);
  282.   if (exp.type != SYM_UNDEF) {
  283.     if (exp.reloctype==R_PPC_ADDR32 && size==2)
  284.       exp.reloctype = R_PPC_ADDR16;
  285.     switch (exp.type) {
  286.       case SYM_RELOC:
  287.         *val = makereloc(gv,&exp);  /* make relocation entry */
  288.         break;
  289.       case SYM_EXTERN:  /* reference to external symbol */
  290.         *val = makexref(gv,&exp,size);
  291.         break;
  292.       default:  /* SYM_ABS */
  293.         *val = exp.value;
  294.         break;
  295.     }
  296.   }
  297.   else
  298.     error(19);  /* undefined symbol */
  299.   return (s);
  300. }
  301.  
  302.  
  303. static uint32 hihalf(struct GlobalVars *gv,uint32 x)
  304. {
  305.   if (gv->signedexp)
  306.     return ((int32)x/0x10000);
  307.   else
  308.     return (x>>16);
  309. }
  310.  
  311.  
  312. static uint32 lohalf(struct GlobalVars *gv,uint32 x)
  313. {
  314.   if (gv->signedexp)
  315.     return ((int16)x);
  316.   else
  317.     return (x&0xffff);
  318. }
  319.  
  320.  
  321. uint32 makereloc(struct GlobalVars *gv,struct Expression *exp)
  322. /* make new relocation entry for current section */
  323. {
  324.   struct Reloc dummy,*reloc;
  325.  
  326.   if (gv->anotherpass) {
  327.     /* don't waste memory, if another pass is required anyway */
  328.     reloc = &dummy;
  329.   }
  330.   else {
  331.     reloc = alloc(sizeof(struct Reloc));
  332.     addtail(&gv->csect->reloclist,&reloc->n);
  333.   }
  334.   reloc->relocsect = exp->symbol->relsect;
  335.   reloc->offset = gv->csect->pc;
  336.   reloc->type = exp->reloctype;
  337.   reloc->addend = exp->value;
  338.   switch (exp->reloctype) {
  339.     case R_PPC_ADDR16_HA:
  340.     case R_PPC_ADDR16_HI:
  341.       reloc->offset += 2;
  342.       return (hihalf(gv,exp->value));
  343.     case R_PPC_ADDR16_LO:
  344.       reloc->offset += 2;
  345.       return (lohalf(gv,exp->value));
  346.     case R_PPC_TOC16:
  347.       reloc->offset += 2;
  348.       return (exp->value);
  349.     case R_PPC_REL14:
  350.     case R_PPC_REL14_BRTAKEN:
  351.     case R_PPC_REL14_BRNTAKEN:
  352.       if (gv->output == OFMT_EHF) {
  353.         reloc->offset += 2;
  354.         return (exp->value + 2);
  355.       }
  356.     default:
  357.       return (exp->value);
  358.   }
  359. }
  360.  
  361.  
  362. uint32 makexref(struct GlobalVars *gv,struct Expression *exp,uint8 size)
  363. {
  364.   struct XReference dummy,*xref;
  365.  
  366.   if (gv->anotherpass) {
  367.     /* don't waste memory, if another pass is required anyway */
  368.     xref = &dummy;
  369.   }
  370.   else {
  371.     xref = alloc(sizeof(struct XReference));
  372.     addtail(&gv->csect->xreflist,&xref->n);
  373.   }
  374.   xref->xsymbol = exp->symbol;
  375.   xref->offset = gv->csect->pc;
  376.   xref->addend = exp->value;
  377.   xref->type = exp->reloctype;
  378.   xref->size = size;
  379.   switch (exp->reloctype) {
  380.     case R_PPC_ADDR16_HA:
  381.     case R_PPC_ADDR16_HI:
  382.       xref->offset += 2;
  383.       return (hihalf(gv,exp->value));
  384.     case R_PPC_ADDR16_LO:
  385.       xref->offset += 2;
  386.       return (lohalf(gv,exp->value));
  387.     case R_PPC_TOC16:
  388.       xref->offset += 2;
  389.       return (exp->value);
  390.     case R_PPC_REL14:
  391.     case R_PPC_REL14_BRTAKEN:
  392.     case R_PPC_REL14_BRNTAKEN:
  393.       if (gv->output == OFMT_EHF) {
  394.         xref->offset += 2;
  395.         return (exp->value + 2);
  396.       }
  397.     default:
  398.       return (exp->value);
  399.   }
  400. }
  401.  
  402.  
  403. char *getintexp(struct GlobalVars *gv,char *s,uint32 *val)
  404. /* evaluate expression and check if absolute integer */
  405. {
  406.   struct Expression exp;
  407.  
  408.   s = eval_expression(gv,&exp,s);
  409.   if (exp.type != SYM_UNDEF) {
  410.     if (exp.type == SYM_ABS)
  411.       *val = exp.value;
  412.     else
  413.       error(24);  /* constant integer expression required */
  414.   }
  415.   else
  416.     error(19);  /* undefined symbol */
  417.   return (s);
  418. }
  419.  
  420.  
  421. char *eval_expression(struct GlobalVars *gv,struct Expression *exp_result,
  422.                       char *s)
  423. /* evaluate an integer expression and determine its type */
  424. {
  425.   struct Expression exp[EXPSTACKSIZE];
  426.   uint8 ops[EXPSTACKSIZE-1],op,ta,tb;
  427.   int i,j,k,exp_args=0;
  428.   uint8 unary;  /* unary operator, 0=none, 1=plus, 2=minus, 3=not */
  429.   char c;
  430.   char *arg=gv->strbuf;
  431.   struct Symbol *sym;
  432.  
  433.   exp_result->value = 0;
  434.   exp_result->type = SYM_UNDEF;
  435.  
  436.   /* build expression stack */
  437.   for (;;) {
  438.     unary = 0;
  439.     exp[exp_args].reloctype = R_PPC_ADDR32;
  440.  
  441.     for (;;) {
  442.       s = skipspaces(s);
  443.       s = getarg(gv,s);  /* try to get next argument */
  444.       if (c = *arg)
  445.         break;  /* got it */
  446.  
  447.       if ((c=*s++) == '(') {  /* beginning of a term? */
  448.         s = eval_expression(gv,&exp[exp_args],s);
  449.         if (*s++ != ')') {
  450.           error(21);  /* missing closing parenthesis */
  451.           s--;
  452.         }
  453.         *arg = 0;  /* expression in term is already evaluated */
  454.         break;
  455.       }
  456.  
  457.       if (c==0 || c=='#' || c==')') {
  458.         error(17);  /* missing argument */
  459.         s--;
  460.         c = 0;
  461.         break;
  462.       }
  463.  
  464.       if (unary)
  465.         error(20);  /* double unary operator */
  466.       else
  467.         switch (c) {
  468.           case '+':
  469.             unary = 1;
  470.             break;
  471.           case '-':
  472.             unary = 2;
  473.             break;
  474.           case '~':
  475.             unary = 3;
  476.             break;
  477.           default:
  478.             error(13);  /* syntax error */
  479.             break;
  480.         }
  481.     }
  482.  
  483.     if (!c)
  484.       break;  /* evaluate */
  485.  
  486.     if (c = *arg) {
  487.  
  488.       if (c>='0' && c<='9') {  /* numeric constant */
  489.         if (c=='0')
  490.           switch (arg[1]) {
  491.             case 'x':
  492.               exp[exp_args].value = read_hex(&arg[2]);
  493.               break;
  494.             case 'b':
  495.               exp[exp_args].value = read_bin(&arg[2]);
  496.               break;
  497.             case 0:
  498.               exp[exp_args].value = 0;
  499.               break;
  500.             default:
  501.               exp[exp_args].value = read_oct(&arg[1]);
  502.               break;
  503.           }
  504.         else
  505.           exp[exp_args].value = read_dec(arg);
  506.         exp[exp_args].type = SYM_ABS;
  507.       }
  508.  
  509.       else if (c=='\"' || c=='\'') {  /* string constant */
  510.         exp[exp_args].value = read_str(arg);
  511.         exp[exp_args].type = SYM_ABS;
  512.       }
  513.  
  514.       else {  /* get symbol value */
  515.         if (sym = search_symbol(gv,arg)) {
  516.           exp[exp_args].value = sym->value;
  517.           exp[exp_args].type = sym->type;
  518.           exp[exp_args].symbol = sym;
  519.         }
  520.         else {
  521.           if (gv->pass && gv->autoextern) {  /* pass 2? auto. decl. extern */
  522.             sym = add_symbol(gv,arg,SYM_EXTERN,0);
  523.             exp[exp_args].value = sym->value;
  524.             exp[exp_args].type = sym->type;
  525.             exp[exp_args].symbol = sym;
  526.           }
  527.           else {
  528.             exp[exp_args].value = 0;
  529.             exp[exp_args].type = SYM_UNDEF;
  530.           }
  531.         }
  532.       }
  533.     }
  534.  
  535.     if (unary) {
  536.       if (exp[exp_args].type >= SYM_RELOC)
  537.         error(22);  /* illegal operation for a relocatable expression */
  538.       else
  539.         switch (unary) {
  540.           case 2:  /* negate */
  541.             exp[exp_args].value = -exp[exp_args].value;
  542.             break;
  543.           case 3:  /* not */
  544.             exp[exp_args].value = ~exp[exp_args].value;
  545.             break;
  546.         }
  547.     }
  548.     if (exp[exp_args].type == SYM_ABS)
  549.       exp[exp_args].reloctype = R_NONE;
  550.  
  551.     /* check for operator */
  552.     s = skipspaces(s);
  553.     c = *s;
  554.     i = 0;
  555.     while (i<NUMOPS) {
  556.       if (c == valid_operators[i])
  557.         break;
  558.       i++;
  559.     }
  560.     if (i==NUMOPS)
  561.       break;  /* end of expression - evaluate */
  562.  
  563.     ops[exp_args++] = i;
  564.     if (*(++s) == c)
  565.       if (i==5 || i==6)  /* <<, >> */
  566.         ++s;
  567.   }
  568.  
  569.   /* evaluate expression stack */
  570.   for (i=MAXOPPRI; i>=0; i--) {
  571.     for (j=0; j<exp_args; ) {
  572.       op = ops[j];
  573.       if (op_priority[op] == i) {
  574.         if (!(ta = exp[j].type) || !(tb = exp[j+1].type)) {
  575.           exp[j].value = 0;
  576.           exp[j].type = SYM_UNDEF;
  577.           exp[j].reloctype = R_PPC_ADDR32;
  578.         }
  579.         else switch(op) {
  580.  
  581.           case 0:  /* + */
  582.             if (ta != tb) {
  583.               if (ta == SYM_ABS) {
  584.                 exp[j].type = tb;  /* reloc + abs = reloc */
  585.                 exp[j].reloctype = exp[j+1].reloctype;
  586.                 exp[j].symbol = exp[j+1].symbol;
  587.               }
  588.               else if (tb != SYM_ABS) {
  589.                 error(22);  /* illegal reloc operation */
  590.                 break;
  591.               }          
  592.             }
  593.             else if (ta >= SYM_RELOC) {
  594.               error(22);
  595.               break;
  596.             }
  597.             exp[j].value += exp[j+1].value;
  598.             break;
  599.  
  600.           case 1:  /* - */
  601.             if (ta != tb) {  /* reloc - abs = reloc */
  602.               if (tb != SYM_ABS) {
  603.                 error(22);
  604.                 break;
  605.               }
  606.             }
  607.             else {  /* reloc - reloc = abs  |  abs - abs = abs */
  608.               if (ta != SYM_EXTERN) {  /* extern - extern  not supported */
  609.                 exp[j].type = SYM_ABS;
  610.                 if (ta == SYM_RELOC)
  611.                   if (exp[j].symbol->relsect != exp[j+1].symbol->relsect)
  612.                     error(23);  /* symbols reside in different sections */
  613.               }
  614.               else {
  615.                 error(22);
  616.                 break;
  617.               }
  618.             }
  619.             exp[j].value -= exp[j+1].value;
  620.             break;
  621.  
  622.           case 2:  /* * */
  623.             if (ta == tb == SYM_ABS)
  624.               exp[j].value *= exp[j+1].value;
  625.             else
  626.               error(22);
  627.             break;
  628.  
  629.           case 3:  /* / */
  630.             if (ta == tb == SYM_ABS)
  631.               exp[j].value /= exp[j+1].value;
  632.             else
  633.               error(22);
  634.             break;
  635.  
  636.           case 4:  /* % */
  637.             if (ta == tb == SYM_ABS)
  638.               exp[j].value %= exp[j+1].value;
  639.             else
  640.               error(22);
  641.             break;
  642.  
  643.           case 5:  /* << */
  644.             if (ta == tb == SYM_ABS)
  645.               exp[j].value <<= exp[j+1].value;
  646.             else
  647.               error(22);
  648.             break;
  649.  
  650.           case 6:  /* << */
  651.             if (ta == tb == SYM_ABS)
  652.               exp[j].value >>= exp[j+1].value;
  653.             else
  654.               error(22);
  655.             break;
  656.  
  657.           case 7:  /* & */
  658.             if (ta == tb == SYM_ABS)
  659.               exp[j].value &= exp[j+1].value;
  660.             else
  661.               error(22);
  662.             break;
  663.  
  664.           case 8:  /* | */
  665.             if (ta == tb == SYM_ABS)
  666.               exp[j].value |= exp[j+1].value;
  667.             else
  668.               error(22);
  669.             break;
  670.  
  671.           case 9:  /* ^ */
  672.             if (ta == tb == SYM_ABS)
  673.               exp[j].value ^= exp[j+1].value;
  674.             else
  675.               error(22);
  676.             break;
  677.         }
  678.  
  679.         exp_args--;
  680.         for (k=j; k<exp_args; k++) {
  681.           memcpy(&exp[k+1],&exp[k+2],sizeof(struct Expression));
  682.           ops[k] = ops[k+1];
  683.         }
  684.       }
  685.       else
  686.         j++;
  687.     }
  688.     if (exp_args==0)
  689.       break;
  690.   }
  691.  
  692.   memcpy(exp_result,&exp[0],sizeof(struct Expression));
  693.   if (*s == '@') {  /* check for @ha, @h or @l */
  694.     s++;
  695.     switch (tolower((unsigned char)*s++)) {
  696.       case 'l':  /* symbol@l : lower half-word */
  697.         if (exp_result->type == SYM_ABS) {
  698.           exp_result->reloctype = R_NONE;
  699.           exp_result->value = lohalf(gv,exp_result->value);
  700.         }
  701.         else
  702.           exp_result->reloctype = R_PPC_ADDR16_LO;
  703.         break;
  704.       case 'h':
  705.         if (tolower((unsigned char)*s) == 'a') {
  706.           s++;  /* symbol@ha : higher (addi) */
  707.           if (exp_result->type == SYM_ABS) {
  708.             exp_result->reloctype = R_NONE;
  709.             if (exp_result->value & 0x8000)
  710.               exp_result->value = hihalf(gv,exp_result->value + 0x10000);
  711.             else
  712.               exp_result->value = hihalf(gv,exp_result->value);
  713.           }
  714.           else
  715.             exp_result->reloctype = R_PPC_ADDR16_HA;
  716.         }
  717.         else {  /* symbol@h : higher half-word */
  718.           if (exp_result->type == SYM_ABS) {
  719.             exp_result->reloctype = R_NONE;
  720.             exp_result->value = hihalf(gv,exp_result->value);
  721.           }
  722.           else
  723.             exp_result->reloctype = R_PPC_ADDR16_HI;
  724.         }
  725.         break;
  726.       default:
  727.         s -= 2;
  728.         break;
  729.     }
  730.   }
  731.  
  732.   return (s);
  733. }
  734.  
  735.  
  736. static uint32 read_hex(char *s)
  737. {
  738.   uint32 x=0,y;
  739.  
  740.   while (y = (unsigned char)*s++) {
  741.     if (y > '9')
  742.       y = (y & 0x5f) - 7;
  743.     x <<= 4;
  744.     x += y - '0';
  745.   }
  746.   return (x);
  747. }
  748.  
  749.  
  750. static uint32 read_dec(char *s)
  751. {
  752.   uint32 x=0,y;
  753.  
  754.   while (y = (unsigned char)*s++) {
  755.     x *= 10;
  756.     x += y - '0';
  757.   }
  758.   return (x);
  759. }
  760.  
  761.  
  762. static uint32 read_oct(char *s)
  763. {
  764.   uint32 x=0,y;
  765.  
  766.   while (y = (unsigned char)*s++) {
  767.     x <<= 3;
  768.     x += y - '0';
  769.   }
  770.   return (x);
  771. }
  772.  
  773.  
  774. static uint32 read_bin(char *s)
  775. {
  776.   uint32 x=0,y;
  777.  
  778.   while (y = (unsigned char)*s++) {
  779.     x <<= 1;
  780.     x += y & 1;
  781.   }
  782.   return (x);
  783. }
  784.  
  785.  
  786. static uint32 read_str(char *s)
  787. {
  788.   uint32 x=0;
  789.   char c,sc=*s++;
  790.  
  791.   while (c = *s++) {
  792.     if (c==sc) {
  793.       if (*s==sc)   /* "" is converted into " */
  794.         s++;
  795.       else
  796.         break;
  797.     }
  798.     else if (c=='\\') {
  799.       if (!(c = escchar(*s++)))
  800.         break;
  801.     }
  802.     x <<= 8;
  803.     x += (unsigned char)c;
  804.   }
  805.   return (x);
  806. }
  807.