Back to index

cell-binutils  2.17cvs20070401
tc-pdp11.c
Go to the documentation of this file.
00001 /* tc-pdp11.c - pdp11-specific -
00002    Copyright 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
00003 
00004    This file is part of GAS, the GNU Assembler.
00005 
00006    GAS is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    GAS is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with GAS; see the file COPYING.  If not, write to
00018    the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00019 
00020 #include "as.h"
00021 #include "safe-ctype.h"
00022 #include "opcode/pdp11.h"
00023 
00024 extern int flonum_gen2vax (int, FLONUM_TYPE * f, LITTLENUM_TYPE *);
00025 
00026 #define TRUE  1
00027 #define FALSE 0
00028 
00029 /* A representation for PDP-11 machine code.  */
00030 struct pdp11_code
00031 {
00032   char *error;
00033   int code;
00034   int additional;    /* Is there an additional word?  */
00035   int word;          /* Additional word, if any.  */
00036   struct
00037   {
00038     bfd_reloc_code_real_type type;
00039     expressionS exp;
00040     int pc_rel;
00041   } reloc;
00042 };
00043 
00044 /* Instruction set extensions.
00045 
00046    If you change this from an array to something else, please update
00047    the "PDP-11 instruction set extensions" comment in pdp11.h.  */
00048 int pdp11_extension[PDP11_EXT_NUM];
00049 
00050 /* Assembly options.  */
00051 
00052 #define ASM_OPT_PIC 1
00053 #define ASM_OPT_NUM 2
00054 
00055 int asm_option[ASM_OPT_NUM];
00056 
00057 /* These chars start a comment anywhere in a source file (except inside
00058    another comment.  */
00059 const char comment_chars[] = "#/";
00060 
00061 /* These chars only start a comment at the beginning of a line.  */
00062 const char line_comment_chars[] = "#/";
00063 
00064 const char line_separator_chars[] = ";";
00065 
00066 /* Chars that can be used to separate mant from exp in floating point nums.  */
00067 const char EXP_CHARS[] = "eE";
00068 
00069 /* Chars that mean this number is a floating point constant.  */
00070 /* as in 0f123.456.  */
00071 /* or    0H1.234E-12 (see exp chars above).  */
00072 const char FLT_CHARS[] = "dDfF";
00073 
00074 void pseudo_even (int);
00075 void pseudo_bss (int);
00076 
00077 const pseudo_typeS md_pseudo_table[] =
00078 {
00079   { "bss", pseudo_bss, 0 },
00080   { "even", pseudo_even, 0 },
00081   { 0, 0, 0 },
00082 };
00083 
00084 static struct hash_control *insn_hash = NULL;
00085 
00086 static int
00087 set_option (char *arg)
00088 {
00089   int yes = 1;
00090 
00091   if (strcmp (arg, "all-extensions") == 0
00092       || strcmp (arg, "all") == 0)
00093     {
00094       memset (pdp11_extension, ~0, sizeof pdp11_extension);
00095       pdp11_extension[PDP11_NONE] = 0;
00096       return 1;
00097     }
00098   else if (strcmp (arg, "no-extensions") == 0)
00099     {
00100       memset (pdp11_extension, 0, sizeof pdp11_extension);
00101       pdp11_extension[PDP11_BASIC] = 1;
00102       return 1;
00103     }
00104 
00105   if (strncmp (arg, "no-", 3) == 0)
00106     {
00107       yes = 0;
00108       arg += 3;
00109     }
00110 
00111   /* Commersial instructions.  */
00112   if (strcmp (arg, "cis") == 0)
00113     pdp11_extension[PDP11_CIS] = yes;
00114   /* Call supervisor mode.  */
00115   else if (strcmp (arg, "csm") == 0)
00116     pdp11_extension[PDP11_CSM] = yes;
00117   /* Extended instruction set.  */
00118   else if (strcmp (arg, "eis") == 0)
00119     pdp11_extension[PDP11_EIS] = pdp11_extension[PDP11_LEIS] = yes;
00120   /* KEV11 floating-point.  */
00121   else if (strcmp (arg, "fis") == 0
00122           || strcmp (arg, "kev11") == 0
00123           || strcmp (arg, "kev-11") == 0)
00124     pdp11_extension[PDP11_FIS] = yes;
00125   /* FP-11 floating-point.  */
00126   else if (strcmp (arg, "fpp") == 0
00127           || strcmp (arg, "fpu") == 0
00128           || strcmp (arg, "fp11") == 0
00129           || strcmp (arg, "fp-11") == 0
00130           || strcmp (arg, "fpj11") == 0
00131           || strcmp (arg, "fp-j11") == 0
00132           || strcmp (arg, "fpj-11") == 0)
00133     pdp11_extension[PDP11_FPP] = yes;
00134   /* Limited extended insns.  */
00135   else if (strcmp (arg, "limited-eis") == 0)
00136     {
00137       pdp11_extension[PDP11_LEIS] = yes;
00138       if (!pdp11_extension[PDP11_LEIS])
00139        pdp11_extension[PDP11_EIS] = 0;
00140     }
00141   /* Move from processor type.  */
00142   else if (strcmp (arg, "mfpt") == 0)
00143     pdp11_extension[PDP11_MFPT] = yes;
00144   /* Multiprocessor insns:  */
00145   else if (strncmp (arg, "mproc", 5) == 0
00146           /* TSTSET, WRTLCK */
00147           || strncmp (arg, "multiproc", 9) == 0)
00148     pdp11_extension[PDP11_MPROC] = yes;
00149   /* Move from/to proc status.  */
00150   else if (strcmp (arg, "mxps") == 0)
00151     pdp11_extension[PDP11_MXPS] = yes;
00152   /* Position-independent code.  */
00153   else if (strcmp (arg, "pic") == 0)
00154     asm_option[ASM_OPT_PIC] = yes;
00155   /* Set priority level.  */
00156   else if (strcmp (arg, "spl") == 0)
00157     pdp11_extension[PDP11_SPL] = yes;
00158   /* Microcode instructions:  */
00159   else if (strcmp (arg, "ucode") == 0
00160           /* LDUB, MED, XFC */
00161           || strcmp (arg, "microcode") == 0)
00162     pdp11_extension[PDP11_UCODE] = yes;
00163   else
00164     return 0;
00165 
00166   return 1;
00167 }
00168 
00169 
00170 static void
00171 init_defaults (void)
00172 {
00173   static int first = 1;
00174 
00175   if (first)
00176     {
00177       set_option ("all-extensions");
00178       set_option ("pic");
00179       first = 0;
00180     }
00181 }
00182 
00183 void
00184 md_begin (void)
00185 {
00186   int i;
00187 
00188   init_defaults ();
00189 
00190   insn_hash = hash_new ();
00191   if (insn_hash == NULL)
00192     as_fatal ("Virtual memory exhausted");
00193 
00194   for (i = 0; i < pdp11_num_opcodes; i++)
00195     hash_insert (insn_hash, pdp11_opcodes[i].name, (void *) (pdp11_opcodes + i));
00196   for (i = 0; i < pdp11_num_aliases; i++)
00197     hash_insert (insn_hash, pdp11_aliases[i].name, (void *) (pdp11_aliases + i));
00198 }
00199 
00200 void
00201 md_number_to_chars (char con[], valueT value, int nbytes)
00202 {
00203   /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
00204      0x12345678 is stored as "\x56\x78\x12\x34". It's
00205      anyones guess what 0x123456 would be stored like.  */
00206 
00207   switch (nbytes)
00208     {
00209     case 0:
00210       break;
00211     case 1:
00212       con[0] =  value       & 0xff;
00213       break;
00214     case 2:
00215       con[0] =  value        & 0xff;
00216       con[1] = (value >>  8) & 0xff;
00217       break;
00218     case 4:
00219       con[0] = (value >> 16) & 0xff;
00220       con[1] = (value >> 24) & 0xff;
00221       con[2] =  value        & 0xff;
00222       con[3] = (value >>  8) & 0xff;
00223       break;
00224     default:
00225       BAD_CASE (nbytes);
00226     }
00227 }
00228 
00229 /* Fix up some data or instructions after we find out the value of a symbol
00230    that they reference.  Knows about order of bytes in address.  */
00231 
00232 void
00233 md_apply_fix (fixS *fixP,
00234               valueT * valP,
00235               segT seg ATTRIBUTE_UNUSED)
00236 {
00237   valueT code;
00238   valueT mask;
00239   valueT val = * valP;
00240   char *buf;
00241   int shift;
00242   int size;
00243 
00244   buf = fixP->fx_where + fixP->fx_frag->fr_literal;
00245   size = fixP->fx_size;
00246   code = md_chars_to_number ((unsigned char *) buf, size);
00247 
00248   switch (fixP->fx_r_type)
00249     {
00250     case BFD_RELOC_16:
00251     case BFD_RELOC_16_PCREL:
00252       mask = 0xffff;
00253       shift = 0;
00254       break;
00255     case BFD_RELOC_PDP11_DISP_8_PCREL:
00256       mask = 0x00ff;
00257       shift = 1;
00258       break;
00259     case BFD_RELOC_PDP11_DISP_6_PCREL:
00260       mask = 0x003f;
00261       shift = 1;
00262       val = -val;
00263       break;
00264     default:
00265       BAD_CASE (fixP->fx_r_type);
00266     }
00267 
00268   if (fixP->fx_addsy != NULL)
00269     val += symbol_get_bfdsym (fixP->fx_addsy)->section->vma;
00270     /* *value += fixP->fx_addsy->bsym->section->vma; */
00271 
00272   code &= ~mask;
00273   code |= (val >> shift) & mask;
00274   number_to_chars_littleendian (buf, code, size);
00275 
00276   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
00277     fixP->fx_done = 1;
00278 }
00279 
00280 long
00281 md_chars_to_number (con, nbytes)
00282      unsigned char con[];   /* Low order byte 1st.  */
00283      int nbytes;            /* Number of bytes in the input.  */
00284 {
00285   /* On a PDP-11, 0x1234 is stored as "\x12\x34", and
00286      0x12345678 is stored as "\x56\x78\x12\x34". It's
00287      anyones guess what 0x123456 would be stored like.  */
00288   switch (nbytes)
00289     {
00290     case 0:
00291       return 0;
00292     case 1:
00293       return con[0];
00294     case 2:
00295       return (con[1] << BITS_PER_CHAR) | con[0];
00296     case 4:
00297       return
00298        (((con[1] << BITS_PER_CHAR) | con[0]) << (2 * BITS_PER_CHAR))
00299        |((con[3] << BITS_PER_CHAR) | con[2]);
00300     default:
00301       BAD_CASE (nbytes);
00302       return 0;
00303     }
00304 }
00305 
00306 static char *
00307 skip_whitespace (char *str)
00308 {
00309   while (*str == ' ' || *str == '\t')
00310     str++;
00311   return str;
00312 }
00313 
00314 static char *
00315 find_whitespace (char *str)
00316 {
00317   while (*str != ' ' && *str != '\t' && *str != 0)
00318     str++;
00319   return str;
00320 }
00321 
00322 static char *
00323 parse_reg (char *str, struct pdp11_code *operand)
00324 {
00325   str = skip_whitespace (str);
00326   if (TOLOWER (*str) == 'r')
00327     {
00328       str++;
00329       switch (*str)
00330        {
00331        case '0': case '1': case '2': case '3':
00332        case '4': case '5': case '6': case '7':
00333          operand->code = *str - '0';
00334          str++;
00335          break;
00336        default:
00337          operand->error = "Bad register name";
00338          return str - 1;
00339        }
00340     }
00341   else if (strncmp (str, "sp", 2) == 0
00342           || strncmp (str, "SP", 2) == 0)
00343     {
00344       operand->code = 6;
00345       str += 2;
00346     }
00347   else if (strncmp (str, "pc", 2) == 0
00348           || strncmp (str, "PC", 2) == 0)
00349     {
00350       operand->code = 7;
00351       str += 2;
00352     }
00353   else
00354     {
00355       operand->error = "Bad register name";
00356       return str;
00357     }
00358 
00359   return str;
00360 }
00361 
00362 static char *
00363 parse_ac5 (char *str, struct pdp11_code *operand)
00364 {
00365   str = skip_whitespace (str);
00366   if (strncmp (str, "fr", 2) == 0
00367       || strncmp (str, "FR", 2) == 0
00368       || strncmp (str, "ac", 2) == 0
00369       || strncmp (str, "AC", 2) == 0)
00370     {
00371       str += 2;
00372       switch (*str)
00373        {
00374        case '0': case '1': case '2': case '3':
00375         case '4': case '5':
00376          operand->code = *str - '0';
00377          str++;
00378          break;
00379        default:
00380          operand->error = "Bad register name";
00381          return str - 2;
00382        }
00383     }
00384   else
00385     {
00386       operand->error = "Bad register name";
00387       return str;
00388     }
00389 
00390   return str;
00391 }
00392 
00393 static char *
00394 parse_ac (char *str, struct pdp11_code *operand)
00395 {
00396   str = parse_ac5 (str, operand);
00397   if (!operand->error && operand->code > 3)
00398     {
00399          operand->error = "Bad register name";
00400          return str - 3;
00401     }
00402 
00403   return str;
00404 }
00405 
00406 static char *
00407 parse_expression (char *str, struct pdp11_code *operand)
00408 {
00409   char *save_input_line_pointer;
00410   segT seg;
00411 
00412   save_input_line_pointer = input_line_pointer;
00413   input_line_pointer = str;
00414   seg = expression (&operand->reloc.exp);
00415   if (seg == NULL)
00416     {
00417       input_line_pointer = save_input_line_pointer;
00418       operand->error = "Error in expression";
00419       return str;
00420     }
00421 
00422   str = input_line_pointer;
00423   input_line_pointer = save_input_line_pointer;
00424 
00425   operand->reloc.pc_rel = 0;
00426 
00427   return str;
00428 }
00429 
00430 static char *
00431 parse_op_no_deferred (char *str, struct pdp11_code *operand)
00432 {
00433   LITTLENUM_TYPE literal_float[2];
00434 
00435   str = skip_whitespace (str);
00436 
00437   switch (*str)
00438     {
00439     case '(':                      /* (rn) and (rn)+ */
00440       str = parse_reg (str + 1, operand);
00441       if (operand->error)
00442        return str;
00443       str = skip_whitespace (str);
00444       if (*str != ')')
00445        {
00446          operand->error = "Missing ')'";
00447          return str;
00448        }
00449       str++;
00450       if (*str == '+')
00451        {
00452          operand->code |= 020;
00453          str++;
00454        }
00455       else
00456        {
00457          operand->code |= 010;
00458        }
00459       break;
00460 
00461       /* Immediate.  */
00462     case '#':
00463     case '$':
00464       str = parse_expression (str + 1, operand);
00465       if (operand->error)
00466        return str;
00467       operand->additional = TRUE;
00468       operand->word = operand->reloc.exp.X_add_number;
00469       switch (operand->reloc.exp.X_op)
00470        {
00471        case O_constant:
00472          break;
00473        case O_symbol:
00474        case O_add:
00475        case O_subtract:
00476          operand->reloc.type = BFD_RELOC_16;
00477          operand->reloc.pc_rel = 0;
00478          break;
00479         case O_big:
00480           if (operand->reloc.exp.X_add_number > 0)
00481             {
00482               operand->error = "Error in expression";
00483               break;
00484             }
00485           /* It's a floating literal...  */
00486           know (operand->reloc.exp.X_add_number < 0);
00487           flonum_gen2vax ('f', &generic_floating_point_number, literal_float);
00488           operand->word = literal_float[0];
00489           if (literal_float[1] != 0)
00490             as_warn (_("Low order bits truncated in immediate float operand"));
00491           break;
00492        default:
00493          operand->error = "Error in expression";
00494          break;
00495        }
00496       operand->code = 027;
00497       break;
00498 
00499       /* label, d(rn), -(rn)  */
00500     default:
00501       {
00502        char *old = str;
00503 
00504        if (strncmp (str, "-(", 2) == 0)   /* -(rn) */
00505          {
00506            str = parse_reg (str + 2, operand);
00507            if (operand->error)
00508              return str;
00509            str = skip_whitespace (str);
00510            if (*str != ')')
00511              {
00512               operand->error = "Missing ')'";
00513               return str;
00514              }
00515            operand->code |= 040;
00516            str++;
00517            break;
00518          }
00519 
00520        str = parse_expression (str, operand);
00521        if (operand->error)
00522          return str;
00523 
00524        str = skip_whitespace (str);
00525 
00526        if (*str != '(')
00527          {
00528            if (operand->reloc.exp.X_op != O_symbol)
00529              {
00530               operand->error = "Label expected";
00531               return old;
00532              }
00533            operand->code = 067;
00534            operand->additional = 1;
00535            operand->word = 0;
00536            operand->reloc.type = BFD_RELOC_16_PCREL;
00537            operand->reloc.pc_rel = 1;
00538            break;
00539          }
00540 
00541        /* d(rn) */
00542        str++;
00543        str = parse_reg (str, operand);
00544        if (operand->error)
00545          return str;
00546 
00547        str = skip_whitespace (str);
00548 
00549        if (*str != ')')
00550          {
00551            operand->error = "Missing ')'";
00552            return str;
00553          }
00554 
00555        str++;
00556        operand->additional = TRUE;
00557        operand->code |= 060;
00558        switch (operand->reloc.exp.X_op)
00559          {
00560          case O_symbol:
00561            operand->word = 0;
00562            operand->reloc.pc_rel = 1;
00563            break;
00564          case O_constant:
00565            if ((operand->code & 7) == 7)
00566              {
00567               operand->reloc.pc_rel = 1;
00568               operand->word = operand->reloc.exp.X_add_number;
00569              }
00570            else
00571              operand->word = operand->reloc.exp.X_add_number;
00572 
00573            break;
00574          default:
00575            BAD_CASE (operand->reloc.exp.X_op);
00576          }
00577        break;
00578       }
00579     }
00580 
00581   return str;
00582 }
00583 
00584 static char *
00585 parse_op_noreg (char *str, struct pdp11_code *operand)
00586 {
00587   str = skip_whitespace (str);
00588   operand->error = NULL;
00589 
00590   if (*str == '@' || *str == '*')
00591     {
00592       str = parse_op_no_deferred (str + 1, operand);
00593       if (operand->error)
00594        return str;
00595       operand->code |= 010;
00596     }
00597   else
00598     str = parse_op_no_deferred (str, operand);
00599 
00600   return str;
00601 }
00602 
00603 static char *
00604 parse_op (char *str, struct pdp11_code *operand)
00605 {
00606   str = skip_whitespace (str);
00607 
00608   str = parse_reg (str, operand);
00609   if (!operand->error)
00610     return str;
00611 
00612   operand->error = NULL;
00613   parse_ac5 (str, operand);
00614   if (!operand->error)
00615     {
00616       operand->error = "Float AC not legal as integer operand";
00617       return str;
00618     }
00619 
00620   return parse_op_noreg (str, operand);
00621 }
00622 
00623 static char *
00624 parse_fop (char *str, struct pdp11_code *operand)
00625 {
00626   str = skip_whitespace (str);
00627 
00628   str = parse_ac5 (str, operand);
00629   if (!operand->error)
00630     return str;
00631 
00632   operand->error = NULL;
00633   parse_reg (str, operand);
00634   if (!operand->error)
00635     {
00636       operand->error = "General register not legal as float operand";
00637       return str;
00638     }
00639 
00640   return parse_op_noreg (str, operand);
00641 }
00642 
00643 static char *
00644 parse_separator (char *str, int *error)
00645 {
00646   str = skip_whitespace (str);
00647   *error = (*str != ',');
00648   if (!*error)
00649     str++;
00650   return str;
00651 }
00652 
00653 void
00654 md_assemble (char *instruction_string)
00655 {
00656   const struct pdp11_opcode *op;
00657   struct pdp11_code insn, op1, op2;
00658   int error;
00659   int size;
00660   char *err = NULL;
00661   char *str;
00662   char *p;
00663   char c;
00664 
00665   str = skip_whitespace (instruction_string);
00666   p = find_whitespace (str);
00667   if (p - str == 0)
00668     {
00669       as_bad ("No instruction found");
00670       return;
00671     }
00672 
00673   c = *p;
00674   *p = '\0';
00675   op = (struct pdp11_opcode *)hash_find (insn_hash, str);
00676   *p = c;
00677   if (op == 0)
00678     {
00679       as_bad (_("Unknown instruction '%s'"), str);
00680       return;
00681     }
00682 
00683   if (!pdp11_extension[op->extension])
00684     {
00685       as_warn ("Unsupported instruction set extension: %s", op->name);
00686       return;
00687     }
00688 
00689   insn.error = NULL;
00690   insn.code = op->opcode;
00691   insn.reloc.type = BFD_RELOC_NONE;
00692   op1.error = NULL;
00693   op1.additional = FALSE;
00694   op1.reloc.type = BFD_RELOC_NONE;
00695   op2.error = NULL;
00696   op2.additional = FALSE;
00697   op2.reloc.type = BFD_RELOC_NONE;
00698 
00699   str = p;
00700   size = 2;
00701 
00702   switch (op->type)
00703     {
00704     case PDP11_OPCODE_NO_OPS:
00705       str = skip_whitespace (str);
00706       if (*str == 0)
00707        str = "";
00708       break;
00709 
00710     case PDP11_OPCODE_IMM3:
00711     case PDP11_OPCODE_IMM6:
00712     case PDP11_OPCODE_IMM8:
00713       str = skip_whitespace (str);
00714       if (*str == '#' || *str == '$')
00715        str++;
00716       str = parse_expression (str, &op1);
00717       if (op1.error)
00718        break;
00719       if (op1.reloc.exp.X_op != O_constant || op1.reloc.type != BFD_RELOC_NONE)
00720        {
00721          op1.error = "operand is not an absolute constant";
00722          break;
00723        }
00724       switch (op->type)
00725        {
00726        case PDP11_OPCODE_IMM3:
00727          if (op1.reloc.exp.X_add_number & ~7)
00728            {
00729              op1.error = "3-bit immediate out of range";
00730              break;
00731            }
00732          break;
00733        case PDP11_OPCODE_IMM6:
00734          if (op1.reloc.exp.X_add_number & ~0x3f)
00735            {
00736              op1.error = "6-bit immediate out of range";
00737              break;
00738            }
00739          break;
00740        case PDP11_OPCODE_IMM8:
00741          if (op1.reloc.exp.X_add_number & ~0xff)
00742            {
00743              op1.error = "8-bit immediate out of range";
00744              break;
00745            }
00746          break;
00747        }
00748       insn.code |= op1.reloc.exp.X_add_number;
00749       break;
00750 
00751     case PDP11_OPCODE_DISPL:
00752       {
00753        char *new;
00754        new = parse_expression (str, &op1);
00755        op1.code = 0;
00756        op1.reloc.pc_rel = 1;
00757        op1.reloc.type = BFD_RELOC_PDP11_DISP_8_PCREL;
00758        if (op1.reloc.exp.X_op != O_symbol)
00759          {
00760            op1.error = "Symbol expected";
00761            break;
00762          }
00763        if (op1.code & ~0xff)
00764          {
00765            err = "8-bit displacement out of range";
00766            break;
00767          }
00768        str = new;
00769        insn.code |= op1.code;
00770        insn.reloc = op1.reloc;
00771       }
00772       break;
00773 
00774     case PDP11_OPCODE_REG:
00775       str = parse_reg (str, &op1);
00776       if (op1.error)
00777        break;
00778       insn.code |= op1.code;
00779       break;
00780 
00781     case PDP11_OPCODE_OP:
00782       str = parse_op (str, &op1);
00783       if (op1.error)
00784        break;
00785       insn.code |= op1.code;
00786       if (op1.additional)
00787        size += 2;
00788       break;
00789 
00790     case PDP11_OPCODE_FOP:
00791       str = parse_fop (str, &op1);
00792       if (op1.error)
00793        break;
00794       insn.code |= op1.code;
00795       if (op1.additional)
00796        size += 2;
00797       break;
00798 
00799     case PDP11_OPCODE_REG_OP:
00800       str = parse_reg (str, &op2);
00801       if (op2.error)
00802        break;
00803       insn.code |= op2.code << 6;
00804       str = parse_separator (str, &error);
00805       if (error)
00806        {
00807          op2.error = "Missing ','";
00808          break;
00809        }
00810       str = parse_op (str, &op1);
00811       if (op1.error)
00812        break;
00813       insn.code |= op1.code;
00814       if (op1.additional)
00815        size += 2;
00816       break;
00817 
00818     case PDP11_OPCODE_REG_OP_REV:
00819       str = parse_op (str, &op1);
00820       if (op1.error)
00821        break;
00822       insn.code |= op1.code;
00823       if (op1.additional)
00824        size += 2;
00825       str = parse_separator (str, &error);
00826       if (error)
00827        {
00828          op2.error = "Missing ','";
00829          break;
00830        }
00831       str = parse_reg (str, &op2);
00832       if (op2.error)
00833        break;
00834       insn.code |= op2.code << 6;
00835       break;
00836 
00837     case PDP11_OPCODE_AC_FOP:
00838       str = parse_ac (str, &op2);
00839       if (op2.error)
00840        break;
00841       insn.code |= op2.code << 6;
00842       str = parse_separator (str, &error);
00843       if (error)
00844        {
00845          op1.error = "Missing ','";
00846          break;
00847        }
00848       str = parse_fop (str, &op1);
00849       if (op1.error)
00850        break;
00851       insn.code |= op1.code;
00852       if (op1.additional)
00853        size += 2;
00854       break;
00855 
00856     case PDP11_OPCODE_FOP_AC:
00857       str = parse_fop (str, &op1);
00858       if (op1.error)
00859        break;
00860       insn.code |= op1.code;
00861       if (op1.additional)
00862        size += 2;
00863       str = parse_separator (str, &error);
00864       if (error)
00865        {
00866          op1.error = "Missing ','";
00867          break;
00868        }
00869       str = parse_ac (str, &op2);
00870       if (op2.error)
00871        break;
00872       insn.code |= op2.code << 6;
00873       break;
00874 
00875     case PDP11_OPCODE_AC_OP:
00876       str = parse_ac (str, &op2);
00877       if (op2.error)
00878        break;
00879       insn.code |= op2.code << 6;
00880       str = parse_separator (str, &error);
00881       if (error)
00882        {
00883          op1.error = "Missing ','";
00884          break;
00885        }
00886       str = parse_op (str, &op1);
00887       if (op1.error)
00888        break;
00889       insn.code |= op1.code;
00890       if (op1.additional)
00891        size += 2;
00892       break;
00893 
00894     case PDP11_OPCODE_OP_AC:
00895       str = parse_op (str, &op1);
00896       if (op1.error)
00897        break;
00898       insn.code |= op1.code;
00899       if (op1.additional)
00900        size += 2;
00901       str = parse_separator (str, &error);
00902       if (error)
00903        {
00904          op1.error = "Missing ','";
00905          break;
00906        }
00907       str = parse_ac (str, &op2);
00908       if (op2.error)
00909        break;
00910       insn.code |= op2.code << 6;
00911       break;
00912 
00913     case PDP11_OPCODE_OP_OP:
00914       str = parse_op (str, &op1);
00915       if (op1.error)
00916        break;
00917       insn.code |= op1.code << 6;
00918       if (op1.additional)
00919        size += 2;
00920       str = parse_separator (str, &error);
00921       if (error)
00922        {
00923          op2.error = "Missing ','";
00924          break;
00925        }
00926       str = parse_op (str, &op2);
00927       if (op2.error)
00928        break;
00929       insn.code |= op2.code;
00930       if (op2.additional)
00931        size += 2;
00932       break;
00933 
00934     case PDP11_OPCODE_REG_DISPL:
00935       {
00936        char *new;
00937        str = parse_reg (str, &op2);
00938        if (op2.error)
00939          break;
00940        insn.code |= op2.code << 6;
00941        str = parse_separator (str, &error);
00942        if (error)
00943          {
00944            op1.error = "Missing ','";
00945            break;
00946          }
00947        new = parse_expression (str, &op1);
00948        op1.code = 0;
00949        op1.reloc.pc_rel = 1;
00950        op1.reloc.type = BFD_RELOC_PDP11_DISP_6_PCREL;
00951        if (op1.reloc.exp.X_op != O_symbol)
00952          {
00953            op1.error = "Symbol expected";
00954            break;
00955          }
00956        if (op1.code & ~0x3f)
00957          {
00958            err = "6-bit displacement out of range";
00959            break;
00960          }
00961        str = new;
00962        insn.code |= op1.code;
00963        insn.reloc = op1.reloc;
00964       }
00965       break;
00966 
00967     default:
00968       BAD_CASE (op->type);
00969     }
00970 
00971   if (op1.error)
00972     err = op1.error;
00973   else if (op2.error)
00974     err = op2.error;
00975   else
00976     {
00977       str = skip_whitespace (str);
00978       if (*str)
00979        err = "Too many operands";
00980     }
00981 
00982   {
00983     char *to = NULL;
00984 
00985     if (err)
00986       {
00987        as_bad (err);
00988        return;
00989       }
00990 
00991     to = frag_more (size);
00992 
00993     md_number_to_chars (to, insn.code, 2);
00994     if (insn.reloc.type != BFD_RELOC_NONE)
00995       fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
00996                  &insn.reloc.exp, insn.reloc.pc_rel, insn.reloc.type);
00997     to += 2;
00998 
00999     if (op1.additional)
01000       {
01001        md_number_to_chars (to, op1.word, 2);
01002        if (op1.reloc.type != BFD_RELOC_NONE)
01003          fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
01004                      &op1.reloc.exp, op1.reloc.pc_rel, op1.reloc.type);
01005        to += 2;
01006       }
01007 
01008     if (op2.additional)
01009       {
01010        md_number_to_chars (to, op2.word, 2);
01011        if (op2.reloc.type != BFD_RELOC_NONE)
01012          fix_new_exp (frag_now, to - frag_now->fr_literal, 2,
01013                      &op2.reloc.exp, op2.reloc.pc_rel, op2.reloc.type);
01014       }
01015   }
01016 }
01017 
01018 int
01019 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
01020                             segT segment ATTRIBUTE_UNUSED)
01021 {
01022   return 0;
01023 }
01024 
01025 void
01026 md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
01027                segT seg ATTRIBUTE_UNUSED,
01028                fragS *fragP ATTRIBUTE_UNUSED)
01029 {
01030 }
01031 
01032 int md_short_jump_size = 2;
01033 int md_long_jump_size = 4;
01034 
01035 void
01036 md_create_short_jump (char *ptr ATTRIBUTE_UNUSED,
01037                     addressT from_addr ATTRIBUTE_UNUSED,
01038                     addressT to_addr ATTRIBUTE_UNUSED,
01039                     fragS *frag ATTRIBUTE_UNUSED,
01040                     symbolS *to_symbol ATTRIBUTE_UNUSED)
01041 {
01042 }
01043 
01044 void
01045 md_create_long_jump (char *ptr ATTRIBUTE_UNUSED,
01046                    addressT from_addr ATTRIBUTE_UNUSED,
01047                    addressT to_addr ATTRIBUTE_UNUSED,
01048                    fragS *frag ATTRIBUTE_UNUSED,
01049                    symbolS *to_symbol ATTRIBUTE_UNUSED)
01050 {
01051 }
01052 
01053 static int
01054 set_cpu_model (char *arg)
01055 {
01056   char buf[4];
01057   char *model = buf;
01058 
01059   if (arg[0] == 'k')
01060     arg++;
01061 
01062   *model++ = *arg++;
01063 
01064   if (strchr ("abdx", model[-1]) == NULL)
01065     return 0;
01066 
01067   if (model[-1] == 'd')
01068     {
01069       if (arg[0] == 'f' || arg[0] == 'j')
01070        model[-1] = *arg++;
01071     }
01072   else if (model[-1] == 'x')
01073     {
01074       if (arg[0] == 't')
01075        model[-1] = *arg++;
01076     }
01077 
01078   if (arg[0] == '-')
01079     arg++;
01080 
01081   if (strncmp (arg, "11", 2) != 0)
01082     return 0;
01083   arg += 2;
01084 
01085   if (arg[0] == '-')
01086     {
01087       if (*++arg == 0)
01088        return 0;
01089     }
01090 
01091   /* Allow up to two revision letters.  */
01092   if (arg[0] != 0)
01093     *model++ = *arg++;
01094   if (arg[0] != 0)
01095     *model++ = *arg++;
01096 
01097   *model++ = 0;
01098 
01099   set_option ("no-extensions");
01100 
01101   /* KA11 (11/15/20).  */
01102   if (strncmp (buf, "a", 1) == 0)
01103     return 1; /* No extensions.  */
01104 
01105   /* KB11 (11/45/50/55/70).  */
01106   else if (strncmp (buf, "b", 1) == 0)
01107     return set_option ("eis") && set_option ("spl");
01108 
01109   /* KD11-A (11/35/40).  */
01110   else if (strncmp (buf, "da", 2) == 0)
01111     return set_option ("limited-eis");
01112 
01113   /* KD11-B (11/05/10).  */
01114   else if (strncmp (buf, "db", 2) == 0
01115           /* KD11-D (11/04).  */
01116           || strncmp (buf, "dd", 2) == 0)
01117     return 1; /* no extensions */
01118 
01119   /* KD11-E (11/34).  */
01120   else if (strncmp (buf, "de", 2) == 0)
01121     return set_option ("eis") && set_option ("mxps");
01122 
01123   /* KD11-F (11/03).  */
01124   else if (strncmp (buf, "df", 2) == 0
01125           /* KD11-H (11/03).  */
01126           || strncmp (buf, "dh", 2) == 0
01127           /* KD11-Q (11/03).  */
01128           || strncmp (buf, "dq", 2) == 0)
01129     return set_option ("limited-eis") && set_option ("mxps");
01130 
01131   /* KD11-K (11/60).  */
01132   else if (strncmp (buf, "dk", 2) == 0)
01133     return set_option ("eis")
01134       && set_option ("mxps")
01135       && set_option ("ucode");
01136 
01137   /* KD11-Z (11/44).  */
01138   else if (strncmp (buf, "dz", 2) == 0)
01139     return set_option ("csm")
01140       && set_option ("eis")
01141       && set_option ("mfpt")
01142       && set_option ("mxps")
01143       && set_option ("spl");
01144 
01145   /* F11 (11/23/24).  */
01146   else if (strncmp (buf, "f", 1) == 0)
01147     return set_option ("eis")
01148       && set_option ("mfpt")
01149       && set_option ("mxps");
01150 
01151   /* J11 (11/53/73/83/84/93/94).  */
01152   else if (strncmp (buf, "j", 1) == 0)
01153     return set_option ("csm")
01154       && set_option ("eis")
01155       && set_option ("mfpt")
01156       && set_option ("multiproc")
01157       && set_option ("mxps")
01158       && set_option ("spl");
01159 
01160   /* T11 (11/21).  */
01161   else if (strncmp (buf, "t", 1) == 0)
01162     return set_option ("limited-eis")
01163       && set_option ("mxps");
01164 
01165   else
01166     return 0;
01167 }
01168 
01169 static int
01170 set_machine_model (char *arg)
01171 {
01172   if (strncmp (arg, "pdp-11/", 7) != 0
01173       && strncmp (arg, "pdp11/", 6) != 0
01174       && strncmp (arg, "11/", 3) != 0)
01175     return 0;
01176 
01177   if (strncmp (arg, "pdp", 3) == 0)
01178     arg += 3;
01179   if (arg[0] == '-')
01180     arg++;
01181   if (strncmp (arg, "11/", 3) == 0)
01182     arg += 3;
01183 
01184   if (strcmp (arg, "03") == 0)
01185     return set_cpu_model ("kd11f");
01186 
01187   else if (strcmp (arg, "04") == 0)
01188     return set_cpu_model ("kd11d");
01189 
01190   else if (strcmp (arg, "05") == 0
01191           || strcmp (arg, "10") == 0)
01192     return set_cpu_model ("kd11b");
01193 
01194   else if (strcmp (arg, "15") == 0
01195           || strcmp (arg, "20") == 0)
01196     return set_cpu_model ("ka11");
01197 
01198   else if (strcmp (arg, "21") == 0)
01199     return set_cpu_model ("t11");
01200 
01201   else if (strcmp (arg, "23") == 0
01202           || strcmp (arg, "24") == 0)
01203     return set_cpu_model ("f11");
01204 
01205   else if (strcmp (arg, "34") == 0
01206           || strcmp (arg, "34a") == 0)
01207     return set_cpu_model ("kd11e");
01208 
01209   else if (strcmp (arg, "35") == 0
01210           || strcmp (arg, "40") == 0)
01211     return set_cpu_model ("kd11da");
01212 
01213   else if (strcmp (arg, "44") == 0)
01214     return set_cpu_model ("kd11dz");
01215 
01216   else if (strcmp (arg, "45") == 0
01217           || strcmp (arg, "50") == 0
01218           || strcmp (arg, "55") == 0
01219           || strcmp (arg, "70") == 0)
01220     return set_cpu_model ("kb11");
01221 
01222   else if (strcmp (arg, "60") == 0)
01223     return set_cpu_model ("kd11k");
01224 
01225   else if (strcmp (arg, "53") == 0
01226           || strcmp (arg, "73") == 0
01227           || strcmp (arg, "83") == 0
01228           || strcmp (arg, "84") == 0
01229           || strcmp (arg, "93") == 0
01230           || strcmp (arg, "94") == 0)
01231     return set_cpu_model ("j11")
01232       && set_option ("fpp");
01233 
01234   else
01235     return 0;
01236 }
01237 
01238 const char *md_shortopts = "m:";
01239 
01240 struct option md_longopts[] =
01241 {
01242 #define OPTION_CPU 257
01243   { "cpu", required_argument, NULL, OPTION_CPU },
01244 #define OPTION_MACHINE 258
01245   { "machine", required_argument, NULL, OPTION_MACHINE },
01246 #define OPTION_PIC 259
01247   { "pic", no_argument, NULL, OPTION_PIC },
01248   { NULL, no_argument, NULL, 0 }
01249 };
01250 
01251 size_t md_longopts_size = sizeof (md_longopts);
01252 
01253 /* Invocation line includes a switch not recognized by the base assembler.
01254    See if it's a processor-specific option.  */
01255 
01256 int
01257 md_parse_option (int c, char *arg)
01258 {
01259   init_defaults ();
01260 
01261   switch (c)
01262     {
01263     case 'm':
01264       if (set_option (arg))
01265        return 1;
01266       if (set_cpu_model (arg))
01267        return 1;
01268       if (set_machine_model (arg))
01269        return 1;
01270       break;
01271 
01272     case OPTION_CPU:
01273       if (set_cpu_model (arg))
01274        return 1;
01275       break;
01276 
01277     case OPTION_MACHINE:
01278       if (set_machine_model (arg))
01279        return 1;
01280       break;
01281 
01282     case OPTION_PIC:
01283       if (set_option ("pic"))
01284        return 1;
01285       break;
01286 
01287     default:
01288       break;
01289     }
01290 
01291   return 0;
01292 }
01293 
01294 void
01295 md_show_usage (FILE *stream)
01296 {
01297   fprintf (stream, "\
01298 \n\
01299 PDP-11 instruction set extentions:\n\
01300 \n\
01301 -m(no-)cis           allow (disallow) commersial instruction set\n\
01302 -m(no-)csm           allow (disallow) CSM instruction\n\
01303 -m(no-)eis           allow (disallow) full extended instruction set\n\
01304 -m(no-)fis           allow (disallow) KEV11 floating-point instructions\n\
01305 -m(no-)fpp           allow (disallow) FP-11 floating-point instructions\n\
01306 -m(no-)fpu           allow (disallow) FP-11 floating-point instructions\n\
01307 -m(no-)limited-eis   allow (disallow) limited extended instruction set\n\
01308 -m(no-)mfpt          allow (disallow) processor type instruction\n\
01309 -m(no-)multiproc     allow (disallow) multiprocessor instructions\n\
01310 -m(no-)mxps          allow (disallow) processor status instructions\n\
01311 -m(no-)spl           allow (disallow) SPL instruction\n\
01312 -m(no-)ucode         allow (disallow) microcode instructions\n\
01313 -mall-extensions     allow all instruction set extensions\n\
01314                      (this is the default)\n\
01315 -mno-extentions             disallow all instruction set extensions\n\
01316 -pic                 generate position-indepenent code\n\
01317 \n\
01318 PDP-11 CPU model options:\n\
01319 \n\
01320 -mka11*                     KA11 CPU.  base line instruction set only\n\
01321 -mkb11*                     KB11 CPU.  enable full EIS and SPL\n\
01322 -mkd11a*             KD11-A CPU.  enable limited EIS\n\
01323 -mkd11b*             KD11-B CPU.  base line instruction set only\n\
01324 -mkd11d*             KD11-D CPU.  base line instruction set only\n\
01325 -mkd11e*             KD11-E CPU.  enable full EIS, MTPS, and MFPS\n\
01326 -mkd11f*             KD11-F CPU.  enable limited EIS, MTPS, and MFPS\n\
01327 -mkd11h*             KD11-H CPU.  enable limited EIS, MTPS, and MFPS\n\
01328 -mkd11q*             KD11-Q CPU.  enable limited EIS, MTPS, and MFPS\n\
01329 -mkd11k*             KD11-K CPU.  enable full EIS, MTPS, MFPS, LDUB, MED,\n\
01330                      XFC, and MFPT\n\
01331 -mkd11z*             KD11-Z CPU.  enable full EIS, MTPS, MFPS, MFPT, SPL,\n\
01332                      and CSM\n\
01333 -mf11*               F11 CPU.  enable full EIS, MFPS, MTPS, and MFPT\n\
01334 -mj11*               J11 CPU.  enable full EIS, MTPS, MFPS, MFPT, SPL,\n\
01335                      CSM, TSTSET, and WRTLCK\n\
01336 -mt11*               T11 CPU.  enable limited EIS, MTPS, and MFPS\n\
01337 \n\
01338 PDP-11 machine model options:\n\
01339 \n\
01340 -m11/03                     same as -mkd11f\n\
01341 -m11/04                     same as -mkd11d\n\
01342 -m11/05                     same as -mkd11b\n\
01343 -m11/10                     same as -mkd11b\n\
01344 -m11/15                     same as -mka11\n\
01345 -m11/20                     same as -mka11\n\
01346 -m11/21                     same as -mt11\n\
01347 -m11/23                     same as -mf11\n\
01348 -m11/24                     same as -mf11\n\
01349 -m11/34                     same as -mkd11e\n\
01350 -m11/34a             same as -mkd11e -mfpp\n\
01351 -m11/35                     same as -mkd11a\n\
01352 -m11/40                     same as -mkd11a\n\
01353 -m11/44                     same as -mkd11z\n\
01354 -m11/45                     same as -mkb11\n\
01355 -m11/50                     same as -mkb11\n\
01356 -m11/53                     same as -mj11\n\
01357 -m11/55                     same as -mkb11\n\
01358 -m11/60                     same as -mkd11k\n\
01359 -m11/70                     same as -mkb11\n\
01360 -m11/73                     same as -mj11\n\
01361 -m11/83                     same as -mj11\n\
01362 -m11/84                     same as -mj11\n\
01363 -m11/93                     same as -mj11\n\
01364 -m11/94                     same as -mj11\n\
01365 ");
01366 }
01367 
01368 symbolS *
01369 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
01370 {
01371   return 0;
01372 }
01373 
01374 valueT
01375 md_section_align (segT segment ATTRIBUTE_UNUSED,
01376                 valueT size)
01377 {
01378   return (size + 1) & ~1;
01379 }
01380 
01381 long
01382 md_pcrel_from (fixS *fixP)
01383 {
01384   return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
01385 }
01386 
01387 /* Translate internal representation of relocation info to BFD target
01388    format.  */
01389 
01390 arelent *
01391 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
01392              fixS *fixp)
01393 {
01394   arelent *reloc;
01395   bfd_reloc_code_real_type code;
01396 
01397   reloc = xmalloc (sizeof (* reloc));
01398 
01399   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
01400   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
01401   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
01402 
01403   /* This is taken account for in md_apply_fix().  */
01404   reloc->addend = -symbol_get_bfdsym (fixp->fx_addsy)->section->vma;
01405 
01406   switch (fixp->fx_r_type)
01407     {
01408     case BFD_RELOC_16:
01409       if (fixp->fx_pcrel)
01410        code = BFD_RELOC_16_PCREL;
01411       else
01412        code = BFD_RELOC_16;
01413       break;
01414 
01415     case BFD_RELOC_16_PCREL:
01416       code = BFD_RELOC_16_PCREL;
01417       break;
01418 
01419     default:
01420       BAD_CASE (fixp->fx_r_type);
01421       return NULL;
01422     }
01423 
01424   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
01425 
01426   if (reloc->howto == NULL)
01427     {
01428       as_bad_where (fixp->fx_file, fixp->fx_line,
01429                   "Can not represent %s relocation in this object file format",
01430                   bfd_get_reloc_code_name (code));
01431       return NULL;
01432     }
01433 
01434   return reloc;
01435 }
01436 
01437 void
01438 pseudo_bss (int c ATTRIBUTE_UNUSED)
01439 {
01440   int temp;
01441 
01442   temp = get_absolute_expression ();
01443   subseg_set (bss_section, temp);
01444   demand_empty_rest_of_line ();
01445 }
01446 
01447 void
01448 pseudo_even (int c ATTRIBUTE_UNUSED)
01449 {
01450   int alignment = 1; /* 2^1 */
01451   frag_align (alignment, 0, 1);
01452   record_alignment (now_seg, alignment);
01453 }