Flag error if absolute constant is too large for an immediate field.
authorJim Wilson <wilson@tuliptree.org>
Fri, 6 Nov 1992 01:59:36 +0000 (01:59 +0000)
committerJim Wilson <wilson@tuliptree.org>
Fri, 6 Nov 1992 01:59:36 +0000 (01:59 +0000)
gas/config/ChangeLog
gas/config/tc-sparc.c

index 398fb274e61de748d5ebe9a3dc2ce2ebcbeb0fa0..0c5aaeb7d0321ecd0db0e540334727497a4ed5cf 100644 (file)
@@ -1,3 +1,9 @@
+Thu Nov  5 17:55:41 1992  Jim Wilson  (wilson@sphagnum.cygnus.com)
+
+       * tc-sparc.c (sparc_ip): Add code to flag error if an absolute
+       constant will not fit in an immediate field.
+       (md_apply_fix, RELOC_BASE13 case): Check for relocation overflow.
+
 Wed Nov  4 07:50:46 1992  Ken Raeburn  (raeburn@cygnus.com)
 
        * obj-coff.c (callj_table): Delete global variable.
index 1f6a67eb4fd6423e90b6f0f8a580d16f19cd8d07..d7fba8f690f59aeff62f0f4e789ce827c7ecc17b 100644 (file)
@@ -525,6 +525,7 @@ char *str;
        unsigned int mask = 0;
        int match = 0;
        int comma = 0;
+       long immediate_max = 0;
        
        for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
            ;
@@ -707,10 +708,12 @@ char *str;
 #ifndef NO_V9
                        case 'I':
                                the_insn.reloc = RELOC_11;
+                               immediate_max = 0x03FF;
                                goto immediate;
                                
                        case 'j':
                                the_insn.reloc = RELOC_10;
+                               immediate_max = 0x01FF;
                                goto immediate;
 
                        case 'k':
@@ -1118,6 +1121,7 @@ char *str;
                                
                        case 'i':   /* 13 bit immediate */
                                the_insn.reloc = RELOC_BASE13;
+                               immediate_max = 0x0FFF;
                                
                                /*FALLTHROUGH */
                                
@@ -1133,13 +1137,13 @@ char *str;
                                                s+=3;
                                                /* start-sanitize-v9 */
 #ifndef NO_V9
-                                       } else if (c == 'h'
+                                       } else if (c == 'u'
                                                   && s[2] == 'h'
                                                   && s[3] == 'i') {
                                                the_insn.reloc = RELOC_HHI22;
                                                s += 4;
                                                
-                                       } else if (c == 'h'
+                                       } else if (c == 'u'
                                                   && s[2] == 'l'
                                                   && s[3] == 'o') {
                                                the_insn.reloc = RELOC_HLO10;
@@ -1185,6 +1189,30 @@ char *str;
                                }
                                (void)getExpression(s);
                                s = expr_end;
+
+                               /* Check for invalid constant values.  Don't
+                                  warn if constant was inside %hi or %lo,
+                                  since these truncate the constant to
+                                  fit.  */
+                               if (immediate_max != 0
+                                   && the_insn.reloc != RELOC_LO10
+                                   && the_insn.reloc != RELOC_HI22
+                                   /* start-sanitize-v9 */
+#ifndef NO_V9
+                                   && the_insn.reloc != RELOC_HLO10
+                                   && the_insn.reloc != RELOC_HHI22
+#endif
+                                   /* end-sanitize-v9 */
+                                   && the_insn.exp.X_add_symbol == 0
+                                   && the_insn.exp.X_subtract_symbol == 0
+                                   && the_insn.exp.X_seg == SEG_ABSOLUTE
+                                   && (the_insn.exp.X_add_number > immediate_max
+                                       || the_insn.exp.X_add_number < ~immediate_max))
+                                 as_bad ("constant value must be between %ld and %ld",
+                                         ~immediate_max, immediate_max);
+                               /* Reset to prevent extraneous range check.  */
+                               immediate_max = 0;
+
                                continue;
                                
                        case 'a':
@@ -1514,7 +1542,7 @@ long val;
                        as_bad("relocation overflow.");
                } /* on overflow */
                
-               buf[2] = (val >> 8) & 0x7;
+               buf[2] |= (val >> 8) & 0x7;
                buf[3] = val & 0xff;
                break;
                
@@ -1524,7 +1552,7 @@ long val;
                        as_bad("relocation overflow.");
                } /* on overflow */
                
-               buf[2] = (val >> 8) & 0x3;
+               buf[2] |= (val >> 8) & 0x3;
                buf[3] = val & 0xff;
                break;
 
@@ -1582,7 +1610,7 @@ long val;
                if (val & ~0x00001fff) {
                        as_bad("relocation overflow");
                } /* on overflow */
-               buf[2] = (val >> 8) & 0x1f;
+               buf[2] |= (val >> 8) & 0x1f;
                buf[3] = val & 0xff;
                break;
                
@@ -1607,6 +1635,10 @@ long val;
        case RELOC_BASE10:
 #endif
        case RELOC_BASE13:
+               if (((val > 0) && (val & ~0x00001fff))
+                   || ((val < 0) && (~(val - 1) & ~0x00001fff))) {
+                       as_bad("relocation overflow");
+               } /* on overflow */
                buf[2] |= (val >> 8) & 0x1f;
                buf[3] = val;
                break;