opcodes:
[deliverable/binutils-gdb.git] / gas / config / tc-d10v.c
index 3ec5b8be599ac84868505728926ac08f6d6be1d0..d20ae10475fe73cc779e18c8408c5894702ae307 100644 (file)
@@ -1,6 +1,5 @@
 /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
-
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation.
+   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -37,8 +36,8 @@ int Optimizing = 0;
 
 #define AT_WORD_P(X) ((X)->X_op == O_right_shift \
                      && (X)->X_op_symbol != NULL \
-                     && (X)->X_op_symbol->sy_value.X_op == O_constant \
-                     && (X)->X_op_symbol->sy_value.X_add_number == AT_WORD_RIGHT_SHIFT)
+                     && symbol_constant_p ((X)->X_op_symbol) \
+                     && S_GET_VALUE ((X)->X_op_symbol) == AT_WORD_RIGHT_SHIFT)
 #define AT_WORD_RIGHT_SHIFT 2
 
 
@@ -63,6 +62,8 @@ typedef struct _fixups
 static Fixups FixUps[2];
 static Fixups *fixups;
 
+static int do_not_ignore_hash = 0;
+
 /* True if instruction swapping warnings should be inhibited.  */
 static unsigned char flag_warn_suppress_instructionswap; /* --nowarnswap */
 
