Back to index

cell-binutils  2.17cvs20070401
tc-mn10200.c
Go to the documentation of this file.
00001 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
00003    2005, 2006  Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to
00019    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
00020    Boston, MA 02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "safe-ctype.h"
00024 #include "subsegs.h"
00025 #include "opcode/mn10200.h"
00026 
00027 /* Structure to hold information about predefined registers.  */
00028 struct reg_name
00029 {
00030   const char *name;
00031   int value;
00032 };
00033 
00034 /* Generic assembler global variables which must be defined by all
00035    targets.  */
00036 
00037 /* Characters which always start a comment.  */
00038 const char comment_chars[] = "#";
00039 
00040 /* Characters which start a comment at the beginning of a line.  */
00041 const char line_comment_chars[] = ";#";
00042 
00043 /* Characters which may be used to separate multiple commands on a
00044    single line.  */
00045 const char line_separator_chars[] = ";";
00046 
00047 /* Characters which are used to indicate an exponent in a floating
00048    point number.  */
00049 const char EXP_CHARS[] = "eE";
00050 
00051 /* Characters which mean that a number is a floating point constant,
00052    as in 0d1.0.  */
00053 const char FLT_CHARS[] = "dD";
00054 
00055 const relax_typeS md_relax_table[] =
00056  {
00057   /* bCC relaxing  */
00058   {0x81, -0x7e, 2, 1},
00059   {0x8004, -0x7ffb, 5, 2},
00060   {0x800006, -0x7ffff9, 7, 0},
00061   /* bCCx relaxing  */
00062   {0x81, -0x7e, 3, 4},
00063   {0x8004, -0x7ffb, 6, 5},
00064   {0x800006, -0x7ffff9, 8, 0},
00065   /* jsr relaxing  */
00066   {0x8004, -0x7ffb, 3, 7},
00067   {0x800006, -0x7ffff9, 5, 0},
00068   /* jmp relaxing  */
00069   {0x81, -0x7e, 2, 9},
00070   {0x8004, -0x7ffb, 3, 10},
00071   {0x800006, -0x7ffff9, 5, 0},
00072 
00073 };
00074 
00075 
00076 /* Fixups.  */
00077 #define MAX_INSN_FIXUPS 5
00078 
00079 struct mn10200_fixup
00080 {
00081   expressionS exp;
00082   int opindex;
00083   bfd_reloc_code_real_type reloc;
00084 };
00085 
00086 struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
00087 static int fc;
00088 
00089 const char *md_shortopts = "";
00090 
00091 struct option md_longopts[] =
00092 {
00093   {NULL, no_argument, NULL, 0}
00094 };
00095 
00096 size_t md_longopts_size = sizeof (md_longopts);
00097 
00098 /* The target specific pseudo-ops which we support.  */
00099 const pseudo_typeS md_pseudo_table[] =
00100 {
00101   { NULL,       NULL,           0 }
00102 };
00103 
00104 /* Opcode hash table.  */
00105 static struct hash_control *mn10200_hash;
00106 
00107 /* This table is sorted. Suitable for searching by a binary search.  */
00108 static const struct reg_name data_registers[] =
00109 {
00110   { "d0", 0 },
00111   { "d1", 1 },
00112   { "d2", 2 },
00113   { "d3", 3 },
00114 };
00115 #define DATA_REG_NAME_CNT                        \
00116   (sizeof (data_registers) / sizeof (struct reg_name))
00117 
00118 static const struct reg_name address_registers[] =
00119 {
00120   { "a0", 0 },
00121   { "a1", 1 },
00122   { "a2", 2 },
00123   { "a3", 3 },
00124 };
00125 #define ADDRESS_REG_NAME_CNT                                   \
00126   (sizeof (address_registers) / sizeof (struct reg_name))
00127 
00128 static const struct reg_name other_registers[] =
00129 {
00130   { "mdr", 0 },
00131   { "psw", 0 },
00132 };
00133 #define OTHER_REG_NAME_CNT                       \
00134   (sizeof (other_registers) / sizeof (struct reg_name))
00135 
00136 /* reg_name_search does a binary search of the given register table
00137    to see if "name" is a valid regiter name.  Returns the register
00138    number from the array on success, or -1 on failure.  */
00139 
00140 static int
00141 reg_name_search (const struct reg_name *regs,
00142                int regcount,
00143                const char *name)
00144 {
00145   int middle, low, high;
00146   int cmp;
00147 
00148   low = 0;
00149   high = regcount - 1;
00150 
00151   do
00152     {
00153       middle = (low + high) / 2;
00154       cmp = strcasecmp (name, regs[middle].name);
00155       if (cmp < 0)
00156        high = middle - 1;
00157       else if (cmp > 0)
00158        low = middle + 1;
00159       else
00160        return regs[middle].value;
00161     }
00162   while (low <= high);
00163   return -1;
00164 }
00165 
00166 /* Summary of register_name().
00167 
00168    in: Input_line_pointer points to 1st char of operand.
00169 
00170    out: An expressionS.
00171        The operand may have been a register: in this case, X_op == O_register,
00172        X_add_number is set to the register number, and truth is returned.
00173        Input_line_pointer->(next non-blank) char after operand, or is in
00174        its original state.  */
00175 
00176 static bfd_boolean
00177 data_register_name (expressionS *expressionP)
00178 {
00179   int reg_number;
00180   char *name;
00181   char *start;
00182   char c;
00183 
00184   /* Find the spelling of the operand.  */
00185   start = name = input_line_pointer;
00186 
00187   c = get_symbol_end ();
00188   reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
00189 
00190   /* Put back the delimiting char.  */
00191   *input_line_pointer = c;
00192 
00193   /* Look to see if it's in the register table.  */
00194   if (reg_number >= 0)
00195     {
00196       expressionP->X_op = O_register;
00197       expressionP->X_add_number = reg_number;
00198 
00199       /* Make the rest nice.  */
00200       expressionP->X_add_symbol = NULL;
00201       expressionP->X_op_symbol = NULL;
00202 
00203       return TRUE;
00204     }
00205 
00206   /* Reset the line as if we had not done anything.  */
00207   input_line_pointer = start;
00208   return FALSE;
00209 }
00210 
00211 /* Summary of register_name().
00212 
00213    in: Input_line_pointer points to 1st char of operand.
00214 
00215    out: An expressionS.
00216        The operand may have been a register: in this case, X_op == O_register,
00217        X_add_number is set to the register number, and truth is returned.
00218        Input_line_pointer->(next non-blank) char after operand, or is in
00219        its original state.  */
00220 
00221 static bfd_boolean
00222 address_register_name (expressionS *expressionP)
00223 {
00224   int reg_number;
00225   char *name;
00226   char *start;
00227   char c;
00228 
00229   /* Find the spelling of the operand.  */
00230   start = name = input_line_pointer;
00231 
00232   c = get_symbol_end ();
00233   reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
00234 
00235   /* Put back the delimiting char.  */
00236   *input_line_pointer = c;
00237 
00238   /* Look to see if it's in the register table.  */
00239   if (reg_number >= 0)
00240     {
00241       expressionP->X_op = O_register;
00242       expressionP->X_add_number = reg_number;
00243 
00244       /* Make the rest nice.  */
00245       expressionP->X_add_symbol = NULL;
00246       expressionP->X_op_symbol = NULL;
00247 
00248       return TRUE;
00249     }
00250 
00251   /* Reset the line as if we had not done anything.  */
00252   input_line_pointer = start;
00253   return FALSE;
00254 }
00255 
00256 /* Summary of register_name().
00257 
00258    in: Input_line_pointer points to 1st char of operand.
00259 
00260    out: An expressionS.
00261        The operand may have been a register: in this case, X_op == O_register,
00262        X_add_number is set to the register number, and truth is returned.
00263        Input_line_pointer->(next non-blank) char after operand, or is in
00264        its original state.  */
00265 
00266 static bfd_boolean
00267 other_register_name (expressionS *expressionP)
00268 {
00269   int reg_number;
00270   char *name;
00271   char *start;
00272   char c;
00273 
00274   /* Find the spelling of the operand.  */
00275   start = name = input_line_pointer;
00276 
00277   c = get_symbol_end ();
00278   reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
00279 
00280   /* Put back the delimiting char.  */
00281   *input_line_pointer = c;
00282 
00283   /* Look to see if it's in the register table.  */
00284   if (reg_number >= 0)
00285     {
00286       expressionP->X_op = O_register;
00287       expressionP->X_add_number = reg_number;
00288 
00289       /* Make the rest nice.  */
00290       expressionP->X_add_symbol = NULL;
00291       expressionP->X_op_symbol = NULL;
00292 
00293       return TRUE;
00294     }
00295 
00296   /* Reset the line as if we had not done anything.  */
00297   input_line_pointer = start;
00298   return FALSE;
00299 }
00300 
00301 void
00302 md_show_usage (FILE *stream)
00303 {
00304   fprintf (stream, _("MN10200 options:\n\
00305 none yet\n"));
00306 }
00307 
00308 int
00309 md_parse_option (int c ATTRIBUTE_UNUSED,
00310                char *arg ATTRIBUTE_UNUSED)
00311 {
00312   return 0;
00313 }
00314 
00315 symbolS *
00316 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
00317 {
00318   return 0;
00319 }
00320 
00321 char *
00322 md_atof (int type, char *litp, int *sizep)
00323 {
00324   int prec;
00325   LITTLENUM_TYPE words[4];
00326   char *t;
00327   int i;
00328 
00329   switch (type)
00330     {
00331     case 'f':
00332       prec = 2;
00333       break;
00334 
00335     case 'd':
00336       prec = 4;
00337       break;
00338 
00339     default:
00340       *sizep = 0;
00341       return _("bad call to md_atof");
00342     }
00343 
00344   t = atof_ieee (input_line_pointer, type, words);
00345   if (t)
00346     input_line_pointer = t;
00347 
00348   *sizep = prec * 2;
00349 
00350   for (i = prec - 1; i >= 0; i--)
00351     {
00352       md_number_to_chars (litp, (valueT) words[i], 2);
00353       litp += 2;
00354     }
00355 
00356   return NULL;
00357 }
00358 
00359 void
00360 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
00361                asection *sec,
00362                fragS *fragP)
00363 {
00364   static unsigned long label_count = 0;
00365   char buf[40];
00366 
00367   subseg_change (sec, 0);
00368   if (fragP->fr_subtype == 0)
00369     {
00370       fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
00371               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00372       fragP->fr_var = 0;
00373       fragP->fr_fix += 2;
00374     }
00375   else if (fragP->fr_subtype == 1)
00376     {
00377       /* Reverse the condition of the first branch.  */
00378       int offset = fragP->fr_fix;
00379       int opcode = fragP->fr_literal[offset] & 0xff;
00380 
00381       switch (opcode)
00382        {
00383        case 0xe8:
00384          opcode = 0xe9;
00385          break;
00386        case 0xe9:
00387          opcode = 0xe8;
00388          break;
00389        case 0xe0:
00390          opcode = 0xe2;
00391          break;
00392        case 0xe2:
00393          opcode = 0xe0;
00394          break;
00395        case 0xe3:
00396          opcode = 0xe1;
00397          break;
00398        case 0xe1:
00399          opcode = 0xe3;
00400          break;
00401        case 0xe4:
00402          opcode = 0xe6;
00403          break;
00404        case 0xe6:
00405          opcode = 0xe4;
00406          break;
00407        case 0xe7:
00408          opcode = 0xe5;
00409          break;
00410        case 0xe5:
00411          opcode = 0xe7;
00412          break;
00413        default:
00414          abort ();
00415        }
00416       fragP->fr_literal[offset] = opcode;
00417 
00418       /* Create a fixup for the reversed conditional branch.  */
00419       sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
00420       fix_new (fragP, fragP->fr_fix + 1, 1,
00421               symbol_new (buf, sec, 0, fragP->fr_next),
00422               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00423 
00424       /* Now create the unconditional branch + fixup to the
00425         final target.  */
00426       fragP->fr_literal[offset + 2] = 0xfc;
00427       fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
00428               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
00429       fragP->fr_var = 0;
00430       fragP->fr_fix += 5;
00431     }
00432   else if (fragP->fr_subtype == 2)
00433     {
00434       /* Reverse the condition of the first branch.  */
00435       int offset = fragP->fr_fix;
00436       int opcode = fragP->fr_literal[offset] & 0xff;
00437 
00438       switch (opcode)
00439        {
00440        case 0xe8:
00441          opcode = 0xe9;
00442          break;
00443        case 0xe9:
00444          opcode = 0xe8;
00445          break;
00446        case 0xe0:
00447          opcode = 0xe2;
00448          break;
00449        case 0xe2:
00450          opcode = 0xe0;
00451          break;
00452        case 0xe3:
00453          opcode = 0xe1;
00454          break;
00455        case 0xe1:
00456          opcode = 0xe3;
00457          break;
00458        case 0xe4:
00459          opcode = 0xe6;
00460          break;
00461        case 0xe6:
00462          opcode = 0xe4;
00463          break;
00464        case 0xe7:
00465          opcode = 0xe5;
00466          break;
00467        case 0xe5:
00468          opcode = 0xe7;
00469          break;
00470        default:
00471          abort ();
00472        }
00473       fragP->fr_literal[offset] = opcode;
00474 
00475       /* Create a fixup for the reversed conditional branch.  */
00476       sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
00477       fix_new (fragP, fragP->fr_fix + 1, 1,
00478               symbol_new (buf, sec, 0, fragP->fr_next),
00479               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00480 
00481       /* Now create the unconditional branch + fixup to the
00482         final target.  */
00483       fragP->fr_literal[offset + 2] = 0xf4;
00484       fragP->fr_literal[offset + 3] = 0xe0;
00485       fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
00486               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
00487       fragP->fr_var = 0;
00488       fragP->fr_fix += 7;
00489     }
00490   else if (fragP->fr_subtype == 3)
00491     {
00492       fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
00493               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00494       fragP->fr_var = 0;
00495       fragP->fr_fix += 3;
00496     }
00497   else if (fragP->fr_subtype == 4)
00498     {
00499       /* Reverse the condition of the first branch.  */
00500       int offset = fragP->fr_fix;
00501       int opcode = fragP->fr_literal[offset + 1] & 0xff;
00502 
00503       switch (opcode)
00504        {
00505        case 0xfc:
00506          opcode = 0xfd;
00507          break;
00508        case 0xfd:
00509          opcode = 0xfc;
00510          break;
00511        case 0xfe:
00512          opcode = 0xff;
00513          break;
00514        case 0xff:
00515          opcode = 0xfe;
00516        case 0xe8:
00517          opcode = 0xe9;
00518          break;
00519        case 0xe9:
00520          opcode = 0xe8;
00521          break;
00522        case 0xe0:
00523          opcode = 0xe2;
00524          break;
00525        case 0xe2:
00526          opcode = 0xe0;
00527          break;
00528        case 0xe3:
00529          opcode = 0xe1;
00530          break;
00531        case 0xe1:
00532          opcode = 0xe3;
00533          break;
00534        case 0xe4:
00535          opcode = 0xe6;
00536          break;
00537        case 0xe6:
00538          opcode = 0xe4;
00539          break;
00540        case 0xe7:
00541          opcode = 0xe5;
00542          break;
00543        case 0xe5:
00544          opcode = 0xe7;
00545          break;
00546        case 0xec:
00547          opcode = 0xed;
00548          break;
00549        case 0xed:
00550          opcode = 0xec;
00551          break;
00552        case 0xee:
00553          opcode = 0xef;
00554          break;
00555        case 0xef:
00556          opcode = 0xee;
00557          break;
00558        default:
00559          abort ();
00560        }
00561       fragP->fr_literal[offset + 1] = opcode;
00562 
00563       /* Create a fixup for the reversed conditional branch.  */
00564       sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
00565       fix_new (fragP, fragP->fr_fix + 2, 1,
00566               symbol_new (buf, sec, 0, fragP->fr_next),
00567               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00568 
00569       /* Now create the unconditional branch + fixup to the
00570         final target.  */
00571       fragP->fr_literal[offset + 3] = 0xfc;
00572       fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
00573               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
00574       fragP->fr_var = 0;
00575       fragP->fr_fix += 6;
00576     }
00577   else if (fragP->fr_subtype == 5)
00578     {
00579       /* Reverse the condition of the first branch.  */
00580       int offset = fragP->fr_fix;
00581       int opcode = fragP->fr_literal[offset + 1] & 0xff;
00582 
00583       switch (opcode)
00584        {
00585        case 0xfc:
00586          opcode = 0xfd;
00587          break;
00588        case 0xfd:
00589          opcode = 0xfc;
00590          break;
00591        case 0xfe:
00592          opcode = 0xff;
00593          break;
00594        case 0xff:
00595          opcode = 0xfe;
00596        case 0xe8:
00597          opcode = 0xe9;
00598          break;
00599        case 0xe9:
00600          opcode = 0xe8;
00601          break;
00602        case 0xe0:
00603          opcode = 0xe2;
00604          break;
00605        case 0xe2:
00606          opcode = 0xe0;
00607          break;
00608        case 0xe3:
00609          opcode = 0xe1;
00610          break;
00611        case 0xe1:
00612          opcode = 0xe3;
00613          break;
00614        case 0xe4:
00615          opcode = 0xe6;
00616          break;
00617        case 0xe6:
00618          opcode = 0xe4;
00619          break;
00620        case 0xe7:
00621          opcode = 0xe5;
00622          break;
00623        case 0xe5:
00624          opcode = 0xe7;
00625          break;
00626        case 0xec:
00627          opcode = 0xed;
00628          break;
00629        case 0xed:
00630          opcode = 0xec;
00631          break;
00632        case 0xee:
00633          opcode = 0xef;
00634          break;
00635        case 0xef:
00636          opcode = 0xee;
00637          break;
00638        default:
00639          abort ();
00640        }
00641       fragP->fr_literal[offset + 1] = opcode;
00642 
00643       /* Create a fixup for the reversed conditional branch.  */
00644       sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
00645       fix_new (fragP, fragP->fr_fix + 2, 1,
00646               symbol_new (buf, sec, 0, fragP->fr_next),
00647               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00648 
00649       /* Now create the unconditional branch + fixup to the
00650         final target.  */
00651       fragP->fr_literal[offset + 3] = 0xf4;
00652       fragP->fr_literal[offset + 4] = 0xe0;
00653       fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
00654               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
00655       fragP->fr_var = 0;
00656       fragP->fr_fix += 8;
00657     }
00658   else if (fragP->fr_subtype == 6)
00659     {
00660       fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
00661               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
00662       fragP->fr_var = 0;
00663       fragP->fr_fix += 3;
00664     }
00665   else if (fragP->fr_subtype == 7)
00666     {
00667       int offset = fragP->fr_fix;
00668       fragP->fr_literal[offset] = 0xf4;
00669       fragP->fr_literal[offset + 1] = 0xe1;
00670 
00671       fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
00672               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
00673       fragP->fr_var = 0;
00674       fragP->fr_fix += 5;
00675     }
00676   else if (fragP->fr_subtype == 8)
00677     {
00678       fragP->fr_literal[fragP->fr_fix] = 0xea;
00679       fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
00680               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
00681       fragP->fr_var = 0;
00682       fragP->fr_fix += 2;
00683     }
00684   else if (fragP->fr_subtype == 9)
00685     {
00686       int offset = fragP->fr_fix;
00687       fragP->fr_literal[offset] = 0xfc;
00688 
00689       fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
00690               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
00691       fragP->fr_var = 0;
00692       fragP->fr_fix += 3;
00693     }
00694   else if (fragP->fr_subtype == 10)
00695     {
00696       int offset = fragP->fr_fix;
00697       fragP->fr_literal[offset] = 0xf4;
00698       fragP->fr_literal[offset + 1] = 0xe0;
00699 
00700       fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
00701               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
00702       fragP->fr_var = 0;
00703       fragP->fr_fix += 5;
00704     }
00705   else
00706     abort ();
00707 }
00708 
00709 valueT
00710 md_section_align (asection *seg, valueT addr)
00711 {
00712   int align = bfd_get_section_alignment (stdoutput, seg);
00713   return ((addr + (1 << align) - 1) & (-1 << align));
00714 }
00715 
00716 void
00717 md_begin (void)
00718 {
00719   char *prev_name = "";
00720   register const struct mn10200_opcode *op;
00721 
00722   mn10200_hash = hash_new ();
00723 
00724   /* Insert unique names into hash table.  The MN10200 instruction set
00725      has many identical opcode names that have different opcodes based
00726      on the operands.  This hash table then provides a quick index to
00727      the first opcode with a particular name in the opcode table.  */
00728 
00729   op = mn10200_opcodes;
00730   while (op->name)
00731     {
00732       if (strcmp (prev_name, op->name))
00733        {
00734          prev_name = (char *) op->name;
00735          hash_insert (mn10200_hash, op->name, (char *) op);
00736        }
00737       op++;
00738     }
00739 
00740   /* This is both a simplification (we don't have to write md_apply_fix)
00741      and support for future optimizations (branch shortening and similar
00742      stuff in the linker.  */
00743   linkrelax = 1;
00744 }
00745 
00746 static unsigned long
00747 check_operand (unsigned long insn ATTRIBUTE_UNUSED,
00748               const struct mn10200_operand *operand,
00749               offsetT val)
00750 {
00751   /* No need to check 24bit or 32bit operands for a bit.  */
00752   if (operand->bits < 24
00753       && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
00754     {
00755       long min, max;
00756       offsetT test;
00757 
00758       if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
00759        {
00760          max = (1 << (operand->bits - 1)) - 1;
00761          min = - (1 << (operand->bits - 1));
00762        }
00763       else
00764        {
00765          max = (1 << operand->bits) - 1;
00766          min = 0;
00767        }
00768 
00769       test = val;
00770 
00771       if (test < (offsetT) min || test > (offsetT) max)
00772        return 0;
00773       else
00774        return 1;
00775     }
00776   return 1;
00777 }
00778 /* If while processing a fixup, a reloc really needs to be created
00779    Then it is done here.  */
00780 
00781 arelent *
00782 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
00783 {
00784   arelent *reloc;
00785   reloc = xmalloc (sizeof (arelent));
00786 
00787   if (fixp->fx_subsy != NULL)
00788     {
00789       if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
00790          && S_IS_DEFINED (fixp->fx_subsy))
00791        {
00792          fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
00793          fixp->fx_subsy = NULL;
00794        }
00795       else
00796        /* FIXME: We should try more ways to resolve difference expressions
00797           here.  At least this is better than silently ignoring the
00798           subtrahend.  */
00799        as_bad_where (fixp->fx_file, fixp->fx_line,
00800                     _("can't resolve `%s' {%s section} - `%s' {%s section}"),
00801                     fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
00802                     segment_name (fixp->fx_addsy
00803                                 ? S_GET_SEGMENT (fixp->fx_addsy)
00804                                 : absolute_section),
00805                     S_GET_NAME (fixp->fx_subsy),
00806                     segment_name (S_GET_SEGMENT (fixp->fx_addsy)));
00807     }
00808 
00809   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
00810   if (reloc->howto == NULL)
00811     {
00812       as_bad_where (fixp->fx_file, fixp->fx_line,
00813                   _("reloc %d not supported by object file format"),
00814                   (int) fixp->fx_r_type);
00815       return NULL;
00816     }
00817   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
00818   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
00819   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
00820   reloc->addend = fixp->fx_offset;
00821   return reloc;
00822 }
00823 
00824 int
00825 md_estimate_size_before_relax (fragS *fragp, asection *seg)
00826 {
00827   if (fragp->fr_subtype == 6
00828       && (!S_IS_DEFINED (fragp->fr_symbol)
00829          || seg != S_GET_SEGMENT (fragp->fr_symbol)))
00830     fragp->fr_subtype = 7;
00831   else if (fragp->fr_subtype == 8
00832           && (!S_IS_DEFINED (fragp->fr_symbol)
00833               || seg != S_GET_SEGMENT (fragp->fr_symbol)))
00834     fragp->fr_subtype = 10;
00835 
00836   if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
00837     abort ();
00838 
00839   return md_relax_table[fragp->fr_subtype].rlx_length;
00840 }
00841 
00842 long
00843 md_pcrel_from (fixS *fixp)
00844 {
00845   return fixp->fx_frag->fr_address;
00846 }
00847 
00848 void
00849 md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
00850 {
00851   /* We shouldn't ever get here because linkrelax is nonzero.  */
00852   abort ();
00853   fixP->fx_done = 1;
00854 }
00855 
00856 /* Insert an operand value into an instruction.  */
00857 
00858 static void
00859 mn10200_insert_operand (unsigned long *insnp,
00860                      unsigned long *extensionp,
00861                      const struct mn10200_operand *operand,
00862                      offsetT val,
00863                      char *file,
00864                      unsigned int line,
00865                      unsigned int shift)
00866 {
00867   /* No need to check 24 or 32bit operands for a bit.  */
00868   if (operand->bits < 24
00869       && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
00870     {
00871       long min, max;
00872       offsetT test;
00873 
00874       if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
00875        {
00876          max = (1 << (operand->bits - 1)) - 1;
00877          min = - (1 << (operand->bits - 1));
00878        }
00879       else
00880        {
00881          max = (1 << operand->bits) - 1;
00882          min = 0;
00883        }
00884 
00885       test = val;
00886 
00887       if (test < (offsetT) min || test > (offsetT) max)
00888        as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
00889     }
00890 
00891   if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
00892     {
00893       *insnp |= (((long) val & ((1 << operand->bits) - 1))
00894                << (operand->shift + shift));
00895 
00896       if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
00897        *insnp |= (((long) val & ((1 << operand->bits) - 1))
00898                  << (operand->shift + shift + 2));
00899     }
00900   else
00901     {
00902       *extensionp |= (val >> 16) & 0xff;
00903       *insnp |= val & 0xffff;
00904     }
00905 }
00906 
00907 void
00908 md_assemble (char *str)
00909 {
00910   char *s;
00911   struct mn10200_opcode *opcode;
00912   struct mn10200_opcode *next_opcode;
00913   const unsigned char *opindex_ptr;
00914   int next_opindex, relaxable;
00915   unsigned long insn, extension, size = 0;
00916   char *f;
00917   int i;
00918   int match;
00919 
00920   /* Get the opcode.  */
00921   for (s = str; *s != '\0' && !ISSPACE (*s); s++)
00922     ;
00923   if (*s != '\0')
00924     *s++ = '\0';
00925 
00926   /* Find the first opcode with the proper name.  */
00927   opcode = (struct mn10200_opcode *) hash_find (mn10200_hash, str);
00928   if (opcode == NULL)
00929     {
00930       as_bad (_("Unrecognized opcode: `%s'"), str);
00931       return;
00932     }
00933 
00934   str = s;
00935   while (ISSPACE (*str))
00936     ++str;
00937 
00938   input_line_pointer = str;
00939 
00940   for (;;)
00941     {
00942       const char *errmsg = NULL;
00943       int op_idx;
00944       char *hold;
00945       int extra_shift = 0;
00946 
00947       relaxable = 0;
00948       fc = 0;
00949       match = 0;
00950       next_opindex = 0;
00951       insn = opcode->opcode;
00952       extension = 0;
00953       for (op_idx = 1, opindex_ptr = opcode->operands;
00954           *opindex_ptr != 0;
00955           opindex_ptr++, op_idx++)
00956        {
00957          const struct mn10200_operand *operand;
00958          expressionS ex;
00959 
00960          if (next_opindex == 0)
00961            {
00962              operand = &mn10200_operands[*opindex_ptr];
00963            }
00964          else
00965            {
00966              operand = &mn10200_operands[next_opindex];
00967              next_opindex = 0;
00968            }
00969 
00970          errmsg = NULL;
00971 
00972          while (*str == ' ' || *str == ',')
00973            ++str;
00974 
00975          if (operand->flags & MN10200_OPERAND_RELAX)
00976            relaxable = 1;
00977 
00978          /* Gather the operand.  */
00979          hold = input_line_pointer;
00980          input_line_pointer = str;
00981 
00982          if (operand->flags & MN10200_OPERAND_PAREN)
00983            {
00984              if (*input_line_pointer != ')' && *input_line_pointer != '(')
00985               {
00986                 input_line_pointer = hold;
00987                 str = hold;
00988                 goto error;
00989               }
00990              input_line_pointer++;
00991              goto keep_going;
00992            }
00993          /* See if we can match the operands.  */
00994          else if (operand->flags & MN10200_OPERAND_DREG)
00995            {
00996              if (!data_register_name (&ex))
00997               {
00998                 input_line_pointer = hold;
00999                 str = hold;
01000                 goto error;
01001               }
01002            }
01003          else if (operand->flags & MN10200_OPERAND_AREG)
01004            {
01005              if (!address_register_name (&ex))
01006               {
01007                 input_line_pointer = hold;
01008                 str = hold;
01009                 goto error;
01010               }
01011            }
01012          else if (operand->flags & MN10200_OPERAND_PSW)
01013            {
01014              char *start = input_line_pointer;
01015              char c = get_symbol_end ();
01016 
01017              if (strcmp (start, "psw") != 0)
01018               {
01019                 *input_line_pointer = c;
01020                 input_line_pointer = hold;
01021                 str = hold;
01022                 goto error;
01023               }
01024              *input_line_pointer = c;
01025              goto keep_going;
01026            }
01027          else if (operand->flags & MN10200_OPERAND_MDR)
01028            {
01029              char *start = input_line_pointer;
01030              char c = get_symbol_end ();
01031 
01032              if (strcmp (start, "mdr") != 0)
01033               {
01034                 *input_line_pointer = c;
01035                 input_line_pointer = hold;
01036                 str = hold;
01037                 goto error;
01038               }
01039              *input_line_pointer = c;
01040              goto keep_going;
01041            }
01042          else if (data_register_name (&ex))
01043            {
01044              input_line_pointer = hold;
01045              str = hold;
01046              goto error;
01047            }
01048          else if (address_register_name (&ex))
01049            {
01050              input_line_pointer = hold;
01051              str = hold;
01052              goto error;
01053            }
01054          else if (other_register_name (&ex))
01055            {
01056              input_line_pointer = hold;
01057              str = hold;
01058              goto error;
01059            }
01060          else if (*str == ')' || *str == '(')
01061            {
01062              input_line_pointer = hold;
01063              str = hold;
01064              goto error;
01065            }
01066          else
01067            {
01068              expression (&ex);
01069            }
01070 
01071          switch (ex.X_op)
01072            {
01073            case O_illegal:
01074              errmsg = _("illegal operand");
01075              goto error;
01076            case O_absent:
01077              errmsg = _("missing operand");
01078              goto error;
01079            case O_register:
01080              if ((operand->flags
01081                  & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
01082               {
01083                 input_line_pointer = hold;
01084                 str = hold;
01085                 goto error;
01086               }
01087 
01088              if (opcode->format == FMT_2 || opcode->format == FMT_5)
01089               extra_shift = 8;
01090              else if (opcode->format == FMT_3 || opcode->format == FMT_6
01091                      || opcode->format == FMT_7)
01092               extra_shift = 16;
01093              else
01094               extra_shift = 0;
01095 
01096              mn10200_insert_operand (&insn, &extension, operand,
01097                                   ex.X_add_number, NULL,
01098                                   0, extra_shift);
01099 
01100              break;
01101 
01102            case O_constant:
01103              /* If this operand can be promoted, and it doesn't
01104                fit into the allocated bitfield for this insn,
01105                then promote it (ie this opcode does not match).  */
01106              if (operand->flags
01107                 & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
01108                 && !check_operand (insn, operand, ex.X_add_number))
01109               {
01110                 input_line_pointer = hold;
01111                 str = hold;
01112                 goto error;
01113               }
01114 
01115              mn10200_insert_operand (&insn, &extension, operand,
01116                                   ex.X_add_number, NULL,
01117                                   0, 0);
01118              break;
01119 
01120            default:
01121              /* If this operand can be promoted, then this opcode didn't
01122                match since we can't know if it needed promotion!  */
01123              if (operand->flags & MN10200_OPERAND_PROMOTE)
01124               {
01125                 input_line_pointer = hold;
01126                 str = hold;
01127                 goto error;
01128               }
01129 
01130              /* We need to generate a fixup for this expression.  */
01131              if (fc >= MAX_INSN_FIXUPS)
01132               as_fatal (_("too many fixups"));
01133              fixups[fc].exp = ex;
01134              fixups[fc].opindex = *opindex_ptr;
01135              fixups[fc].reloc = BFD_RELOC_UNUSED;
01136              ++fc;
01137              break;
01138            }
01139 
01140 keep_going:
01141          str = input_line_pointer;
01142          input_line_pointer = hold;
01143 
01144          while (*str == ' ' || *str == ',')
01145            ++str;
01146 
01147        }
01148 
01149       /* Make sure we used all the operands!  */
01150       if (*str != ',')
01151        match = 1;
01152 
01153     error:
01154       if (match == 0)
01155        {
01156          next_opcode = opcode + 1;
01157          if (!strcmp (next_opcode->name, opcode->name))
01158            {
01159              opcode = next_opcode;
01160              continue;
01161            }
01162 
01163          as_bad ("%s", errmsg);
01164          return;
01165        }
01166       break;
01167     }
01168 
01169   while (ISSPACE (*str))
01170     ++str;
01171 
01172   if (*str != '\0')
01173     as_bad (_("junk at end of line: `%s'"), str);
01174 
01175   input_line_pointer = str;
01176 
01177   if (opcode->format == FMT_1)
01178     size = 1;
01179   else if (opcode->format == FMT_2 || opcode->format == FMT_4)
01180     size = 2;
01181   else if (opcode->format == FMT_3 || opcode->format == FMT_5)
01182     size = 3;
01183   else if (opcode->format == FMT_6)
01184     size = 4;
01185   else if (opcode->format == FMT_7)
01186     size = 5;
01187   else
01188     abort ();
01189 
01190   /* Write out the instruction.  */
01191   if (relaxable && fc > 0)
01192     {
01193       /* On a 64-bit host the size of an 'int' is not the same
01194         as the size of a pointer, so we need a union to convert
01195         the opindex field of the fr_cgen structure into a char *
01196         so that it can be stored in the frag.  We do not have
01197         to worry about loosing accuracy as we are not going to
01198         be even close to the 32bit limit of the int.  */
01199       union
01200       {
01201        int opindex;
01202        char * ptr;
01203       }
01204       opindex_converter;
01205       int type;
01206 
01207       /* bCC  */
01208       if (size == 2 && opcode->opcode != 0xfc0000)
01209        {
01210          /* Handle bra specially.  Basically treat it like jmp so
01211             that we automatically handle 8, 16 and 32 bit offsets
01212             correctly as well as jumps to an undefined address.
01213 
01214             It is also important to not treat it like other bCC
01215             instructions since the long forms of bra is different
01216             from other bCC instructions.  */
01217          if (opcode->opcode == 0xea00)
01218            type = 8;
01219          else
01220            type = 0;
01221        }
01222       /* jsr  */
01223       else if (size == 3 && opcode->opcode == 0xfd0000)
01224        type = 6;
01225       /* jmp  */
01226       else if (size == 3 && opcode->opcode == 0xfc0000)
01227        type = 8;
01228       /* bCCx  */
01229       else
01230        type = 3;
01231 
01232       opindex_converter.opindex = fixups[0].opindex;
01233       f = frag_var (rs_machine_dependent, 8, 8 - size, type,
01234                   fixups[0].exp.X_add_symbol,
01235                   fixups[0].exp.X_add_number,
01236                   opindex_converter.ptr);
01237       number_to_chars_bigendian (f, insn, size);
01238       if (8 - size > 4)
01239        {
01240          number_to_chars_bigendian (f + size, 0, 4);
01241          number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
01242        }
01243       else
01244        number_to_chars_bigendian (f + size, 0, 8 - size);
01245     }
01246   else
01247     {
01248       f = frag_more (size);
01249 
01250       /* Oh, what a mess.  The instruction is in big endian format, but
01251         16 and 24bit immediates are little endian!  */
01252       if (opcode->format == FMT_3)
01253        {
01254          number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
01255          number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
01256        }
01257       else if (opcode->format == FMT_6)
01258        {
01259          number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
01260          number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
01261        }
01262       else if (opcode->format == FMT_7)
01263        {
01264          number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
01265          number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
01266          number_to_chars_littleendian (f + 4, extension & 0xff, 1);
01267        }
01268       else
01269        number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
01270 
01271       /* Create any fixups.  */
01272       for (i = 0; i < fc; i++)
01273        {
01274          const struct mn10200_operand *operand;
01275 
01276          operand = &mn10200_operands[fixups[i].opindex];
01277          if (fixups[i].reloc != BFD_RELOC_UNUSED)
01278            {
01279              reloc_howto_type *reloc_howto;
01280              int size;
01281              int offset;
01282              fixS *fixP;
01283 
01284              reloc_howto = bfd_reloc_type_lookup (stdoutput,
01285                                              fixups[i].reloc);
01286 
01287              if (!reloc_howto)
01288               abort ();
01289 
01290              size = bfd_get_reloc_size (reloc_howto);
01291 
01292              if (size < 1 || size > 4)
01293               abort ();
01294 
01295              offset = 4 - size;
01296              fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
01297                               size,
01298                               &fixups[i].exp,
01299                               reloc_howto->pc_relative,
01300                               fixups[i].reloc);
01301 
01302              /* PC-relative offsets are from the first byte of the
01303                next instruction, not from the start of the current
01304                instruction.  */
01305              if (reloc_howto->pc_relative)
01306               fixP->fx_offset += size;
01307            }
01308          else
01309            {
01310              int reloc, pcrel, reloc_size, offset;
01311              fixS *fixP;
01312 
01313              reloc = BFD_RELOC_NONE;
01314              /* How big is the reloc?  Remember SPLIT relocs are
01315                implicitly 32bits.  */
01316              reloc_size = operand->bits;
01317 
01318              offset = size - reloc_size / 8;
01319 
01320              /* Is the reloc pc-relative?  */
01321              pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
01322 
01323              /* Choose a proper BFD relocation type.  */
01324              if (pcrel)
01325               {
01326                 if (reloc_size == 8)
01327                   reloc = BFD_RELOC_8_PCREL;
01328                 else if (reloc_size == 24)
01329                   reloc = BFD_RELOC_24_PCREL;
01330                 else
01331                   abort ();
01332               }
01333              else
01334               {
01335                 if (reloc_size == 32)
01336                   reloc = BFD_RELOC_32;
01337                 else if (reloc_size == 16)
01338                   reloc = BFD_RELOC_16;
01339                 else if (reloc_size == 8)
01340                   reloc = BFD_RELOC_8;
01341                 else if (reloc_size == 24)
01342                   reloc = BFD_RELOC_24;
01343                 else
01344                   abort ();
01345               }
01346 
01347              /* Convert the size of the reloc into what fix_new_exp
01348                  wants.  */
01349              reloc_size = reloc_size / 8;
01350              if (reloc_size == 8)
01351               reloc_size = 0;
01352              else if (reloc_size == 16)
01353               reloc_size = 1;
01354              else if (reloc_size == 32 || reloc_size == 24)
01355               reloc_size = 2;
01356 
01357              fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
01358                               reloc_size, &fixups[i].exp, pcrel,
01359                               ((bfd_reloc_code_real_type) reloc));
01360 
01361              /* PC-relative offsets are from the first byte of the
01362                next instruction, not from the start of the current
01363                instruction.  */
01364              if (pcrel)
01365               fixP->fx_offset += size;
01366            }
01367        }
01368     }
01369 }
01370