home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / cctools / as / i860.c < prev    next >
C/C++ Source or Header  |  1997-01-24  |  29KB  |  1,235 lines

  1. /* i860.c -- Assemble for the i860
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <mach-o/i860/reloc.h>
  25.  
  26. #include "i860-opcode.h"
  27. #include "as.h"
  28. #include "flonum.h"
  29. #include "expr.h"
  30. #include "hash.h"
  31. #include "frags.h"
  32. #include "fixes.h"
  33. #include "read.h"
  34. #include "md.h"
  35. #include "symbols.h"
  36. #include "messages.h"
  37. #include "sections.h"
  38.  
  39. /*
  40.  * These are the default cputype and cpusubtype for the i860 architecture.
  41.  */
  42. const cpu_type_t md_cputype = CPU_TYPE_I860;
  43. cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_I860_ALL;
  44.  
  45. /*
  46.  * This is the byte sex for the i860 architecture.  The chip is running in
  47.  * big endian mode so the assembler puts out the entire file (instructions
  48.  * included) in big endian.  When the program is loaded in memory to be run
  49.  * the program doing the loading byte swaps the fix width instructions.  If
  50.  * this is not to be done by the loading program then BYTE_SWAP can be defined
  51.  * in here that will put out the instructiona in little endian in the object
  52.  * file.
  53.  */
  54. const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
  55.  
  56. static int i860_ip(
  57.     char *str);
  58. static void md_insn_to_chars(
  59.     unsigned char *buf,
  60.     long val,
  61.     int n);
  62.  
  63. const relax_typeS md_relax_table[] = { {0} };
  64.  
  65. /* handle of the OPCODE hash table */
  66. static struct hash_control *op_hash = NULL;
  67.  
  68. static void s_dual(
  69.     int mode);
  70. static void s_i860_align(
  71.     int value);
  72. static void s_i860_org(
  73.     int value);
  74.  
  75. const pseudo_typeS md_pseudo_table[] = {
  76.     { "float",    float_cons,    'f'    },
  77.     { "int",    cons,        4    },
  78.     { "align",    s_i860_align,    0    },    /* Alignment is in bytes */
  79.     { "blkb",    s_space,    0    },    /* Reserve space, in bytes */
  80.     { "dual",    s_dual,        1    },    /* Dual insn mode crock */
  81.     { "enddual",s_dual,        0    },
  82.     { "extern",    s_globl,    0    },    /* as860 equiv of .globl */
  83.     { "ln",    s_line,        0    },    /* as860 equiv of .line */
  84.     { "org",    s_i860_org,    0    },
  85. #ifndef NeXT
  86.     { "quad",    big_cons,    16    },    /* A quad is 16 bytes on 860 */
  87. #endif /* NeXT */
  88.     { "string",    stringer,    1    },    /* as860 equiv of .asciz */
  89.     { NULL,     0,        0    },
  90. };
  91.  
  92. static int dual_insn_mode = 0;
  93.  
  94. /* This array holds the chars that always start a comment.  If the
  95.     pre-processor is disabled, these aren't very useful */
  96. const char md_comment_chars[] = "|!";
  97.  
  98. /* This array holds the chars that only start a comment at the beginning of
  99.    a line.  If the line seems to have the form '# 123 filename'
  100.    .line and .file directives will appear in the pre-processed output */
  101. /* Note that input_file.c hand checks for '#' at the beginning of the
  102.    first line of the input file.  This is because the compiler outputs
  103.    #NO_APP at the beginning of its output. */
  104. /* Also note that a '/' followed by a '*' will always start a comment */
  105. const char md_line_comment_chars[] = "#";
  106.  
  107. /* Chars that can be used to separate mant from exp in floating point nums */
  108. const char md_EXP_CHARS[] = "eE";
  109.  
  110. /* Chars that mean this number is a floating point constant */
  111. /* As in 0f12.456 */
  112. /* or    0d1.2345e12 */
  113. const char md_FLT_CHARS[] = "rRsSfFdDxXpP";
  114.  
  115. /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
  116.    changed in read.c .  Ideally it shouldn't have to know about it at all,
  117.    but nothing is ideal around here.
  118.  */
  119. int size_reloc_info = sizeof(struct relocation_info);
  120.  
  121. static unsigned char octal[256];
  122. #define isoctal(c)  octal[c]
  123. static unsigned char toHex[256];
  124.  
  125. /* Local fatal error flag.  Used to bomb assembler in md_end after scanning input */
  126. static int I860_errors;
  127.  
  128. static int insn_count;    /* Track insns assembled, as a word count */
  129.  
  130. struct i860_it {
  131.     char    *error;
  132.     unsigned long opcode;
  133.     struct nlist *nlistp;
  134.     expressionS exp;
  135.     int pcrel;
  136.     enum reloc_type_i860 reloc;
  137. };
  138. static struct i860_it the_insn;
  139.  
  140. #ifdef I860_DEBUG
  141. static void print_insn(
  142.     struct i860_it *insn);
  143. #endif /* I860_DEBUG */
  144.  
  145. static int getExpression(
  146.     char *str);
  147. static char *expr_end;
  148.  
  149. /* Flags returned by i860_ip() */
  150. #define INSERT_NOP    0x00000001
  151.  
  152. static
  153. void
  154. s_dual(
  155. int mode)
  156. {
  157.     dual_insn_mode = mode;
  158. }
  159.  
  160. static
  161. void
  162. s_i860_align(
  163. int value)
  164. {
  165.     register unsigned int temp;
  166.     register long int temp_fill;
  167.     unsigned int i = 0;
  168.     unsigned int bytes;
  169.     char *toP;
  170.  
  171.     bytes = temp = get_absolute_expression ();
  172. #define MAX_ALIGNMENT (1 << 15)
  173.     if ( temp > MAX_ALIGNMENT ) {
  174.     as_warn("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
  175.     }
  176.  
  177.     /*
  178.      * For the i860, `.align (1<<n)' actually means `.align n'
  179.      * so we have to convert it.
  180.      */
  181.     if (temp != 0) {
  182.     for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
  183.         ;
  184.     }
  185.     if (temp != 1) {
  186.     as_warn("Alignment not a power of 2");
  187.     }
  188.     temp = i;
  189.     if (*input_line_pointer == ',') {
  190.     input_line_pointer ++;
  191.     temp_fill = get_absolute_expression ();
  192.     } else {
  193.     if ( frchain_now->frch_nsect == text_nsect )
  194.             temp_fill = OP_NOP;
  195.     else
  196.         temp_fill = 0;
  197.     }
  198.     if ( frchain_now->frch_nsect == text_nsect )    /* emit NOPs! */
  199.     {    /* Grow the code frag as needed and dump nops into it. */
  200.     if ( bytes & 3 )
  201.         as_warn( "Instruction alignment must be a multiple of 4." );
  202.     bytes &= ~3;
  203.     /* This is really tacky, but works for a fixed width insn machine */
  204.         while ( bytes && ((insn_count * 4) % bytes) != 0 ) 
  205.     {
  206.         toP = frag_more(4);    /* Add an instruction */
  207.         /* put out the opcode */
  208.         md_insn_to_chars(toP, temp_fill, 4);    /* Fill instruction */
  209.         insn_count++;
  210.     }
  211.         /* Clean up */
  212.     demand_empty_rest_of_line();
  213.     return;
  214.     }
  215.     /* Only make a frag if we HAVE to. . . */
  216.     if (temp) {
  217.     frag_align (temp, (int)temp_fill);
  218.     }
  219.     /*
  220.      * If this alignment is larger than any previous alignment then this
  221.      * becomes the section's alignment.
  222.      */
  223.     if(frchain_now->frch_section.align < temp)
  224.     frchain_now->frch_section.align = temp;
  225.     demand_empty_rest_of_line();
  226.     return;
  227. }
  228.  
  229. static
  230. void
  231. s_i860_org(
  232. int value)
  233. {
  234.     register segT segment;
  235.     expressionS exp;
  236.     register long int temp_fill;
  237.     register char *p;
  238.     extern segT get_known_segmented_expression();
  239.  
  240. /*
  241.  * Don't believe the documentation of BSD 4.2 AS.
  242.  * There is no such thing as a sub-segment-relative origin.
  243.  * Any absolute origin is given a warning, then assumed to be segment-relative.
  244.  * Any segmented origin expression ("foo+42") had better be in the right
  245.  * segment or the .org is ignored.
  246.  *
  247.  * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
  248.  * never know sub-segment sizes when we are reading code.
  249.  * BSD will crash trying to emit -ve numbers of filler bytes in certain
  250.  * .orgs. We don't crash, but see as-write for that code.
  251.  */
  252.     segment = get_known_segmented_expression(& exp);
  253.     if ( *input_line_pointer == ',' ) {
  254.         input_line_pointer ++;
  255.         temp_fill = get_absolute_expression ();
  256.     } else
  257.         temp_fill = 0;
  258.  
  259.     if((segment != SEG_SECT ||
  260.         exp.X_add_symbol->sy_other != frchain_now->frch_nsect) &&
  261.         segment != SEG_ABSOLUTE)
  262.         as_warn("Illegal expression. current section assumed.");
  263.  
  264.     if ( exp.X_add_symbol != NULL )
  265.         as_warn("Symbol relative .org may corrupt alignment.");
  266.     else if ( exp.X_add_number & 3 )
  267.     {
  268.         exp.X_add_number &= ~3;
  269.         as_warn(".org not on instruction boundry. Adjusted to \".org %ld\"",
  270.         exp.X_add_number);
  271.     }
  272.     if ( exp.X_add_symbol == NULL )
  273.         insn_count = exp.X_add_number >> 2;
  274.     p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
  275. exp . X_add_number, (char *)0);
  276.     * p = temp_fill;
  277.  
  278.     demand_empty_rest_of_line();
  279. }
  280.  
  281.  
  282. /*
  283.  * This function is called once, at assembler startup time.  This should
  284.  * set up all the tables, etc that the MD part of the assembler needs
  285.  */
  286. void
  287. md_begin(
  288. void)
  289. {
  290.     register char *retval = NULL;
  291.     register int i;
  292.     int j = 0;
  293.  
  294.     insn_count = 0;
  295.     if ((op_hash = hash_new()) == NULL)
  296.     as_fatal("Virtual memory exhausted");
  297.  
  298.     for (i = 0; i < NUMOPCODES; ++i) {
  299.     if (~i860_opcodes[i].mask & i860_opcodes[i].match) {
  300.         printf("bad opcode - `%s %s'\n",
  301.         i860_opcodes[i].name, i860_opcodes[i].args);
  302.         ++j;
  303.     }
  304.     }
  305.  
  306.     if (j)
  307.     exit(1);
  308.  
  309.     for (i = 0; i < NUMOPCODES; ++i) {
  310.       retval = hash_insert(op_hash, (char *)i860_opcodes[i].name,
  311.                (char *)&i860_opcodes[i]);
  312.       if(retval && *retval) {
  313.       as_fatal("Internal Error:  Can't hash %s: %s",
  314.         i860_opcodes[i].name, retval);
  315.       }
  316.       while (!i860_opcodes[i].last)
  317.       ++i;
  318.     }
  319.     for (i = '0'; i < '8'; ++i)
  320.     octal[i] = 1;
  321.     for (i = '0'; i <= '9'; ++i)
  322.     toHex[i] = i - '0';
  323.     for (i = 'a'; i <= 'f'; ++i)
  324.     toHex[i] = i + 10 - 'a';
  325.     for (i = 'A'; i <= 'F'; ++i)
  326.     toHex[i] = i + 10 - 'A';
  327.  
  328.     I860_errors = 0;
  329.     return;
  330. }
  331.  
  332. void
  333. md_end(
  334. void)
  335. {
  336.     if ( I860_errors )
  337.     {
  338.         fprintf( stderr, "%d fatal %s encountered during assembly.\n", I860_errors,
  339.         (I860_errors == 1 ? "error" : "errors") );
  340.         exit( 42 );    /* Fatal errors seen during assembly */
  341.     }
  342.  
  343.     return;
  344. }
  345.  
  346. void
  347. md_assemble(
  348. char *str)
  349. {
  350.     char *toP;
  351.     int flags;
  352.  
  353.     assert(str);
  354.     flags = i860_ip(str);
  355.     if ( flags & INSERT_NOP )
  356.     {
  357.         toP = frag_more(4);
  358.         /* put out the opcode */
  359.         md_insn_to_chars(toP, OP_NOP, 4);
  360.     ++insn_count;
  361.     }
  362.     toP = frag_more(4);
  363.     /* put out the opcode */
  364.     md_insn_to_chars(toP, the_insn.opcode, 4);
  365.     ++insn_count;
  366.  
  367.     /* put out the symbol-dependent stuff */
  368.     if (the_insn.reloc != NO_RELOC) {
  369.     fix_new(
  370.         frag_now,                           /* which frag */
  371.         (toP - frag_now->fr_literal), /* where */
  372.         4,                                  /* size */
  373.         the_insn.exp.X_add_symbol,
  374.         the_insn.exp.X_subtract_symbol,
  375.         the_insn.exp.X_add_number,
  376.         the_insn.pcrel, 0,
  377.         the_insn.reloc
  378.     );
  379.     }
  380. }
  381.  
  382. static
  383. int
  384. i860_ip(
  385. char *str)
  386. {
  387.     char *s;
  388.     char *op;
  389.     const char *args;
  390.     char c;
  391.     struct i860_opcode *insn;
  392.     char *argsStart;
  393.     char *s1;
  394.     unsigned long   opcode;
  395.     unsigned int mask;
  396.     int this_insn_is_dual = 0;
  397.     int adjustment;
  398.     int    align_mask;
  399.     int match = FALSE;
  400.     int comma = 0;
  401.     int flags = 0;
  402.     static int expect_int_insn;    /* Tracking for fp/int insns in dual mode. */
  403.  
  404.     /* Advance s to end of opcode */
  405.     for (s = str; islower(*s) || *s == '.' || isdigit(*s); ++s)
  406.     ;
  407.     switch (*s) {
  408.  
  409.     case '\0':
  410.     break;
  411.  
  412.     case ',':
  413.     comma = 1;
  414.  
  415.     /*FALLTHROUGH*/
  416.  
  417.     case ' ':
  418.     case '\t':
  419.     *s++ = '\0';
  420.     break;
  421.  
  422.     default:
  423.         as_warn("Unknown opcode: `%s'", str);
  424.         exit(1);
  425.     }
  426.     /* Code to sniff for 'd.' prefix here and flag for dual insn mode */
  427.     op = str;
  428.     if ( *op == 'd' && *(op + 1) == '.' )
  429.     {
  430.         op += 2;
  431.     this_insn_is_dual = 1;
  432.     }
  433.         
  434.     if ((insn = (struct i860_opcode *) hash_find(op_hash, op)) == NULL) {
  435.     as_warn("Unknown instruction or format: `%s'.", str);
  436.     memset(&the_insn, '\0', sizeof(the_insn));    /* Patch in no-op to hold alignment */
  437.     the_insn.reloc = NO_RELOC;
  438.     the_insn.opcode = OP_NOP;
  439.     ++I860_errors;                /* Flag as fatal error */
  440.     return flags;
  441.     }
  442.     if (comma) {
  443.     *--s = ',';
  444.     }
  445.     argsStart = s;
  446.     for (;;) {
  447.     opcode = insn->match;
  448.     memset(&the_insn, '\0', sizeof(the_insn));
  449.     the_insn.reloc = NO_RELOC;
  450.  
  451.     /*
  452.      * Build the opcode, checking as we go to make
  453.      * sure that the operands match
  454.      */
  455.     for (args = insn->args; ; ++args) {
  456.         align_mask = 0;
  457.         switch (*args) {
  458.  
  459.         case '\0':  /* end of args */
  460.         if (*s == '\0') {
  461.             match = TRUE;
  462.         }
  463.         break;
  464.  
  465.         case '+':
  466.         case '(':   /* these must match exactly */
  467.         case ')':
  468.         case ',':
  469.         case ' ':
  470.         if (*s++ == *args)
  471.             continue;
  472.         break;
  473.         
  474.         case 'C':   /* Control register */
  475.         if (strncmp(s, "fir", 3) == 0) {
  476.             s += 3;
  477.             SET_RS2(opcode, 0);
  478.             continue;
  479.         }
  480.         if (strncmp(s, "psr", 3) == 0) {
  481.             s += 3;
  482.             SET_RS2(opcode, 1);
  483.             continue;
  484.         }
  485.         if (strncmp(s, "dirbase", 7) == 0) {
  486.             s += 7;
  487.             SET_RS2(opcode, 2);
  488.             continue;
  489.         }
  490.         if (strncmp(s, "db", 2) == 0) {
  491.             s += 2;
  492.             SET_RS2(opcode, 3);
  493.             continue;
  494.         }
  495.         if (strncmp(s, "fsr", 3) == 0) {
  496.             s += 3;
  497.             SET_RS2(opcode, 4);
  498.             continue;
  499.         }
  500.         if (strncmp(s, "epsr", 4) == 0) {
  501.             s += 4;
  502.             SET_RS2(opcode, 5);
  503.             continue;
  504.         }
  505.         break;
  506.  
  507.         case '1':    /* next operand must be a register */
  508.         case '2':
  509.         case 'd':
  510.         {
  511.             switch (c = *s++) {
  512.  
  513.             case 'f':   /* frame pointer */
  514.                 if (*s++ == 'p') {
  515.                 mask = 3;    /* register fp is alias for r3 */
  516.                 break;
  517.             }
  518.             goto error;
  519.  
  520.             case 's':   /* global register */
  521.             if (*s++ == 'p') {
  522.                 mask = 2;    /* register sp is alias for r2 */
  523.                 break;
  524.             }
  525.             goto error;
  526.  
  527.             case 'r': /* any register */
  528.                 if (!isdigit(c = *s++)) {
  529.                 goto error;
  530.             }
  531.             if (isdigit(*s)) {
  532.                 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
  533.                 goto error;
  534.                 }
  535.             } else {
  536.                 c -= '0';
  537.             }
  538.             mask= c;
  539.             break;
  540.  
  541.             default:
  542.             goto error;
  543.             }
  544.             /*
  545.              * Got the register, now figure out where
  546.              * it goes in the opcode.
  547.              */
  548.             switch (*args) {
  549.  
  550.             case '1':
  551.                 SET_RS1(opcode, mask);
  552.             continue;
  553.  
  554.             case '2':
  555.                 SET_RS2(opcode, mask);
  556.             continue;
  557.  
  558.             case 'd':
  559.                 SET_RD(opcode, mask);
  560.             continue;
  561.             }
  562.         }
  563.         break;
  564.  
  565.         case 'e':    /* next operand is a floating point register */
  566.         case 'f':
  567.         case 'g':
  568.         case 'E':
  569.         case 'F':
  570.         case 'G':
  571.         case 'H':
  572.             if (*s++ == 'f' && isdigit(*s)) {
  573.             mask = *s++;
  574.             if (isdigit(*s)) {
  575.             mask = 10 * (mask - '0') + (*s++ - '0');
  576.             if (mask >= 32) {
  577.                 break;
  578.             }
  579.             } else {
  580.             mask -= '0';
  581.             }
  582.             if ( (*args == 'E' || *args == 'F' || *args == 'G') && (mask & 1) )
  583.             {
  584.                 as_warn( "f%d: Even register required.  Adjusted to f%d.",
  585.                 mask, mask & 0x1E );
  586.             mask &= 0x1E;
  587.             }
  588.             else if ( *args == 'H' && (mask & 3) )
  589.             {
  590.                 as_warn( "f%d: Quad register required.  Adjusted to f%d.",
  591.                 mask, mask & 0x1C );
  592.             mask &= 0x1C;
  593.             }
  594.             switch (*args) {
  595.  
  596.             case 'e':
  597.             case 'E':
  598.                 SET_RS1(opcode, mask);
  599.             continue;
  600.  
  601.             case 'f':
  602.             case 'F':
  603.                 SET_RS2(opcode, mask);
  604.             continue;
  605.  
  606.             case 'g':
  607.             case 'G':
  608.             case 'H':
  609.                 SET_RD(opcode, mask);
  610.             continue;
  611.             }
  612.         }
  613.         break;
  614.     
  615.         case 'B':    /* 5 bit immediate unsigned constant */    
  616.           (void)getExpression(s);
  617.         s = expr_end;
  618.         if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
  619.         {
  620.             as_warn( "Constant expression expected" );
  621.             ++I860_errors;
  622.         }
  623.         if ( the_insn.exp.X_add_number < 0 || the_insn.exp.X_add_number > 31 )
  624.             as_warn( "Constant must be between 0 and 31. Modulo 32 applied." );
  625.         SET_RS1(opcode, the_insn.exp.X_add_number); /* Takes const modulo 32 */
  626.         continue;
  627.         
  628.         case 'D':    /* immediate unsigned constant used in shift opcodes */    
  629.           (void)getExpression(s);
  630.         s = expr_end;
  631.         if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
  632.         {
  633.             as_warn( "Constant expression expected" );
  634.             ++I860_errors;
  635.         }
  636.         if ( the_insn.exp.X_add_number < 0 || the_insn.exp.X_add_number > 31 )
  637.             as_warn( "Constant must be between 0 and 31. Modulo 32 applied." );
  638.         opcode |= (the_insn.exp.X_add_number & 0x1F);
  639.         continue;
  640.  
  641.         case 'i':       /* low 16 bits, byte aligned */
  642.             the_insn.reloc = I860_RELOC_LOW0;
  643.         goto immediate;
  644.         
  645.         case 'I':       /* high 16 bits */
  646.             the_insn.reloc = I860_RELOC_HIGH;
  647.         goto immediate;
  648.  
  649.         case 'j':       /* low 16 bits, short aligned */
  650.             the_insn.reloc = I860_RELOC_LOW1;
  651.         align_mask = 1;
  652.         goto immediate;
  653.  
  654.         case 'k':       /* low 16 bits, int aligned */
  655.             the_insn.reloc = I860_RELOC_LOW2;
  656.         align_mask = 3;
  657.         goto immediate;
  658.  
  659.         case 'l':       /* low 16 bits, double aligned */
  660.             the_insn.reloc = I860_RELOC_LOW3;
  661.         align_mask = 7;
  662.         goto immediate;
  663.  
  664.         case 'm':       /* low 16 bits, quad aligned */
  665.             the_insn.reloc = I860_RELOC_LOW4;
  666.         align_mask = 15;
  667.         goto immediate;
  668.  
  669.         case 'n':       /* low 16 bits, byte aligned, split field */
  670.             the_insn.reloc = I860_RELOC_SPLIT0;
  671.         goto immediate;
  672.  
  673.         case 'o':       /* low 16 bits, short aligned, split field */
  674.             the_insn.reloc = I860_RELOC_SPLIT1;
  675.         align_mask = 1;
  676.         goto immediate;
  677.  
  678.         case 'p':       /* low 16 bits, int aligned, split field */
  679.             the_insn.reloc = I860_RELOC_SPLIT2;
  680.         align_mask = 3;
  681.         goto immediate;
  682.  
  683.         case 'J':       /* High 16 bits, requiring adjustment */
  684.             the_insn.reloc = I860_RELOC_HIGHADJ;
  685.         goto immediate;
  686.  
  687.  
  688.         case 'K':   /* 26 bit PC relative immediate */
  689.             the_insn.reloc = I860_RELOC_BRADDR;
  690.         the_insn.pcrel = 1;
  691.         goto immediate;
  692.  
  693.         case 'L':   /* 16 bit PC relative split format immediate */
  694.             the_insn.reloc = I860_RELOC_SPLIT0;
  695.         the_insn.pcrel = 1;
  696.         goto immediate;
  697.         /*FALLTHROUGH*/
  698.  
  699.         immediate:
  700.         if(*s==' ')
  701.           s++;
  702.         adjustment = 0;
  703.         if ( *s == 'h' && *(s + 1) == '%' )
  704.         {
  705.             adjustment = I860_RELOC_HIGH;
  706.             if ( the_insn.reloc == I860_RELOC_LOW0 && the_insn.pcrel == 0 )
  707.             {
  708.                 the_insn.reloc = I860_RELOC_HIGH;
  709.             }
  710.             else
  711.                 as_warn("Improper use of h%%.");
  712.             s += 2;
  713.         }
  714.         else if ( *s == 'h' && *(s + 1) == 'a' && *(s + 2) == '%' )
  715.         {
  716.             adjustment = I860_RELOC_HIGHADJ;
  717.             if ( the_insn.reloc == I860_RELOC_LOW0 && the_insn.pcrel == 0 )
  718.             {
  719.                 the_insn.reloc = I860_RELOC_HIGHADJ;
  720.             }
  721.             else
  722.                 as_warn("Improper use of ha%%.");
  723.  
  724.             s += 3;
  725.         }
  726.         else if ( *s == 'l' &&  *(s + 1) == '%' )
  727.         {    /* the_insn.reloc is correct as is. */
  728.             adjustment = I860_RELOC_LOW0;
  729.             s += 2;
  730.         }
  731.         /* Note that if the getExpression() fails, we will still have
  732.            created U entries in the symbol table for the 'symbols'
  733.            in the input string.  Try not to create U symbols for
  734.            registers, etc. */
  735.            
  736.         /* This stuff checks to see if the expression ends
  737.            in '(', as in ld.l foo(r20). If it does, it
  738.            removes the '(' from the expression, and 
  739.            re-sets 's' to point to the right place */
  740.  
  741.         for(s1=s;*s1 && *s1!=','&& *s1!=')';s1++)
  742.             ;
  743.  
  744.         if( s1 != s && *s1 == '(' && s1[1] == 'r' && isdigit(s1[2])
  745.             && (s1[3]==')' || (isdigit(s1[3]) && s1[4] == ')')) ) {
  746.                 *s1='\0';
  747.                 (void)getExpression(s);
  748.                 *s1='(';
  749.                 s=s1;
  750.         }
  751.         else
  752.         {
  753.             (void)getExpression(s);
  754.             s = expr_end;
  755.         }
  756.         /*
  757.          * If there is an adjustment, we assume the user knows what
  758.          * they are doing.  If no adjustment, we very carefully range 
  759.          * check for both signed and unsigned operations, to avoid 
  760.          * unpleasant suprises.  The checks are skipped for branch and
  761.          * call instructions, matching the behavior of the Intel assembler.
  762.          */
  763.         if ( ! adjustment && *op != 'b' && *op != 'c' )
  764.         {
  765.             if ( the_insn.exp.X_seg != SEG_ABSOLUTE )
  766.             {
  767.             as_warn(
  768.               "Non-absolute expression requires h%%, l%%, or ha%% prefix."
  769.             );
  770.             }
  771.             else
  772.             {
  773.                 if ( IS_LOGOP(opcode) )
  774.             {
  775.                 if ( ((unsigned)the_insn.exp.X_add_number) > 0xFFFF )
  776.                     as_warn("%lu is too big for 16 bit unsigned value!",
  777.                     the_insn.exp.X_add_number);
  778.             }
  779.             else
  780.             {
  781.                 if ( ((int)the_insn.exp.X_add_number) > 32767 ||
  782.                      ((int)the_insn.exp.X_add_number) < -32768 )
  783.                 as_warn("%ld is out of range for 16 bit signed value!",
  784.                     the_insn.exp.X_add_number);
  785.                     
  786.                 if ((align_mask & the_insn.exp.X_add_number) != 0)
  787.                     as_warn("Const offset 0x%x incorrectly aligned.",
  788.                     (unsigned int)the_insn.exp.X_add_number);
  789.             }
  790.             }
  791.         }
  792.         continue;
  793.         
  794.         default:
  795.         abort();
  796.         }
  797.         break;
  798.     }
  799.     error:
  800.     if (match == FALSE) {
  801.         /* args don't match */
  802.         if (!insn->last) {
  803.         ++insn;
  804.         s = argsStart;
  805.         continue;
  806.         } else {
  807.         as_warn("Illegal operands (%s %s).", str, argsStart);
  808.         ++I860_errors;
  809.         return flags;
  810.         }
  811.     }
  812.     break;
  813.     }
  814.     /* If the last insn was dual, check and make sure that this insn is integer insn */
  815.     if ( expect_int_insn && (dual_insn_mode || this_insn_is_dual) )
  816.     {
  817.             if ( (opcode & OP_PREFIX_MASK) == PREFIX_FPU || opcode == OP_FNOP )
  818.         {
  819.         as_warn( "Core half of prev dual insn pair missing." );
  820.         }
  821.         expect_int_insn = 0;
  822.     }
  823.     /* Check the insn format and fold in the dual mode bit if appropriate. */
  824.     if ( dual_insn_mode || this_insn_is_dual )
  825.     {
  826.         if ( (opcode & OP_PREFIX_MASK) == PREFIX_FPU || opcode == OP_FNOP )
  827.         {
  828.                 if ( insn_count & 1 )    /* Odd insn, not on 64 bit bound! */
  829.             {
  830.             as_warn( "Dual FP insn on odd addr." );
  831.             }
  832.             opcode |= DUAL_INSN_MODE_BIT;
  833.             expect_int_insn = 1;
  834.         }
  835.         else if ( this_insn_is_dual ) /* d. prefix on a non-FPU insn error */
  836.         {
  837.             as_warn("d. prefix not allowed for `%s'. (Ignored!)", op);
  838.         } 
  839.     }
  840.     else
  841.             expect_int_insn = 0;    /* Single insn mode. */
  842.     /* Check for correct alignment of const in branch to label + offset */
  843.     if (    (the_insn.reloc == I860_RELOC_BRADDR
  844.              || (the_insn.pcrel && the_insn.reloc == I860_RELOC_SPLIT0)
  845.         ) && (the_insn.exp.X_add_number & 3) )
  846.             as_warn( "Branch offset is not aligned to instruction boundry!" );
  847.     the_insn.opcode = opcode;
  848.     return flags;
  849. }
  850.  
  851. static
  852. int
  853. getExpression(
  854. char *str)
  855. {
  856.     char *save_in;
  857.     segT seg;
  858.  
  859.     save_in = input_line_pointer;
  860.     input_line_pointer = str;
  861.     switch (seg = expression(&the_insn.exp)) {
  862.  
  863.     case SEG_ABSOLUTE:
  864.     case SEG_SECT:
  865.     case SEG_DIFFSECT:
  866.     case SEG_UNKNOWN:
  867.     case SEG_BIG:
  868.     case SEG_NONE:
  869.     break;
  870.  
  871.     default:
  872.     the_insn.error = "bad segment";
  873.     expr_end = input_line_pointer;
  874.     input_line_pointer=save_in;
  875.     return 1;
  876.     }
  877.     expr_end = input_line_pointer;
  878.     input_line_pointer = save_in;
  879.     return 0;
  880. }
  881.  
  882.  
  883. #define MAX_LITTLENUMS 6
  884.  
  885. /*
  886.     This is identical to the md_atof in m68k.c.  I think this is right,
  887.     but I'm not sure.
  888.  
  889.    Turn a string in input_line_pointer into a floating point constant of type
  890.    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
  891.    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
  892.  */
  893. char *
  894. md_atof(
  895. int type,
  896. char *litP,
  897. int *sizeP)
  898. {
  899.     int    prec;
  900.     LITTLENUM_TYPE words[MAX_LITTLENUMS];
  901.     LITTLENUM_TYPE *wordP;
  902.     char    *t;
  903.     char    *atof_ieee();
  904.  
  905.     switch(type) {
  906.  
  907.     case 'f':
  908.     case 'F':
  909.     case 's':
  910.     case 'S':
  911.     prec = 2;
  912.     break;
  913.  
  914.     case 'd':
  915.     case 'D':
  916.     case 'r':
  917.     case 'R':
  918.     prec = 4;
  919.     break;
  920.     /* The following two formats get reduced to doubles. */
  921.     case 'x':
  922.     case 'X':
  923.         type = 'd';
  924.     prec = 4;
  925.     break;
  926.  
  927.     case 'p':
  928.     case 'P':
  929.         type = 'd';
  930.     prec = 4;
  931.     break;
  932.  
  933.     default:
  934.     *sizeP=0;
  935.     return "Bad call to MD_ATOF()";
  936.     }
  937.     t=atof_ieee(input_line_pointer,type,words);
  938.     if(t)
  939.     input_line_pointer=t;
  940.     *sizeP=prec * sizeof(LITTLENUM_TYPE);
  941.     for(wordP=words;prec--;) {
  942.     md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
  943.     litP+=sizeof(LITTLENUM_TYPE);
  944.     }
  945.     return "";    /* Someone should teach Dean about null pointers */
  946. }
  947.  
  948. /*
  949.  * Write out big-endian.  Valid for data only in our I860 implementation.
  950.  */
  951. void
  952. md_number_to_chars(
  953. char *buf,
  954. long val,
  955. int n)
  956. {
  957.  
  958.     switch(n) {
  959.  
  960.     case 4:
  961.     *buf++ = val >> 24;
  962.     *buf++ = val >> 16;
  963.     case 2:
  964.     *buf++ = val >> 8;
  965.     case 1:
  966.     *buf = val;
  967.     break;
  968.  
  969.     default:
  970.     abort();
  971.     }
  972.     return;
  973. }
  974.  
  975. #ifdef BYTE_SWAP
  976. /*
  977.  * Write out little-endian.  Valid for instructions only in
  978.  * our i860 implementation.
  979.  */
  980. static
  981. void
  982. md_insn_to_chars(
  983. unsigned char *buf,
  984. long val,
  985. int n)
  986. {
  987.  
  988.     switch(n) {
  989.  
  990.     case 4:
  991.     *buf++ = val;
  992.     *buf++ = val >> 8;
  993.     *buf++ = val >> 16;
  994.     *buf++ = val >> 24;
  995.     break;
  996.     case 2:
  997.     *buf++ = val;
  998.     *buf++ = val >> 8;
  999.     break;
  1000.     case 1:
  1001.     *buf = val;
  1002.     break;
  1003.  
  1004.     default:
  1005.     abort();
  1006.     }
  1007.     return;
  1008. }
  1009. #else /* !defined(BYTE_SWAP) */
  1010.  
  1011. static
  1012. void
  1013. md_insn_to_chars(
  1014. unsigned char *buf,
  1015. long val,
  1016. int n)
  1017. {
  1018.     md_number_to_chars(buf,val,n);
  1019. }
  1020. #endif /* BYTE_SWAP */
  1021.  
  1022. void
  1023. md_number_to_imm(
  1024. unsigned char *buf,
  1025. long val,
  1026. int n,
  1027. fixS *fixP,
  1028. int nsect)
  1029. {
  1030.     unsigned long opcode;
  1031.  
  1032.     if ( nsect == text_nsect && (n % 4) != 0 )
  1033.         as_warn("Immediate write of non-aligned data into text segment." );
  1034.     
  1035.     if (nsect != text_nsect ||
  1036.     fixP->fx_r_type == NO_RELOC ||
  1037.     fixP->fx_r_type == I860_RELOC_VANILLA)
  1038.     {
  1039.     switch (n) {    /* Write out the data big-endian style. */
  1040.     case 1:
  1041.         *buf = val;
  1042.         break;
  1043.     case 2:
  1044.         *buf++ = (val>>8);
  1045.         *buf = val;
  1046.         break;
  1047.     case 4:
  1048.         *buf++ = (val>>24);
  1049.         *buf++ = (val>>16);
  1050.         *buf++ = (val>>8);
  1051.         *buf = val;
  1052.         break;
  1053.     default:
  1054.         abort();
  1055.     }
  1056.     return;
  1057.     }
  1058.  
  1059.     assert(n == 4);    /* Better be an instruction with relocation data.... */
  1060.     assert(fixP->fx_r_type < NO_RELOC && fixP->fx_r_type > I860_RELOC_VANILLA);
  1061.     /*
  1062.      * Here is where we do initial bit fiddling to load immediate 
  1063.      * values into the i860 bit fields.
  1064.      */
  1065. #ifdef BYTE_SWAP     
  1066.     /* Note that all of these insns are ultimately little-endian */
  1067.     /* Get the opcode from the buffer.  Less efficient, but more coherent... */
  1068.     opcode = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
  1069. #else
  1070.     opcode = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
  1071. #endif  
  1072.     /* Apply the relocation value 'val' */
  1073.     switch (fixP->fx_r_type) { 
  1074.         case I860_RELOC_PAIR:
  1075.         as_warn("questionable relocation type I860_RELOC_PAIR");
  1076.         break;
  1077.         case I860_RELOC_HIGH:
  1078.         opcode &= ~0xFFFF;
  1079.         opcode |= ((val >> 16) & 0xFFFF);
  1080.         break;
  1081.         case I860_RELOC_LOW0:
  1082.         opcode &= ~0xFFFF;
  1083.         opcode |= (val & 0xFFFF);
  1084.         break;
  1085.         case I860_RELOC_LOW1:
  1086.         opcode &= 0xFFFF0001;
  1087.         opcode |= (val & 0xFFFE);    /* Bit 0 is an insn bit! */
  1088.         break;
  1089.         case I860_RELOC_LOW2:
  1090.         opcode &= 0xFFFF0003;
  1091.         opcode |= (val & 0xFFFC);    /* Bits 0 and 1 are insn bits! */
  1092.         break;
  1093.         case I860_RELOC_LOW3:
  1094.         opcode &= 0xFFFF0007;
  1095.         opcode |= (val & 0xFFF8);    /* Bits 0 thru 2 are insn bits! */
  1096.         break;
  1097.         case I860_RELOC_LOW4:
  1098.         opcode &= 0xFFFF000F;
  1099.         opcode |= (val & 0xFFF0);    /* Bits 0 thru 3 are insn bits! */
  1100.         break;
  1101.         case I860_RELOC_SPLIT0:
  1102.         opcode &= 0xFFE0F800;
  1103.         if ( fixP->fx_pcrel )         /* A 16 bit branch relative insn? */
  1104.             val >>= 2;        /* Convert to word address */
  1105.         opcode |= ((val & 0xF800) << 5) | (val & 0x7FF);
  1106.         break;
  1107.         case I860_RELOC_SPLIT1:
  1108.         opcode &= 0xFFE0F801;        /* Again, bit 0 is an insn bit! */
  1109.         opcode |= ((val & 0xF800) << 5) | (val & 0x7FE);
  1110.         break;
  1111.         case I860_RELOC_SPLIT2:
  1112.         opcode &= 0xFFE0F803;        /* Bits 0 and 1 are insn bits! */
  1113.         opcode |= ((val & 0xF800) << 5) | (val & 0x7FC);
  1114.         break;
  1115.         case I860_RELOC_HIGHADJ:            /* Adjusted variant */
  1116.         opcode &= ~0xFFFF;
  1117.         /* If the low half would be negative, compensate by adding 1 to 
  1118.          * high half.
  1119.          */
  1120.         if ( (val & 0x8000) != 0 )
  1121.             val = (val >> 16) + 1;
  1122.         else
  1123.             val = (val >> 16);
  1124.         opcode |= (val & 0xFFFF);
  1125.         break;
  1126.         case I860_RELOC_BRADDR:
  1127.         if ( fixP->fx_pcrel )         /* A 26 bit branch relative insn? */
  1128.             val >>= 2;        /* Convert to word address */
  1129.         opcode &= 0xFC000000;
  1130.         opcode |= (val & 0x03FFFFFF);
  1131.         break;
  1132.     
  1133.     default:
  1134.         as_warn("bad relocation type: 0x%02x", fixP->fx_r_type);
  1135.         break;
  1136.     }
  1137. #ifdef BYTE_SWAP
  1138.     buf[0] = opcode;
  1139.     buf[1] = opcode >> 8;
  1140.     buf[2] = opcode >> 16;
  1141.     buf[3] = opcode >> 24;
  1142. #else
  1143.     buf[3] = opcode;
  1144.     buf[2] = opcode >> 8;
  1145.     buf[1] = opcode >> 16;
  1146.     buf[0] = opcode >> 24;
  1147. #endif
  1148.     return;
  1149. }
  1150.  
  1151. /* should never be called for i860 */
  1152. void
  1153. md_convert_frag(
  1154. fragS *fragP)
  1155. {
  1156.     fprintf(stderr, "i860_convert_frag\n");
  1157.     abort();
  1158. }
  1159.  
  1160. /* should never be called for i860 */
  1161. int
  1162. md_estimate_size_before_relax(
  1163. fragS *fragP,
  1164. int nsect)
  1165. {
  1166.     fprintf(stderr, "i860_estimate_size_before_relax\n");
  1167.     abort();
  1168.     return 0;
  1169. }
  1170.  
  1171. #ifdef I860_DEBUG
  1172. /* for debugging only */
  1173. static void
  1174. print_insn(
  1175. struct i860_it *insn)
  1176. {
  1177.     char *Reloc[] = {
  1178.     "RELOC_8",
  1179.     "RELOC_16",
  1180.     "RELOC_32",
  1181.     "RELOC_DISP8",
  1182.     "RELOC_DISP16",
  1183.     "RELOC_DISP32",
  1184.     "RELOC_WDISP30",
  1185.     "RELOC_WDISP22",
  1186.     "RELOC_HI22",
  1187.     "RELOC_22",
  1188.     "RELOC_13",
  1189.     "RELOC_LO10",
  1190.     "RELOC_SFA_BASE",
  1191.     "RELOC_SFA_OFF13",
  1192.     "RELOC_BASE10",
  1193.     "RELOC_BASE13",
  1194.     "RELOC_BASE22",
  1195.     "RELOC_PC10",
  1196.     "RELOC_PC22",
  1197.     "RELOC_JMP_TBL",
  1198.     "RELOC_SEGOFF16",
  1199.     "RELOC_GLOB_DAT",
  1200.     "RELOC_JMP_SLOT",
  1201.     "RELOC_RELATIVE",
  1202.     "NO_RELOC"
  1203.     };
  1204.  
  1205.     if (insn->error) {
  1206.     fprintf(stderr, "ERROR: %s\n");
  1207.     }
  1208.     fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
  1209.     fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
  1210.     fprintf(stderr, "exp =  {\n");
  1211.     fprintf(stderr, "\t\tX_add_symbol = %s\n",
  1212.     insn->exp.X_add_symbol ?
  1213.     (insn->exp.X_add_symbol->sy_name ? 
  1214.     insn->exp.X_add_symbol->sy_name : "???") : "0");
  1215.     fprintf(stderr, "\t\tX_sub_symbol = %s\n",
  1216.     insn->exp.X_subtract_symbol ?
  1217.         (insn->exp.X_subtract_symbol->sy_name ? 
  1218.             insn->exp.X_subtract_symbol->sy_name : "???") : "0");
  1219.     fprintf(stderr, "\t\tX_add_number = %d\n",
  1220.     insn->exp.X_add_number);
  1221.     fprintf(stderr, "}\n");
  1222.     return;
  1223. }
  1224. #endif /* I860_DEBUG */
  1225.  
  1226. int
  1227. md_parse_option(
  1228. char **argP,
  1229. int *cntP,
  1230. char ***vecP)
  1231. {
  1232.     return 1;
  1233. }
  1234.  
  1235.