* config/tc-m68k.c (m68k_ip): Accept 'B' as a size for an
authorIan Lance Taylor <ian@airs.com>
Fri, 3 Jan 1997 17:14:02 +0000 (17:14 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 3 Jan 1997 17:14:02 +0000 (17:14 +0000)
immediate value.
(md_assemble): If the size is 'B', set fx_signed.
(md_apply_fix_2): Use fx_signed when checking for overflow.

* write.h (struct fix): Add fx_signed field.
* write.c (fix_new_internal): Initialize fx_no_overflow and
fx_signed fields.
(fixup_segment): Use fx_signed when checking for overflow.
* config/obj-coff.c (fixup_segment): Check fx_no_overflow and
fx_signed when checking for overflow.

gas/ChangeLog
gas/config/obj-coff.c
gas/config/tc-m68k.c
gas/write.c

index 90b0c58..fae59ee 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jan  3 12:09:24 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * config/tc-m68k.c (m68k_ip): Accept 'B' as a size for an
+       immediate value.
+       (md_assemble): If the size is 'B', set fx_signed.
+       (md_apply_fix_2): Use fx_signed when checking for overflow.
+
+       * write.h (struct fix): Add fx_signed field.
+       * write.c (fix_new_internal): Initialize fx_no_overflow and
+       fx_signed fields.
+       (fixup_segment): Use fx_signed when checking for overflow.
+       * config/obj-coff.c (fixup_segment): Check fx_no_overflow and
+       fx_signed when checking for overflow.
+
 Thu Jan  2 13:37:29 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        * NOTES, NOTES.config: Removed.  These are rarely, if ever,
index d06212e..695647a 100644 (file)
@@ -1,5 +1,5 @@
 /* coff object file format
-   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
+   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 96, 1997
    Free Software Foundation, Inc.
 
    This file is part of GAS.
@@ -4083,17 +4083,21 @@ fixup_segment (segP, this_segment_type)
 #endif
        }                       /* if pcrel */
 
-      if (!fixP->fx_bit_fixP)
+      if (!fixP->fx_bit_fixP && ! fixP->fx_no_overflow)
        {
 #ifndef TC_M88K
          /* The m88k uses the offset field of the reloc to get around
             this problem.  */
          if ((size == 1
-              && (add_number & ~0xFF)
-              && ((add_number & ~0xFF) != (-1 & ~0xFF)))
+              && ((add_number & ~0xFF)
+                  || (fixP->fx_signed && (add_number & 0x80)))
+              && ((add_number & ~0xFF) != (-1 & ~0xFF)
+                  || (fixP->fx_signed && (add_number & 0x80) == 0)))
              || (size == 2
-                 && (add_number & ~0xFFFF)
-                 && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF))))
+                 && ((add_number & ~0xFFFF)
+                     || (fixP->fx_signed && (add_number & 0x8000)))
+                 && ((add_number & ~0xFFFF) != (-1 & ~0xFFFF)
+                     || (fixP->fx_signed && (add_number & 0x8000) == 0))))
            {
              as_bad_where (fixP->fx_file, fixP->fx_line,
                            "Value of %ld too large for field of %d bytes at 0x%lx",
index 0e40fa3..7204ec3 100644 (file)
@@ -1152,6 +1152,11 @@ m68k_ip (instring)
                           && (opP->disp.exp.X_op != O_constant
                               || ! isbyte (opP->disp.exp.X_add_number)))
                    losing++;
+                 else if (s[1] == 'B'
+                          && ! isvar (&opP->disp)
+                          && (opP->disp.exp.X_op != O_constant
+                              || ! issbyte (opP->disp.exp.X_add_number)))
+                   losing++;
                  else if (s[1] == 'w'
                           && ! isvar (&opP->disp)
                           && (opP->disp.exp.X_op != O_constant
@@ -2289,6 +2294,13 @@ m68k_ip (instring)
                the_ins.reloc[the_ins.nrel - 1].n =
                  (opcode->m_codenum) * 2 + 1;
              break;
+           case 'B':
+             if (!issbyte (tmpreg))
+               opP->error = "out of range";
+             opcode->m_opcode |= tmpreg;
+             if (isvar (&opP->disp))
+               the_ins.reloc[the_ins.nrel - 1].n = opcode->m_codenum * 2 - 1;
+             break;
            case 'w':
              if (!isword (tmpreg))
                opP->error = "out of range";
@@ -3337,6 +3349,8 @@ md_assemble (str)
                              get_reloc_code (n, the_ins.reloc[m].pcrel,
                                              the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
+         if (the_ins.reloc[m].wid == 'B')
+           fixP->fx_signed = 1;
        }
       return;
     }
@@ -3888,7 +3902,7 @@ md_apply_fix_2 (fixP, val)
      like "0xff" for a byte field.  So extend the upper part of the range
      to accept such numbers.  We arbitrarily disallow "-0xff" or "0xff+0xff",
      so that we can do any range checking at all.  */
-  if (!fixP->fx_pcrel)
+  if (! fixP->fx_pcrel && ! fixP->fx_signed)
     upper_limit = upper_limit * 2 + 1;
 
   if ((addressT) val > upper_limit
index 18ebc49..1ec9130 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
+   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 1997
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -162,6 +162,8 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
   fixP->fx_addnumber = 0;
   fixP->fx_tcbit = 0;
   fixP->fx_done = 0;
+  fixP->fx_no_overflow = 0;
+  fixP->fx_signed = 0;
 
 #ifdef TC_FIX_TYPE
   TC_INIT_FIX_DATA(fixP);
@@ -2560,8 +2562,12 @@ fixup_segment (fixP, this_segment_type)
                 the host architecture.  */
              mask <<= size * 4;
              mask <<= size * 4;
-             if ((add_number & mask) != 0
-                 && (add_number & mask) != mask)
+             if (((add_number & mask) != 0
+                  || (fixP->fx_signed
+                      && (add_number & (mask >> 1)) != 0))
+                 && ((add_number & mask) != mask
+                     || (fixP->fx_signed
+                         && (add_number & (mask >> 1)) == 0)))
                {
                  char buf[50], buf2[50];
                  sprint_value (buf, fragP->fr_address + where);