@@ -159,7 +160,7 @@ register_name (expressionP)
     {
       expressionP->X_op = O_register;
       /* temporarily store a pointer to the string here */
-      expressionP->X_op_symbol = (struct symbol *)input_line_pointer;
+      expressionP->X_op_symbol = (symbolS *)input_line_pointer;
       expressionP->X_add_number = reg_number;
       input_line_pointer = p;
       return 1;
@@ -195,10 +196,19 @@ check_range (num, bits, flags)
 
   if (flags & OPERAND_SIGNED)
     {
-      max = (1 << (bits - 1))-1; 
-      min = - (1 << (bits - 1));  
-      if (((long)num > max) || ((long)num < min))
-       retval = 1;
+      /* Signed 3-bit integers are restricted to the (-2, 3) range */
+      if (flags & RESTRICTED_NUM3)
+       {
+         if ((long) num < -2 || (long) num > 3)
+           retval = 1;
+       }
+      else
+       {
+         max = (1 << (bits - 1)) - 1; 
+         min = - (1 << (bits - 1));  
+         if (((long) num > max) || ((long) num < min))
+           retval = 1;
+       }
     }
   else
     {
@@ -393,7 +403,8 @@ get_operands (exp)
   char *p = input_line_pointer;
   int numops = 0;
   int post = 0;
-
+  int uses_at = 0;
+  
   while (*p)  
     {
       while (*p == ' ' || *p == '\t' || *p == ',') 
@@ -403,6 +414,8 @@ get_operands (exp)
       
       if (*p == '@') 
        {
+         uses_at = 1;
+         
          p++;
          exp[numops].X_op = O_absent;
          if (*p == '(') 
@@ -437,7 +450,20 @@ get_operands (exp)
       if (!register_name (&exp[numops]))
        {
          /* parse as an expression */
-         expression (&exp[numops]);
+         if (uses_at)
+           {
+             /* Any expression that involves the indirect addressing
+                cannot also involve immediate addressing.  Therefore
+                the use of the hash character is illegal.  */
+             int save = do_not_ignore_hash;
+             do_not_ignore_hash = 1;
+             
+             expression (&exp[numops]);
+             
+             do_not_ignore_hash = save;
+           }
+         else
+           expression (&exp[numops]);
        }
 
       if (strncasecmp (input_line_pointer, "@word", 5) == 0)
@@ -600,7 +626,7 @@ build_insn (opcode, opers, insn)
 
       /* truncate to the proper number of bits */
       if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
-       as_bad(_("operand out of range: %d"),number);
+       as_bad (_("operand out of range: %d"),number);
       number &= 0x7FFFFFFF >> (31 - bits);
       insn = insn | (number << shift);
     }
@@ -713,7 +739,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
 
   if ( (exec_type != 1) && ((opcode1->exec_type & PARONLY)
                        || (opcode2->exec_type & PARONLY)))
-    as_fatal(_("Instruction must be executed in parallel"));
+    as_fatal (_("Instruction must be executed in parallel"));
   
   if ( (opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE))
     as_fatal (_("Long instructions may not be combined."));
@@ -807,7 +833,7 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
       fx = fx->next;
       break;
     default:
-      as_fatal(_("unknown execution type passed to write_2_short()"));
+      as_fatal (_("unknown execution type passed to write_2_short()"));
     }
 
   f = frag_more(4);
@@ -979,16 +1005,16 @@ static unsigned long prev_insn;
 static struct d10v_opcode *prev_opcode = 0;
 static subsegT prev_subseg;
 static segT prev_seg = 0;;
+static int etype = 0;          /* saved extype.  used for multiline instructions */
 
 void
 md_assemble (str)
      char *str;
 {
-  struct d10v_opcode *opcode;
+  struct d10v_opcode * opcode;
   unsigned long insn;
-  int extype=0;                        /* execution type; parallel, etc */
-  static int etype=0;          /* saved extype.  used for multiline instructions */
-  char *str2;
+  int extype = 0;              /* execution type; parallel, etc */
+  char * str2;
 
   if (etype == 0)
     {
@@ -1015,7 +1041,7 @@ md_assemble (str)
          
          /* if two instructions are present and we already have one saved
             then first write it out */
-         d10v_cleanup();
+         d10v_cleanup ();
          
          /* assemble first instruction and save it */
          prev_insn = do_assemble (str, &prev_opcode);
@@ -1047,8 +1073,8 @@ md_assemble (str)
   if (opcode->format & LONG_OPCODE) 
     {
       if (extype) 
-       as_fatal(_("Unable to mix instructions as specified"));
-      d10v_cleanup();
+       as_fatal (_("Unable to mix instructions as specified"));
+      d10v_cleanup ();
       write_long (opcode, insn, fixups);
       prev_opcode = NULL;
       return;
@@ -1065,7 +1091,7 @@ md_assemble (str)
   else
     {
       if (extype) 
-       as_fatal(_("Unable to mix instructions as specified"));
+       as_fatal (_("Unable to mix instructions as specified"));
       /* save off last instruction so it may be packed on next pass */
       prev_opcode = opcode;
       prev_insn = insn;
@@ -1091,26 +1117,26 @@ do_assemble (str, opcode)
   expressionS myops[6];
   unsigned long insn;
 
-  /* Drop leading whitespace */
+  /* Drop leading whitespace */
   while (*str == ' ')
     str++;
 
-  /* find the opcode end */
+  /* Find the opcode end.  */
   for (op_start = op_end = (unsigned char *) (str);
        *op_end
        && nlen < 20
        && !is_end_of_line[*op_end] && *op_end != ' ';
        op_end++)
     {
-      name[nlen] = tolower(op_start[nlen]);
+      name[nlen] = tolower (op_start[nlen]);
       nlen++;
     }
   name[nlen] = 0;
 
   if (nlen == 0)
-    return (-1);
+    return -1;
   
-  /* find the first opcode with the proper name */
+  /* Find the first opcode with the proper name.  */
   *opcode = (struct d10v_opcode *)hash_find (d10v_hash, name);
   if (*opcode == NULL)
       as_fatal (_("unknown opcode: %s"),name);
@@ -1227,7 +1253,7 @@ find_opcode (opcode, myops)
                    value = S_GET_VALUE(myops[opnum].X_add_symbol) - value -
                      (obstack_next_free(&frchain_now->frch_obstack) - frag_now->fr_literal);
                  else
-                   value = S_GET_VALUE(myops[opnum].X_add_symbol);
+                   value += S_GET_VALUE(myops[opnum].X_add_symbol);
 
                  if (AT_WORD_P (&myops[opnum]))
                    {
@@ -1288,7 +1314,7 @@ find_opcode (opcode, myops)
                  ((flags & OPERAND_PLUS)    && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
                  ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
                  ((flags & OPERAND_ATPAR)   && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
-                 ((flags & OPERAND_ATSIGN)  && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
+                 ((flags & OPERAND_ATSIGN)  && ((X_op != O_absent) || ((num != OPERAND_ATSIGN) && (num != OPERAND_ATPAR)))))
                {
                  match = 0;
                  break;
@@ -1351,7 +1377,7 @@ find_opcode (opcode, myops)
     {
       if ((d10v_operands[opcode->operands[i]].flags & OPERAND_EVEN) &&
          (myops[i].X_add_number & 1)) 
-       as_fatal(_("Register number must be EVEN"));
+       as_fatal (_("Register number must be EVEN"));
       if (myops[i].X_op == O_register)
        {
          if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG)) 
@@ -1376,7 +1402,8 @@ tc_gen_reloc (seg, fixp)
 {
   arelent *reloc;
   reloc = (arelent *) xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
+  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
@@ -1529,11 +1556,12 @@ d10v_cleanup ()
   segT seg;
   subsegT subseg;
 
-  if (prev_opcode)
+  if (prev_opcode && etype == 0)
     {
       seg = now_seg;
       subseg = now_subseg;
-      subseg_set (prev_seg, prev_subseg);
+      if (prev_seg)
+       subseg_set (prev_seg, prev_subseg);
       write_1_short (prev_opcode, prev_insn, fixups->next);
       subseg_set (seg, subseg);
       prev_opcode = NULL;
@@ -1594,7 +1622,7 @@ void
 md_operand (expressionP)
      expressionS *expressionP;
 {
-  if (*input_line_pointer == '#')
+  if (*input_line_pointer == '#' && ! do_not_ignore_hash)
     {
       input_line_pointer++;
       expression (expressionP);
This page took 0.026317 seconds and 4 git commands to generate.