home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.2 (Developer) / NS_dev_3.2.iso / NextDeveloper / Source / GNU / cctools / as / m88k.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-07  |  34.4 KB  |  1,750 lines

  1. /* m88k.c -- Assemble for the 88100
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is not yet 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. #include <ctype.h>
  21. #include "m88k-opcode.h"
  22. #include "as.h"
  23. #include "frags.h"
  24. #include "struc-symbol.h"
  25. #include "flonum.h"
  26. #include "expr.h"
  27. #include "hash.h"
  28. #include "md.h"
  29. #include "m88k.h"
  30. #include "write.h"
  31. #include "read.h"
  32. #include "obstack.h"
  33. /*
  34. #include "struc-symbol.h"
  35. */
  36. #include "symbols.h"
  37.  
  38. static int calcop();
  39. static char *parse_reg();
  40. #ifdef m88110
  41. static char *parse_ereg();
  42. static char *parse_e4rot();
  43. static char *parse_xreg();
  44. #endif m88110
  45. static char *parse_pcr();
  46. static char *parse_cnd();
  47. static char *parse_bf();
  48. static char *parse_rot();
  49. static char *parse_cmp();
  50. static char *parse_cst();
  51. static char *parse_rsc();
  52. static char *parse_cr();
  53. static char *parse_fcr();
  54. static char *getval();
  55.  
  56. #ifdef NeXT
  57. static long in_delay_slot = 0;
  58. #endif NeXT
  59.  
  60. static char *cmpslot[] = { "**", "**", "eq", "ne", "gt", "le", "lt", "ge",
  61.                "hi", "ls", "lo", "hs",
  62. #ifdef m88110
  63.                "be", "nb", "he", "nh",
  64. #endif m88110
  65.                 NULL };
  66.  
  67. static struct {
  68.     char *name;
  69.     unsigned int num;
  70.  
  71. } cndmsk[] = {
  72.         "eq0", 0x02,
  73.         "ne0", 0x0d,
  74.         "gt0", 0x01,
  75.         "lt0", 0x0c,
  76.         "ge0", 0x03,
  77.         "le0", 0x0e,
  78.         NULL,  0x00,
  79.           };
  80.  
  81. struct m88k_insn {
  82.         unsigned long opcode;
  83.         expressionS exp;
  84. #ifdef NeXT
  85.         enum reloc_type_m88k reloc;
  86. #else
  87.         enum reloc_type reloc;
  88. #endif
  89. };
  90.  
  91. extern char *myname;
  92. static struct hash_control *op_hash = NULL;
  93.  
  94. /* This is the number to put at the beginning of the a.out file */
  95. long omagic = OMAGIC;
  96.  
  97. /* These chars start a comment anywhere in a source file (except inside
  98.    another comment */
  99. char comment_chars[] = ";";
  100.  
  101. /* These chars only start a comment at the beginning of a line. */
  102. char line_comment_chars[] = "#";
  103.  
  104. /* Chars that can be used to separate mant from exp in floating point nums */
  105. char EXP_CHARS[] = "eE";
  106.  
  107. /* Chars that mean this number is a floating point constant */
  108. /* as in 0f123.456 */
  109. /* or    0H1.234E-12 (see exp chars above) */
  110. char FLT_CHARS[] = "dDfF";
  111.  
  112. extern void float_cons (), cons (), s_globl (), s_line (), s_space ();
  113.  
  114. #ifdef NeXT
  115. static void s_reg();
  116. static void s_scaled();
  117. static void s_m88k_abs();
  118. static void s_no_delay();
  119. static void s_dot();
  120. extern void totally_ignore_line();
  121. #endif NeXT
  122.  
  123. const pseudo_typeS md_pseudo_table[] =
  124. {
  125. #ifdef NeXT
  126.     {"greg", s_reg, 'r' },
  127.     {"xreg", s_reg, 'x' },
  128.     {"scaled", s_scaled, 0},
  129.     {"abs", s_m88k_abs, 0},
  130.     {"no_delay", s_no_delay, 0},
  131.     {"dot", s_dot, 0},
  132. #endif NeXT
  133. #ifndef NeXT
  134.       /* At NeXT we don't allow these */
  135.     {"dfloat", float_cons, 'd'},
  136.     {"ffloat", float_cons, 'f'},
  137.     {"global", s_globl, 0},
  138.     {"half", cons, 2 },
  139.     {"ln", s_line, 0},
  140.     {"zero", s_space, 0},
  141.       /* At NeXT we allow .word only on the 68k machines, and the i860 where
  142.        we don't ship the assembler */
  143.     {"word", cons, 4 },
  144. #endif
  145.     {0}
  146. };
  147.  
  148. #ifdef NeXT
  149. static
  150. void
  151. s_dot(void)
  152. {
  153.     char *name, *end_name, delim;
  154.     symbolS *symbolP;
  155.     unsigned long n_value, val;
  156.  
  157.     if( * input_line_pointer == '"')
  158.       name = input_line_pointer + 1;
  159.     else
  160.       name = input_line_pointer;
  161.     delim = get_symbol_end();
  162.     end_name = input_line_pointer;
  163.     *end_name = 0;
  164.  
  165.     symbolP = symbol_find_or_make (name);
  166.     symbolP -> sy_type = N_ABS;
  167. #ifdef Mach_O
  168.     symbolP -> sy_other = 0; /* NO_SECT */
  169. #endif Mach_O
  170.     symbolP -> sy_value = obstack_next_free(&frags) - frag_now->fr_literal;
  171.     symbolP -> sy_frag = &zero_address_frag;
  172.  
  173.     *end_name = delim;
  174.     totally_ignore_line();
  175. }
  176. /*
  177.  * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
  178.  * which set symbol to 1 or 0 depending on if the expression is a general
  179.  * register or extended register respectfully.  These are intended for use in
  180.  * macros.
  181.  */
  182. static
  183. void
  184. s_reg(reg)
  185. char reg;
  186. {
  187.     char *name, *end_name, delim;
  188.     symbolS *symbolP;
  189.     unsigned long n_value, val;
  190.  
  191.     if( * input_line_pointer == '"')
  192.       name = input_line_pointer + 1;
  193.     else
  194.       name = input_line_pointer;
  195.     delim = get_symbol_end();
  196.     end_name = input_line_pointer;
  197.     *end_name = delim;
  198.     SKIP_WHITESPACE();
  199.     if ( * input_line_pointer != ',' ) {
  200.         *end_name = 0;
  201.         as_warn("Expected comma after name \"%s\"", name);
  202.         *end_name = delim;
  203.         ignore_rest_of_line();
  204.         return;
  205.     }
  206.     input_line_pointer ++;
  207.     *end_name = 0;
  208.  
  209.     SKIP_WHITESPACE();
  210.     n_value = 0;
  211.     if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
  212.         input_line_pointer++;
  213.         if(isdigit(*input_line_pointer)){
  214.         val = 0;
  215.         while (isdigit(*input_line_pointer)){
  216.             if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
  217.             break;
  218.         }
  219.         SKIP_WHITESPACE();
  220.         if(val <= 31 &&
  221.            (*input_line_pointer == '\n' || *input_line_pointer == '@'))
  222.             n_value = 1;
  223.         }
  224.     }
  225.  
  226.     symbolP = symbol_find_or_make (name);
  227.     symbolP -> sy_type = N_ABS;
  228. #ifdef Mach_O
  229.     symbolP -> sy_other = 0; /* NO_SECT */
  230. #endif Mach_O
  231.     symbolP -> sy_value = n_value;
  232.     symbolP -> sy_frag = & zero_address_frag;
  233.  
  234.     *end_name = delim;
  235.     totally_ignore_line();
  236. }
  237.  
  238. /*
  239.  * s_scaled() is used to implement ".scaled symbol,exp" which sets symbol to 1
  240.  * or 0 depending on if the expression is a scaled general register expression
  241.  * "r1[r2]" or not respectfully.  This is intended for use in macros.
  242.  */
  243. static
  244. void
  245. s_scaled()
  246. {
  247.     char *name, *end_name, delim;
  248.     symbolS *symbolP;
  249.     unsigned long n_value, val;
  250.  
  251.     if( * input_line_pointer == '"')
  252.       name = input_line_pointer + 1;
  253.     else
  254.       name = input_line_pointer;
  255.     delim = get_symbol_end();
  256.     end_name = input_line_pointer;
  257.     *end_name = delim;
  258.     SKIP_WHITESPACE();
  259.     if ( * input_line_pointer != ',' ) {
  260.         *end_name = 0;
  261.         as_warn("Expected comma after name \"%s\"", name);
  262.         *end_name = delim;
  263.         ignore_rest_of_line();
  264.         return;
  265.     }
  266.     input_line_pointer ++;
  267.     *end_name = 0;
  268.  
  269.     SKIP_WHITESPACE();
  270.     n_value = 0;
  271.     if (*input_line_pointer == 'r' || *input_line_pointer == 'R'){
  272.         input_line_pointer++;
  273.         if(isdigit(*input_line_pointer)){
  274.         val = 0;
  275.         while (isdigit(*input_line_pointer)){
  276.             if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
  277.             break;
  278.         }
  279.         SKIP_WHITESPACE();
  280.         if(val <= 31 && *input_line_pointer == '['){
  281.             input_line_pointer++;
  282.             if (*input_line_pointer == 'r' ||
  283.             *input_line_pointer == 'R'){
  284.             input_line_pointer++;
  285.             if(isdigit(*input_line_pointer)){
  286.                 val = 0;
  287.                 while (isdigit(*input_line_pointer)){
  288.                 if ((val = val * 10 +
  289.                        *input_line_pointer++ - '0') > 31)
  290.                     break;
  291.                 }
  292.                 if(val <= 31 && *input_line_pointer == ']'){
  293.                 input_line_pointer++;
  294.                 SKIP_WHITESPACE();
  295.                 if(*input_line_pointer == '\n' ||
  296.                    *input_line_pointer == '@')
  297.                         n_value = 1;
  298.                 }
  299.             }
  300.             }
  301.         }
  302.         }
  303.     }
  304.  
  305.     symbolP = symbol_find_or_make (name);
  306.     symbolP -> sy_type = N_ABS;
  307. #ifdef Mach_O
  308.     symbolP -> sy_other = 0; /* NO_SECT */
  309. #endif Mach_O
  310.     symbolP -> sy_value = n_value;
  311.     symbolP -> sy_frag = & zero_address_frag;
  312.  
  313.     *end_name = delim;
  314.     totally_ignore_line();
  315. }
  316.  
  317. /*
  318.  * s_m88k_abs() is used to implement ".abs symbol,exp" which sets symbol to 1
  319.  * or 0 depending on if the expression is an absolute expression or not
  320.  * respectfully.  This is intended for use in macros.
  321.  */
  322. static
  323. void
  324. s_m88k_abs()
  325. {
  326.     char *name, *end_name, delim, *start;
  327.     symbolS *symbolP;
  328.     unsigned long n_value, val, is_reg_exp;
  329.  
  330.     start = input_line_pointer;
  331.     if( * input_line_pointer == '"')
  332.       name = input_line_pointer + 1;
  333.     else
  334.       name = input_line_pointer;
  335.     delim = get_symbol_end();
  336.     end_name = input_line_pointer;
  337.     *end_name = delim;
  338.     SKIP_WHITESPACE();
  339.     if ( * input_line_pointer != ',' ) {
  340.         *end_name = 0;
  341.         as_warn("Expected comma after name \"%s\"", name);
  342.         *end_name = delim;
  343.         ignore_rest_of_line();
  344.         return;
  345.     }
  346.     input_line_pointer ++;
  347.     *end_name = 0;
  348.  
  349.     SKIP_WHITESPACE();
  350.     is_reg_exp = 0;
  351.     n_value = 0;
  352.     if(*input_line_pointer == 'r' || *input_line_pointer == 'R'){
  353.         input_line_pointer++;
  354.         if(isdigit(*input_line_pointer)){
  355.         val = 0;
  356.         while (isdigit(*input_line_pointer)){
  357.             if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
  358.             break;
  359.         }
  360.         SKIP_WHITESPACE();
  361.         if(val <= 31)
  362.             is_reg_exp = 1;
  363.         }
  364.     }
  365.     if(is_reg_exp == 0){
  366.         *end_name = delim;
  367.         input_line_pointer = start;
  368.         s_abs();
  369.         return;
  370.     }
  371.  
  372.     symbolP = symbol_find_or_make (name);
  373.     symbolP -> sy_type = N_ABS;
  374. #ifdef Mach_O
  375.     symbolP -> sy_other = 0; /* NO_SECT */
  376. #endif Mach_O
  377.     symbolP -> sy_value = n_value;
  378.     symbolP -> sy_frag = & zero_address_frag;
  379.     *end_name = delim;
  380.  
  381.     totally_ignore_line();
  382. }
  383.  
  384. /*
  385.  * s_no_delay() is used to implement ".no_delay string" which will abort and
  386.  * print the string if the last instruction assembled has a delay slot.
  387.  * This is intended for use in macros that expand to more than one instruction
  388.  * that could be put in delay slots.  This is not really correct in it's
  389.  * operation in that it is not per-section and does not take into account
  390.  * anything other than assembled instructions.
  391.  */
  392. static
  393. void
  394. s_no_delay()
  395. {
  396.     char *p, c;
  397.  
  398.     p = input_line_pointer;
  399.     while(*p != '\n' && *p != '@' && *p != '\0')
  400.         p++;
  401.     c = *p;
  402.     *p = '\0';
  403.     
  404.     if(in_delay_slot)
  405.         as_fatal("delay slot abort %s detected.  Assembly stopping.",
  406.              input_line_pointer);
  407.     input_line_pointer = p;
  408.     *p = c;
  409. }
  410. #endif NeXT
  411.  
  412. void
  413. md_begin()
  414. {
  415.     register char *retval = NULL;
  416.     register unsigned int i = 0;
  417.  
  418.     /* initialize hash table */
  419.  
  420.     op_hash = hash_new();
  421.     if (op_hash == NULL)
  422.         as_fatal("Could not initialize hash table");
  423.  
  424.     /* loop until you see the end of the list */
  425.  
  426.     while (*m88k_opcodes[i].name) {
  427.         char *name = m88k_opcodes[i].name;
  428.  
  429.         /* hash each mnemonic and record its position */
  430.  
  431.         retval = hash_insert(op_hash, name, &m88k_opcodes[i]);
  432.  
  433.         if (retval != NULL && *retval != '\0')
  434.             as_fatal("Can't hash instruction '%s':%s",
  435.                     m88k_opcodes[i].name, retval);
  436.  
  437.         /* skip to next unique mnemonic or end of list */
  438.  
  439.         for (i++; !strcmp(m88k_opcodes[i].name, name); i++);
  440.     }
  441. }
  442.  
  443. int
  444. md_parse_option (argP, cntP, vecP)
  445. char **argP;
  446. int *cntP;
  447. char ***vecP;
  448. {
  449.     return (1);
  450. }
  451.  
  452. void
  453. md_assemble(op)
  454. char *op;
  455. {
  456.     char *param, *thisfrag;
  457.     struct m88k_opcode *format;
  458.     struct m88k_insn insn;
  459. #ifdef NeXT
  460.     long pcrel;
  461. #endif NeXT
  462.  
  463.     assert(op);
  464.  
  465.     /* skip over instruction to find parameters */
  466.  
  467.     /* *param != '\0' is need for instructions that have no parameters
  468.        like rte */
  469.     for (param = op; !isspace(*param) && *param != '\0' ; param++);
  470.     *param++ = '\0';
  471.  
  472.     /* try to find the instruction in the hash table */
  473.  
  474.     if ((format = (struct m88k_opcode *) hash_find(op_hash, op)) == NULL) {
  475.         as_warn("Invalid mnemonic '%s'", op);
  476.         return;
  477.     }
  478.  
  479.     /* try parsing this instruction into insn */
  480.  
  481.     while (!calcop(format,param,&insn))
  482.  
  483.         /* if it doesn't parse try the next instruction */
  484.  
  485.         if (!strcmp(format->name, format[1].name))
  486.             format++;
  487.         else {
  488.             as_warn("Parameter syntax error");
  489.             return;
  490.         }
  491.  
  492.     /* grow the current frag and plop in the opcode */
  493.  
  494.     thisfrag = frag_more(4);
  495.     md_number_to_chars(thisfrag, insn.opcode, 4);
  496. #ifdef NeXT
  497.     in_delay_slot = format->delay_slot;
  498. #endif NeXT
  499. #ifdef NeXT    /* generate stabs for debugging assembly code */
  500.     /*
  501.      * If the -g flag is present generate a line number stab for the
  502.      * instruction.
  503.      * 
  504.      * See the detailed comments about stabs in read_a_source_file() for a
  505.      * description of what is going on here.
  506.      */
  507.     if (flagseen['g'] && now_seg == SEG_TEXT && now_subseg == 0){
  508.       struct symbol *symbolP, *symbol_new();
  509.       extern unsigned int logical_input_line;
  510.  
  511.         symbolP = symbol_new(
  512.             "",
  513.             68 /* N_SLINE */,
  514.             seg_n_sect(now_seg, now_subseg),
  515.             logical_input_line /* n_desc, line number */,
  516.             obstack_next_free(&frags) - frag_now->fr_literal,
  517.             frag_now);
  518.     }
  519. #endif NeXT    /* generate stabs for debugging assembly code */
  520.  
  521. #ifdef NeXT
  522.     pcrel = 0;
  523.     if (insn.reloc == RELOC_PC16 || insn.reloc == RELOC_PC26){
  524.         /*
  525.          * The NeXT linker has the ability to scatter blocks of
  526.          * sections between labels.  This requires that brances to
  527.          * labels that survive to the link phase must be able to
  528.          * be relocated.
  529.          */
  530.         if(insn.exp.X_add_symbol != NULL &&
  531.            (insn.exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
  532.         pcrel = 1 + 2;
  533.         else
  534.         pcrel = 1;
  535.     }
  536. #endif NeXT
  537.  
  538.     /* if this instruction requires labels mark it for later */
  539.     switch (insn.reloc) {
  540.  
  541.         case NO_RELOC:
  542.                 break;
  543.  
  544.         case RELOC_LO16:
  545.         case RELOC_HI16:
  546.                 fix_new(
  547.                     frag_now,
  548. #ifdef NeXT
  549.                     thisfrag - frag_now->fr_literal,
  550.                     4,
  551. #else !defined(NeXT)
  552.                     thisfrag - frag_now->fr_literal + 2,
  553.                     2,
  554. #endif NeXT
  555.                     insn.exp.X_add_symbol,
  556.                     insn.exp.X_subtract_symbol,
  557.                     insn.exp.X_add_number,
  558.                     0,
  559.                     insn.reloc
  560.                 );
  561.                 break;
  562.  
  563. #ifndef NeXT
  564.         case RELOC_IW16:
  565.                 fix_new(
  566.                     frag_now,
  567.                     thisfrag - frag_now->fr_literal,
  568.                     4,
  569.                     insn.exp.X_add_symbol,
  570.                     insn.exp.X_subtract_symbol,
  571.                     insn.exp.X_add_number,
  572.                     0,
  573.                     insn.reloc
  574.                 );
  575.                 break;
  576. #endif !defined(NeXT)
  577.  
  578.         case RELOC_PC16:
  579.                 fix_new(
  580.                     frag_now,
  581. #ifdef NeXT
  582.                     thisfrag - frag_now->fr_literal,
  583.                     4,
  584. #else !defined(NeXT)
  585.                     thisfrag - frag_now->fr_literal + 2,
  586.                     2,
  587. #endif NeXT
  588.                     insn.exp.X_add_symbol,
  589.                     insn.exp.X_subtract_symbol,
  590.                     insn.exp.X_add_number,
  591. #ifdef NeXT
  592.                     pcrel,
  593. #else !defined(NeXT)
  594.                     1,
  595. #endif NeXT
  596.                     insn.reloc
  597.                 );
  598.                 break;
  599.  
  600.         case RELOC_PC26:
  601.                 fix_new(
  602.                     frag_now,
  603.                     thisfrag - frag_now->fr_literal,
  604.                     4,
  605.                     insn.exp.X_add_symbol,
  606.                     insn.exp.X_subtract_symbol,
  607.                     insn.exp.X_add_number,
  608. #ifdef NeXT
  609.                     pcrel,
  610. #else !defined(NeXT)
  611.                     1,
  612. #endif NeXT
  613.                     insn.reloc
  614.                 );
  615.                 break;
  616.  
  617.         default:
  618.                 as_warn("Unknown relocation type");
  619.                 break;
  620.     }
  621. }
  622.  
  623. static
  624. int
  625. calcop(format,param,insn)
  626. struct m88k_opcode *format;
  627. char *param;
  628. struct m88k_insn *insn;
  629. {
  630.     int parcnt;
  631.  
  632.     /* initial the passed structure */
  633.  
  634.     bzero(insn, sizeof(*insn));
  635.     insn->reloc = NO_RELOC;
  636.     insn->opcode = format->opcode;
  637.  
  638.     /* parse all parameters */
  639.  
  640.     for (parcnt=0; parcnt<3 && format->op[parcnt].type != NIL; parcnt++) {
  641.  
  642.         switch (format->op[parcnt].type) {
  643.  
  644.             case CNST:
  645.                 param = parse_cst(param, insn, format, parcnt);
  646.                 break;
  647.  
  648.             case REG:
  649.                 param = parse_reg(param, insn, format, parcnt);
  650.                 break;
  651. #ifdef m88110
  652.             case EREG:
  653.                 param = parse_ereg(param, insn, format, parcnt);
  654.                 break;
  655.  
  656.             case E4ROT:
  657.                 param = parse_e4rot(param, insn, format,parcnt);
  658.                 break;
  659.  
  660.             case XREG:
  661.                 param = parse_xreg(param, insn, format, parcnt);
  662.                 break;
  663. #endif m88110
  664.             case BF:
  665.                 param = parse_bf(param, insn, format, parcnt);
  666.                 break;
  667.  
  668.             case ROT:
  669.                 param = parse_rot(param, insn, format, parcnt);
  670.                 break;
  671.  
  672.             case REGSC:
  673.                 param = parse_rsc(param, insn, format, parcnt);
  674.                 break;
  675.  
  676.             case CRREG:
  677.                 param = parse_cr(param, insn, format, parcnt);
  678.                 break;
  679.  
  680.             case FCRREG:
  681.                 param = parse_fcr(param, insn, format, parcnt);
  682.                 break;
  683.  
  684.             case PCREL:
  685.                 param = parse_pcr(param, insn, format, parcnt);
  686.                 break;
  687.  
  688.             case CONDMASK:
  689.                 param = parse_cnd(param, insn, format, parcnt);
  690.                 break;
  691.  
  692.             case CMPRSLT:
  693.                 param = parse_cmp(param, insn, format, parcnt);
  694.                 break;
  695.  
  696.             default:
  697.                 as_fatal("Unknown parameter type");
  698.         }
  699.  
  700.         /* see if parser failed or not */
  701.  
  702.         if (param == NULL)
  703.             return 0;
  704.     }
  705.  
  706.     return 1;
  707. }
  708.  
  709. static
  710. char *
  711. parse_pcr(param, insn, format, parcnt)
  712. char *param;
  713. struct m88k_insn *insn;
  714. struct m88k_opcode *format;
  715. int parcnt;
  716. {
  717.     char *saveptr, *saveparam;
  718.     segT seg;
  719.  
  720.     saveptr = input_line_pointer;
  721.     input_line_pointer = param;
  722.  
  723.     seg = expression(&insn->exp);
  724.  
  725.     saveparam = input_line_pointer;
  726.     input_line_pointer = saveptr;
  727.  
  728.     switch (format->op[parcnt].width) {
  729.  
  730.         case 16: insn->reloc = RELOC_PC16;
  731.              break;
  732.  
  733.         case 26: insn->reloc = RELOC_PC26;
  734.              break;
  735.  
  736.         default: as_warn("Strange PC relative width %d",
  737.                         format->op[parcnt].width);
  738.              break;
  739.     }
  740.  
  741.     return saveparam;
  742. }
  743.  
  744. static
  745. char *
  746. parse_reg(param, insn, format, parcnt)
  747. char *param;
  748. struct m88k_insn *insn;
  749. struct m88k_opcode *format;
  750. int parcnt;
  751. {
  752.     unsigned int val = 0;
  753.  
  754.     if (*param != 'r' && *param != 'R')
  755.         return NULL;
  756.  
  757.     param++;
  758.  
  759.     if (!isdigit(*param))
  760.         return NULL;
  761.  
  762.     while (isdigit(*param))
  763.         if ((val = val * 10 + *param++ - '0') > 31)
  764.             return NULL;
  765.  
  766.     insn->opcode |= val << format->op[parcnt].offset;
  767.  
  768.     switch (*param) {
  769.  
  770.         case '\0' :
  771.             if (parcnt == 2 || format->op[parcnt+1].type == NIL)
  772.                 return param;
  773.             else
  774.                 return NULL;
  775.  
  776.         case '['  :
  777.             if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
  778.                 return param+1;
  779.             else
  780.                 return NULL;
  781.  
  782.         case ','  :
  783.             if (parcnt != 2 && format->op[parcnt+1].type != NIL)
  784.                 return param+1;
  785.             else
  786.                 return NULL;
  787.     }
  788.  
  789.     return NULL;
  790. }
  791.  
  792. #ifdef m88110
  793. static
  794. char *
  795. parse_ereg(param, insn, format, parcnt)
  796. char *param;
  797. struct m88k_insn *insn;
  798. struct m88k_opcode *format;
  799. int parcnt;
  800. {
  801.     unsigned int val = 0;
  802.  
  803.     if (*param != 'r' && *param != 'R')
  804.         return NULL;
  805.  
  806.     param++;
  807.  
  808.     if (!isdigit(*param))
  809.         return NULL;
  810.  
  811.     while (isdigit(*param))
  812.         if ((val = val * 10 + *param++ - '0') > 31)
  813.             return NULL;
  814.  
  815.     if((val & 0x1) != 0)
  816.         return NULL;
  817.  
  818.     insn->opcode |= val << format->op[parcnt].offset;
  819.  
  820.     switch (*param) {
  821.  
  822.         case '\0' :
  823.             if (parcnt == 2 || format->op[parcnt+1].type == NIL)
  824.                 return param;
  825.             else
  826.                 return NULL;
  827.  
  828.         case '['  :
  829.             if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
  830.                 return param+1;
  831.             else
  832.                 return NULL;
  833.  
  834.         case ','  :
  835.             if (parcnt != 2 && format->op[parcnt+1].type != NIL)
  836.                 return param+1;
  837.             else
  838.                 return NULL;
  839.     }
  840.  
  841.     return NULL;
  842. }
  843.  
  844. static
  845. char *
  846. parse_e4rot(param, insn, format, parcnt)
  847. char *param;
  848. struct m88k_insn *insn;
  849. struct m88k_opcode *format;
  850. int parcnt;
  851. {
  852.     int val;
  853.     char *saveptr, save_c, *offset_ptr;
  854.         expressionS exp;
  855.     segT seg;
  856.  
  857.     /* Now step over the '<' and look for the offset expression before a
  858.        '>' and the end of line (which is a '\0' when we get here).  We
  859.        know there is a '\0' where the end of line was because that is
  860.        what parse_a_buffer() in read.c does before calling md_assemble */
  861.     if (*param++ != '<')
  862.         return NULL;
  863.     offset_ptr = param;
  864.     while(*param != '\0')
  865.         param++;
  866.     if(param == offset_ptr || param[-1] != '>')
  867.         return NULL;
  868.     param--;
  869.     save_c = *param;
  870.     *param = '\0';
  871.     saveptr = input_line_pointer;
  872.     input_line_pointer = offset_ptr;
  873.     seg = expression(&exp);
  874.     *param = save_c;
  875.     input_line_pointer = saveptr;
  876.     val = exp.X_add_number;
  877.     if(seg != SEG_ABSOLUTE || val > 60 || (val & 0x3) != 0)
  878.         return NULL;
  879.  
  880.     val >>= 2;
  881.     insn->opcode |= val << format->op[parcnt].offset;
  882.  
  883.     return param+1;
  884. }
  885.  
  886. static
  887. char *
  888. parse_xreg(param, insn, format, parcnt)
  889. char *param;
  890. struct m88k_insn *insn;
  891. struct m88k_opcode *format;
  892. int parcnt;
  893. {
  894.     unsigned int val = 0;
  895.  
  896.     if (*param != 'x' && *param != 'X')
  897.         return NULL;
  898.  
  899.     param++;
  900.  
  901.     if (!isdigit(*param))
  902.         return NULL;
  903.  
  904.     while (isdigit(*param))
  905.         if ((val = val * 10 + *param++ - '0') > 31)
  906.             return NULL;
  907.  
  908.     insn->opcode |= val << format->op[parcnt].offset;
  909.  
  910.     switch (*param) {
  911.  
  912.         case '\0' :
  913.             if (parcnt == 2 || format->op[parcnt+1].type == NIL)
  914.                 return param;
  915.             else
  916.                 return NULL;
  917.  
  918.         case '['  :
  919.             if (parcnt != 2 && format->op[parcnt+1].type == REGSC)
  920.                 return param+1;
  921.             else
  922.                 return NULL;
  923.  
  924.         case ','  :
  925.             if (parcnt != 2 && format->op[parcnt+1].type != NIL)
  926.                 return param+1;
  927.             else
  928.                 return NULL;
  929.     }
  930.  
  931.     return NULL;
  932. }
  933. #endif m88110
  934.  
  935. static
  936. char *
  937. parse_cmp(param, insn, format, parcnt)
  938. char *param;
  939. struct m88k_insn *insn;
  940. struct m88k_opcode *format;
  941. int parcnt;
  942. {
  943.     int val;
  944.     char *saveptr, save_c, *offset_ptr, c;
  945.         expressionS exp;
  946.     segT seg;
  947.  
  948.     /* look for the offset expression before a ',' */
  949.     c = *param;
  950.     if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
  951.         c == '~'){
  952.         offset_ptr = param;
  953.         while(*param != ',')
  954.             param++;
  955.         if(param == offset_ptr || *param != ',')
  956.             return NULL;
  957.         save_c = *param;
  958.         *param = '\0';
  959.         saveptr = input_line_pointer;
  960.         input_line_pointer = offset_ptr;
  961.         seg = expression(&exp);
  962.         *param = save_c;
  963.         input_line_pointer = saveptr;
  964.         val = exp.X_add_number;
  965.         if(seg != SEG_ABSOLUTE ||
  966.            val > (1 << format->op[parcnt].width) || val < 0)
  967.             return NULL;
  968.     } else {
  969.         if (isupper(*param))
  970.             *param = tolower(*param);
  971.  
  972.         if (isupper(*(param+1)))
  973.             *(param+1) = tolower(*(param+1));
  974.  
  975.         for (val=0; cmpslot[val] != NULL; val++)
  976.             if (!strncmp(param,cmpslot[val],2))
  977.                 break;
  978.  
  979.         if (cmpslot[val] == NULL)
  980.             return NULL;
  981.  
  982.         param += 2;
  983.     }
  984.  
  985.     if (*param++ != ',')
  986.         return NULL;
  987.  
  988.     insn->opcode |= val << format->op[parcnt].offset;
  989.  
  990.     return param;
  991. }
  992.  
  993. static
  994. char *
  995. parse_cnd(param, insn, format, parcnt)
  996. char *param;
  997. struct m88k_insn *insn;
  998. struct m88k_opcode *format;
  999. int parcnt;
  1000. {
  1001.     int val;
  1002.     char *saveptr, save_c, *offset_ptr, c;
  1003.         expressionS exp;
  1004.     segT seg;
  1005.  
  1006.     /* look for the offset expression before a ',' */
  1007.     c = *param;
  1008.     if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
  1009.         c == '~'){
  1010.         offset_ptr = param;
  1011.         while(*param != ',')
  1012.             param++;
  1013.         if(param == offset_ptr || *param != ',')
  1014.             return NULL;
  1015.         save_c = *param;
  1016.         *param = '\0';
  1017.         saveptr = input_line_pointer;
  1018.         input_line_pointer = offset_ptr;
  1019.         seg = expression(&exp);
  1020.         *param = save_c;
  1021.         input_line_pointer = saveptr;
  1022.         val = exp.X_add_number;
  1023.         if(seg != SEG_ABSOLUTE ||
  1024.            val > (1 << format->op[parcnt].width) || val < 0)
  1025.             return NULL;
  1026.     } else {
  1027.         if (isupper(*param))
  1028.             *param = tolower(*param);
  1029.  
  1030.         if (isupper(*(param+1)))
  1031.             *(param+1) = tolower(*(param+1));
  1032.  
  1033.         for (val=0; cndmsk[val].name != NULL; val++)
  1034.             if (!strncmp(param,cndmsk[val].name,3))
  1035.                 break;
  1036.  
  1037.         if (cndmsk[val].name == NULL)
  1038.             return NULL;
  1039.  
  1040.         val = cndmsk[val].num;
  1041.  
  1042.         param += 3;
  1043.     }
  1044.  
  1045.     if (*param++ != ',')
  1046.         return NULL;
  1047.  
  1048.     insn->opcode |= val << format->op[parcnt].offset;
  1049.  
  1050.     return param;
  1051. }
  1052.  
  1053. static
  1054. char *
  1055. parse_bf(param, insn, format, parcnt)
  1056. char *param;
  1057. struct m88k_insn *insn;
  1058. struct m88k_opcode *format;
  1059. int parcnt;
  1060. {
  1061.     int val, width;
  1062.     char *saveptr, save_c, *offset_ptr, c;
  1063.         expressionS exp;
  1064.     segT seg;
  1065.  
  1066.     /* We know there is a '\0' where the end of line was because that is
  1067.        what parse_a_buffer() in read.c does before calling md_assemble */
  1068.  
  1069.     /* First look for the width expression before a '<' */
  1070.     saveptr = input_line_pointer;
  1071.     input_line_pointer = param;
  1072.     while(*param != '<' && *param != '\0')
  1073.         param++;
  1074.     if(*param == '\0'){
  1075.         input_line_pointer = saveptr;
  1076.         return NULL;
  1077.     }
  1078.     save_c = *param;
  1079.     *param = '\0';
  1080.     seg = expression(&exp);
  1081.     *param = save_c;
  1082.     input_line_pointer = saveptr;
  1083.     width = exp.X_add_number;
  1084.     if(seg != SEG_ABSOLUTE || width > 32 || width < 0)
  1085.         return NULL;
  1086.  
  1087.     /* Now step over the '<' and look for the offset expression before a
  1088.        '>' and the end of line (which is a '\0' when we get here) */
  1089.     param++;
  1090.     c = *param;
  1091.     if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
  1092.         c == '~'){
  1093.         offset_ptr = param;
  1094.         while(*param != '\0')
  1095.             param++;
  1096.         if(param != offset_ptr && param[-1] != '>')
  1097.             return NULL;
  1098.         param--;
  1099.         save_c = *param;
  1100.         *param = '\0';
  1101.         saveptr = input_line_pointer;
  1102.         input_line_pointer = offset_ptr;
  1103.         seg = expression(&exp);
  1104.         *param = save_c;
  1105.         input_line_pointer = saveptr;
  1106.         val = exp.X_add_number;
  1107.         if(seg != SEG_ABSOLUTE || val > 32 || val < 0)
  1108.             return NULL;
  1109.     }
  1110.     else {
  1111.         if (isupper(*param))
  1112.             *param = tolower(*param);
  1113.  
  1114.         if (isupper(*(param+1)))
  1115.             *(param+1) = tolower(*(param+1));
  1116.  
  1117.         for (val=0; cmpslot[val] != NULL; val++)
  1118.             if (!strncmp(param,cmpslot[val],2))
  1119.                 break;
  1120.  
  1121.         if (cmpslot[val] == NULL)
  1122.             return NULL;
  1123.  
  1124.         param += 2;
  1125.     }
  1126.     if (*param != '>')
  1127.         return NULL;
  1128.     insn->opcode |= width << 5;
  1129.     insn->opcode |= val;
  1130.  
  1131.     return param+1;
  1132. }
  1133.  
  1134. static
  1135. char *
  1136. parse_rot(param, insn, format, parcnt)
  1137. char *param;
  1138. struct m88k_insn *insn;
  1139. struct m88k_opcode *format;
  1140. int parcnt;
  1141. {
  1142.     int val;
  1143.     char *saveptr, save_c, *offset_ptr;
  1144.         expressionS exp;
  1145.     segT seg;
  1146.  
  1147.     /* Now step over the '<' and look for the offset expression before a
  1148.        '>' and the end of line (which is a '\0' when we get here).  We
  1149.        know there is a '\0' where the end of line was because that is
  1150.        what parse_a_buffer() in read.c does before calling md_assemble */
  1151.     if (*param++ != '<')
  1152.         return NULL;
  1153.     offset_ptr = param;
  1154.     while(*param != '\0')
  1155.         param++;
  1156.     if(param != offset_ptr && param[-1] != '>')
  1157.         return NULL;
  1158.     param--;
  1159.     save_c = *param;
  1160.     *param = '\0';
  1161.     saveptr = input_line_pointer;
  1162.     input_line_pointer = offset_ptr;
  1163.     seg = expression(&exp);
  1164.     *param = save_c;
  1165.     input_line_pointer = saveptr;
  1166.     val = exp.X_add_number;
  1167.     if(seg != SEG_ABSOLUTE && (val > 32 || val < 0))
  1168.         return NULL;
  1169.  
  1170.     insn->opcode |= val;
  1171.  
  1172.     return param+1;
  1173. }
  1174.  
  1175. static
  1176. char *
  1177. parse_rsc(param, insn, format, parcnt)
  1178. char *param;
  1179. struct m88k_insn *insn;
  1180. struct m88k_opcode *format;
  1181. int parcnt;
  1182. {
  1183.     unsigned int val = 0;
  1184.  
  1185.     if (*param != 'r' && *param != 'R')
  1186.         return NULL;
  1187.  
  1188.     param++;
  1189.  
  1190.     if (!isdigit(*param))
  1191.         return NULL;
  1192.  
  1193.     while (isdigit(*param))
  1194.         if ((val = val * 10 + *param++ - '0') > 31)
  1195.             return NULL;
  1196.  
  1197.     insn->opcode |= val << format->op[parcnt].offset;
  1198.  
  1199.     if (*param != ']' || *(param+1) != '\0')
  1200.         return NULL;
  1201.  
  1202.     return param+1;
  1203. }
  1204.  
  1205. static
  1206. char *
  1207. parse_cr(param, insn, format, parcnt)
  1208. char *param;
  1209. struct m88k_insn *insn;
  1210. struct m88k_opcode *format;
  1211. int parcnt;
  1212. {
  1213.     unsigned int val = 0;
  1214.  
  1215.     if (strncmp(param, "cr", 2))
  1216.         return NULL;
  1217.  
  1218.     param += 2;
  1219.  
  1220.     if (!isdigit(*param))
  1221.         return NULL;
  1222.  
  1223.     while (isdigit(*param))
  1224.         if ((val = val * 10 + *param++ - '0') > 63)
  1225.             return NULL;
  1226.  
  1227.     /*
  1228.      * the following fix is not as generic as I'd like, but the
  1229.      * hardware is real picky about this.    - bowen@cs.buffalo.edu
  1230.      * This fix is to make sure the S1 and S2 fields are the same.
  1231.      */
  1232.     insn->opcode |= (insn->opcode & 0x001f0000) >> 16;
  1233.  
  1234.     insn->opcode |= val << format->op[parcnt].offset;
  1235.  
  1236.     if (*param != '\0')
  1237.         return NULL;
  1238.  
  1239.     return param;
  1240. }
  1241.  
  1242. static
  1243. char *
  1244. parse_fcr(param, insn, format, parcnt)
  1245. char *param;
  1246. struct m88k_insn *insn;
  1247. struct m88k_opcode *format;
  1248. int parcnt;
  1249. {
  1250.     unsigned int val = 0;
  1251.  
  1252.     if (strncmp(param, "fcr", 3))
  1253.         return NULL;
  1254.  
  1255.     param += 3;
  1256.  
  1257.     if (!isdigit(*param))
  1258.         return NULL;
  1259.  
  1260.     while (isdigit(*param))
  1261.         if ((val = val * 10 + *param++ - '0') > 63)
  1262.             return NULL;
  1263.  
  1264.     /*
  1265.      * This is to make sure the S1 and S2 fields are the same.
  1266.      */
  1267.     insn->opcode |= (insn->opcode & 0x001f0000) >> 16;
  1268.  
  1269.     insn->opcode |= val << format->op[parcnt].offset;
  1270.  
  1271.     if (*param != '\0')
  1272.         return NULL;
  1273.  
  1274.     return param;
  1275. }
  1276.  
  1277. static
  1278. char *
  1279. parse_cst(param, insn, format, parcnt)
  1280. char *param;
  1281. struct m88k_insn *insn;
  1282. struct m88k_opcode *format;
  1283. int parcnt;
  1284. {
  1285.     char c, *saveptr, *saveparam;
  1286.     unsigned int val, mask, nohilo = 0;
  1287.     segT seg;
  1288.     int sign;
  1289.         expressionS exp;
  1290.  
  1291.     c = *param;
  1292.     if (isdigit(c) || c == '(' || c == '-' || c == '+' || c == '!' ||
  1293.         c == '~'){
  1294.         saveptr = input_line_pointer;
  1295.         input_line_pointer = param;
  1296.         while(*param != '\0')
  1297.             param++;
  1298.         seg = expression(&exp);
  1299.         input_line_pointer = saveptr;
  1300.         val = exp.X_add_number;
  1301.         if(seg != SEG_ABSOLUTE ||
  1302.            val > (1 << format->op[parcnt].width) || val < 0)
  1303.             return NULL;
  1304.     }
  1305.     else if (!strncmp(param,"hi16(",5))
  1306.  
  1307.         if (isdigit(*(param+5))) {
  1308.             param = getval(param+5,&val);
  1309.             val = (val & 0xffff0000) >> 16;
  1310.             if (*param++ != ')')
  1311.                 return NULL;
  1312.  
  1313.         } else
  1314.             insn->reloc = RELOC_HI16;
  1315.     else if (!strncmp(param,"lo16(",5))
  1316.  
  1317.         if (isdigit(*(param+5))) {
  1318.             param = getval(param+5,&val);
  1319.             val &= 0x0000ffff;
  1320.             if (*param++ != ')')
  1321.                 return NULL;
  1322.  
  1323.         } else
  1324.             insn->reloc = RELOC_LO16;
  1325.  
  1326. #ifndef NeXT
  1327.     else if (!strncmp(param,"iw16(",5))
  1328.  
  1329.         if (isdigit(*(param+5))) {
  1330.             param = getval(param+5,&val);
  1331.             val &= 0x0000ffff;
  1332.             if (*param++ != ')')
  1333.                 return NULL;
  1334.  
  1335.         } else
  1336.             insn->reloc = RELOC_IW16;
  1337. #endif !defined(NeXT)
  1338.  
  1339.     else if (*param == 'r' && isdigit(*(param+1)))
  1340.  
  1341.         return NULL;
  1342.  
  1343.     else {
  1344.         insn->reloc = RELOC_LO16;
  1345.         nohilo = 1;
  1346.     }
  1347.  
  1348.     if (insn->reloc != NO_RELOC) {
  1349.  
  1350.         saveptr = input_line_pointer;
  1351.         input_line_pointer = param + (nohilo ? 0 : 5);
  1352.  
  1353.         seg = expression(&insn->exp);
  1354.  
  1355.         saveparam = input_line_pointer;
  1356.         input_line_pointer = saveptr;
  1357.  
  1358.         if (nohilo) {
  1359.  
  1360.             if (*saveparam != '\0')
  1361.                 return NULL;
  1362.  
  1363.             return saveparam;
  1364.         }
  1365.  
  1366.         if (*saveparam != ')')
  1367.             return NULL;
  1368.  
  1369.         return saveparam+1;
  1370.     }
  1371.  
  1372.     if ((1 << format->op[parcnt].width) <= val)
  1373.         return NULL;
  1374.  
  1375.     insn->opcode |= val << format->op[parcnt].offset;
  1376.  
  1377.     if (*param != '\0')
  1378.         return NULL;
  1379.  
  1380.     return param;
  1381. }
  1382.  
  1383. #define isoct(z) (z >= '0' && z <= '7')
  1384. #define ishex(z) ((z >= '0' && z <= '9') || (z >= 'a' && z <= 'f') || (z >= 'A' && z <= 'F'))
  1385. #define hexval(z) \
  1386.   (isdigit(z) ? (z) - '0' :        \
  1387.    islower(z) ? (z) - 'a' + 10 :    \
  1388.    (z) - 'A' + 10)
  1389.  
  1390. static
  1391. char *
  1392. getval(param, val)
  1393. char *param;
  1394. unsigned int *val;
  1395. {
  1396.     *val = 0;
  1397.  
  1398.     if (*param == '0' && (*(param+1) == 'x' || *(param+1) == 'X'))
  1399.  
  1400.         for (param += 2; ishex(*param); param++)
  1401.  
  1402.             if (*val > 0x0fffffff)
  1403.                 return param;
  1404.             else
  1405.                 *val = *val * 16 + hexval(*param);
  1406.  
  1407.     else if (*param == '0')
  1408.  
  1409.         for (param++; isoct(*param); param++)
  1410.  
  1411.             if (*val > 0x1fffffff)
  1412.                 return param;
  1413.             else
  1414.                 *val = *val * 8 + *param - '0';
  1415.  
  1416.     else
  1417.  
  1418.         for (; isdigit(*param); param++)
  1419.  
  1420.             *val = *val * 10 + *param - '0';
  1421.  
  1422.     return param;
  1423. }
  1424.  
  1425. void
  1426. md_number_to_chars (buf, val, nbytes)
  1427. char *buf;
  1428. int val;
  1429. int nbytes;
  1430. {
  1431.     switch(nbytes) {
  1432.  
  1433.         case 4:
  1434.             *buf++ = val >> 24;
  1435.             *buf++ = val >> 16;
  1436.         case 2:
  1437.             *buf++ = val >> 8;
  1438.         case 1:
  1439.             *buf = val;
  1440.             break;
  1441.  
  1442.         default:
  1443.             abort();
  1444.     }
  1445. }
  1446.  
  1447. void
  1448. md_number_to_imm (buf, val, nbytes, fixP, seg_type)
  1449. unsigned char *buf;
  1450. unsigned int val;
  1451. int nbytes;
  1452. fixS *fixP;
  1453. int seg_type;
  1454. {
  1455.     if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC
  1456. #ifdef NeXT
  1457.         || fixP->fx_r_type == M88K_RELOC_VANILLA
  1458. #endif NeXT
  1459.         ) {
  1460.         switch (nbytes) {
  1461.             case 4:
  1462.                 *buf++ = val >> 24;
  1463.                 *buf++ = val >> 16;
  1464.             case 2:
  1465.                 *buf++ = val >> 8;
  1466.             case 1:
  1467.                 *buf = val;
  1468.                 break;
  1469.  
  1470.             default:
  1471.                 abort();
  1472.         }
  1473.         return;
  1474.     }
  1475.  
  1476.     switch (fixP->fx_r_type) {
  1477. #ifdef NeXT
  1478.             case RELOC_LO16:
  1479.                 buf[2] = val >> 8;
  1480.                 buf[3] = val;
  1481.                 break;
  1482.             case RELOC_HI16:
  1483.                 buf[2] = val >> 24;
  1484.                 buf[3] = val >> 16;
  1485.                 break;
  1486.  
  1487.             case RELOC_PC16:
  1488.                 val += 4;
  1489.                 buf[2] = val >> 10;
  1490.                 buf[3] = val >> 2;
  1491.                 break;
  1492.  
  1493.             case RELOC_PC26:
  1494.                 val += 4;
  1495.                 buf[0] |= (val >> 26) & 0x03;
  1496.                 buf[1] = val >> 18;
  1497.                 buf[2] = val >> 10;
  1498.                 buf[3] = val >> 2;
  1499.                 break;
  1500. #else !defined NeXT
  1501.             case RELOC_LO16:
  1502.                 buf[0] = val >> 8;
  1503.                 buf[1] = val;
  1504.                 break;
  1505.  
  1506.             case RELOC_IW16:
  1507.                 buf[2] = val >> 8;
  1508.                 buf[3] = val;
  1509.                 break;
  1510.  
  1511.             case RELOC_HI16:
  1512.                 buf[0] = val >> 24;
  1513.                 buf[1] = val >> 16;
  1514.                 break;
  1515.  
  1516.             case RELOC_PC16:
  1517.                 val += 4;
  1518.                 buf[0] = val >> 10;
  1519.                 buf[1] = val >> 2;
  1520.                 break;
  1521.  
  1522.             case RELOC_PC26:
  1523.                 val += 4;
  1524.                 buf[0] |= (val >> 26) & 0x03;
  1525.                 buf[1] = val >> 18;
  1526.                 buf[2] = val >> 10;
  1527.                 buf[3] = val >> 2;
  1528.                 break;
  1529.  
  1530.             case RELOC_32:
  1531.                 buf[0] = val >> 24;
  1532.                 buf[1] = val >> 16;
  1533.                 buf[2] = val >> 8;
  1534.                 buf[3] = val;
  1535.                 break;
  1536. #endif !defined(NeXT)
  1537.  
  1538.             default:
  1539.                 as_warn("Bad relocation type");
  1540.                 break;
  1541.     }
  1542. }
  1543.  
  1544. void
  1545. md_number_to_disp (buf, val, nbytes)
  1546. char *buf;
  1547. int val;
  1548. int nbytes;
  1549. {
  1550.     md_number_to_chars (buf, val, nbytes);
  1551. }
  1552.  
  1553. void
  1554. md_number_to_field (buf, val, nbytes)
  1555. char *buf;
  1556. int val;
  1557. int nbytes;
  1558. {
  1559.     md_number_to_chars (buf, val, nbytes);
  1560. }
  1561.  
  1562. void
  1563. md_ri_to_chars (ri_p, ri)
  1564.      struct relocation_info *ri_p, ri;
  1565. {
  1566.     /*
  1567.      * if you want to cross-assemble from
  1568.      * a little-endian then you might need to
  1569.      * do some byte-swapping here.
  1570.      */
  1571.     return;
  1572. }
  1573.  
  1574. #define MAX_LITTLENUMS 6
  1575.  
  1576. /* Turn a string in input_line_pointer into a floating point constant of type
  1577.    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
  1578.    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
  1579.  */
  1580. char *
  1581. md_atof(type,litP,sizeP)
  1582. char type;
  1583. char *litP;
  1584. int *sizeP;
  1585. {
  1586.     int    prec;
  1587.     LITTLENUM_TYPE words[MAX_LITTLENUMS];
  1588.     LITTLENUM_TYPE *wordP;
  1589.     char    *t;
  1590.     char    *atof_ieee();
  1591.  
  1592.     switch(type) {
  1593.     case 'f':
  1594.     case 'F':
  1595.     case 's':
  1596.     case 'S':
  1597.         prec = 2;
  1598.         break;
  1599.  
  1600.     case 'd':
  1601.     case 'D':
  1602.     case 'r':
  1603.     case 'R':
  1604.         prec = 4;
  1605.         break;
  1606.  
  1607.     case 'x':
  1608.     case 'X':
  1609.         prec = 6;
  1610.         break;
  1611.  
  1612.     case 'p':
  1613.     case 'P':
  1614.         prec = 6;
  1615.         break;
  1616.  
  1617.     default:
  1618.         *sizeP=0;
  1619.         return "Bad call to MD_ATOF()";
  1620.     }
  1621.     t=atof_ieee(input_line_pointer,type,words);
  1622.     if(t)
  1623.         input_line_pointer=t;
  1624.  
  1625.     *sizeP=prec * sizeof(LITTLENUM_TYPE);
  1626.     for(wordP=words;prec--;) {
  1627.         md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
  1628.         litP+=sizeof(LITTLENUM_TYPE);
  1629.     }
  1630.     return "";    /* Someone should teach Dean about null pointers */
  1631. }
  1632.  
  1633. int md_short_jump_size = 4;
  1634.  
  1635. void
  1636. md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
  1637. char *ptr;
  1638. long from_addr, to_addr;
  1639. fragS *frag;
  1640. symbolS *to_symbol;
  1641. {
  1642.     ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
  1643.     fix_new(
  1644.         frag,
  1645.         ptr - frag->fr_literal,
  1646.         4,
  1647.         to_symbol,
  1648.         (symbolS *) 0,
  1649.         (long int) 0,
  1650.         0,
  1651.         RELOC_PC26
  1652.     );
  1653. }
  1654.  
  1655. int md_long_jump_size = 4;
  1656.  
  1657. void
  1658. md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
  1659. char *ptr;
  1660. long from_addr, to_addr;
  1661. fragS *frag;
  1662. symbolS *to_symbol;
  1663. {
  1664.     ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
  1665.     fix_new(
  1666.         frag,
  1667.         ptr - frag->fr_literal,
  1668.         4,
  1669.         to_symbol,
  1670.         (symbolS *) 0,
  1671.         (long int) 0,
  1672.         0,
  1673.         RELOC_PC26
  1674.     );
  1675. }
  1676.  
  1677. int
  1678. md_estimate_size_before_relax (fragP, segment_type)
  1679. register fragS *fragP;
  1680. register int segment_type;
  1681. {
  1682.     as_warn("Relaxation should never occur");
  1683. }
  1684.  
  1685. const relax_typeS md_relax_table[] = {0};
  1686.  
  1687. void
  1688. md_convert_frag (fragP)
  1689.      register fragS *fragP;
  1690. {
  1691.     as_warn("Relaxation should never occur");
  1692. }
  1693.  
  1694. void
  1695. md_end()
  1696. {
  1697. }
  1698.  
  1699. #ifndef Mach_O
  1700. /*
  1701.  * Risc relocations are completely different, so it needs
  1702.  * this machine dependent routine to emit them.
  1703.  */
  1704. void
  1705. emit_relocations(fixP, segment_address_in_file)
  1706.     register fixS *fixP;
  1707.     relax_addressT segment_address_in_file;
  1708. {
  1709.     struct reloc_info_m88k ri;
  1710.     register symbolS *symbolP;
  1711.     extern char *next_object_file_charP;
  1712.     long add_number;
  1713.  
  1714.     bzero((char *) &ri, sizeof(ri));
  1715.     for (; fixP; fixP = fixP->fx_next) {
  1716.  
  1717.     if (fixP->fx_r_type >= NO_RELOC) {
  1718.         fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
  1719.         abort();
  1720.     }
  1721.  
  1722.     if ((symbolP = fixP->fx_addsy) != NULL) {
  1723.         ri.r_address = fixP->fx_frag->fr_address +
  1724.             fixP->fx_where - segment_address_in_file;
  1725.         if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
  1726.         ri.r_extern = 1;
  1727.         ri.r_symbolnum = symbolP->sy_number;
  1728.         } else {
  1729.         ri.r_extern = 0;
  1730.         ri.r_symbolnum = symbolP->sy_type & N_TYPE;
  1731.         }
  1732.         if (symbolP && symbolP->sy_frag) {
  1733.         ri.r_addend = symbolP->sy_frag->fr_address;
  1734.         }
  1735.         ri.r_type = fixP->fx_r_type;
  1736.         if (fixP->fx_pcrel) {
  1737. /*        ri.r_addend -= fixP->fx_where;          */
  1738.         ri.r_addend -= ri.r_address;            
  1739.         } else {
  1740.         ri.r_addend = fixP->fx_addnumber;
  1741.         }
  1742.  
  1743. /*        md_ri_to_chars((char *) &ri, ri);        */
  1744.         append(&next_object_file_charP, (char *)& ri, sizeof(ri));
  1745.     }
  1746.     }
  1747.     return;
  1748. }
  1749. #endif !defined(Mach_O)
  1750.