From: Ian Lance Taylor Date: Mon, 20 Jan 1997 17:43:43 +0000 (+0000) Subject: * config/tc-mips.c (md_begin): Don't set interlocks for X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c36a90ef651661e24330501dfbde33545f548301;p=binutils-gdb.git * config/tc-mips.c (md_begin): Don't set interlocks for mips_4650. PR 11507. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index cdd2f0e8fb7..a10580e18d7 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +Mon Jan 20 12:42:06 1997 Ian Lance Taylor + + * config/tc-mips.c (md_begin): Don't set interlocks for + mips_4650. + Wed Jan 15 13:51:50 1997 Ian Lance Taylor * read.c (read_a_source_file): Make sure the symbol ends with diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index a788dcced7c..1160d137d43 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -827,7 +827,7 @@ md_begin () if (mips_4100 < 0) mips_4100 = 0; - if (mips_4650 || mips_4010 || mips_4100 || mips_cpu == 4300) + if (mips_4010 || mips_4100 || mips_cpu == 4300) interlocks = 1; else interlocks = 0; @@ -2552,8 +2552,8 @@ load_register (counter, reg, ep, dbl) expressionS *ep; int dbl; { - int shift, freg; - expressionS hi32, lo32, tmp; + int freg; + expressionS hi32, lo32; if (ep->X_op != O_big) { @@ -2613,11 +2613,9 @@ load_register (counter, reg, ep, dbl) if (ep->X_op != O_big) { hi32 = *ep; - shift = 32; - hi32.X_add_number >>= shift; + hi32.X_add_number = (valueT) hi32.X_add_number >> 16; + hi32.X_add_number = (valueT) hi32.X_add_number >> 16; hi32.X_add_number &= 0xffffffff; - if ((hi32.X_add_number & 0x80000000) != 0) - hi32.X_add_number |= ~ (offsetT) 0xffffffff; lo32 = *ep; lo32.X_add_number &= 0xffffffff; } @@ -2638,76 +2636,130 @@ load_register (counter, reg, ep, dbl) freg = 0; else { + int shift, bit; + unsigned long hi, lo; + if (hi32.X_add_number == 0xffffffff) { if ((lo32.X_add_number & 0xffff8000) == 0xffff8000) { - macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j", reg, 0, - (int) BFD_RELOC_LO16); + macro_build ((char *) NULL, counter, &lo32, "addiu", "t,r,j", + reg, 0, (int) BFD_RELOC_LO16); return; } if (lo32.X_add_number & 0x80000000) { macro_build ((char *) NULL, counter, &lo32, "lui", "t,u", reg, (int) BFD_RELOC_HI16); - macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", reg, reg, - (int) BFD_RELOC_LO16); + if (lo32.X_add_number & 0xffff) + macro_build ((char *) NULL, counter, &lo32, "ori", "t,r,i", + reg, reg, (int) BFD_RELOC_LO16); return; } } - /* Check for 16bit shifted constant: */ - shift = 32; - tmp.X_add_number = hi32.X_add_number << shift | lo32.X_add_number; - /* We know that hi32 is non-zero, so start the mask on the first - bit of the hi32 value: */ + /* Check for 16bit shifted constant. We know that hi32 is + non-zero, so start the mask on the first bit of the hi32 + value. */ shift = 17; do { - if ((tmp.X_add_number & ~((offsetT)0xffff << shift)) == 0) - { - tmp.X_op = O_constant; - tmp.X_add_number >>= shift; - macro_build ((char *) NULL, counter, &tmp, "ori", "t,r,i", reg, 0, - (int) BFD_RELOC_LO16); - macro_build ((char *) NULL, counter, NULL, - (shift >= 32) ? "dsll32" : "dsll", - "d,w,<", reg, reg, (shift >= 32) ? shift - 32 : shift); - return; - } + unsigned long himask, lomask; + + if (shift < 32) + { + himask = 0xffff >> (32 - shift); + lomask = (0xffff << shift) & 0xffffffff; + } + else + { + himask = 0xffff << (shift - 32); + lomask = 0; + } + if ((hi32.X_add_number & ~ (offsetT) himask) == 0 + && (lo32.X_add_number & ~ (offsetT) lomask) == 0) + { + expressionS tmp; + + tmp.X_op = O_constant; + if (shift < 32) + tmp.X_add_number = ((hi32.X_add_number << (32 - shift)) + | (lo32.X_add_number >> shift)); + else + tmp.X_add_number = hi32.X_add_number >> (shift - 32); + macro_build ((char *) NULL, counter, &tmp, "ori", "t,r,i", reg, 0, + (int) BFD_RELOC_LO16); + macro_build ((char *) NULL, counter, NULL, + (shift >= 32) ? "dsll32" : "dsll", + "d,w,<", reg, reg, + (shift >= 32) ? shift - 32 : shift); + return; + } shift++; } while (shift <= (64 - 16)); - freg = 0; - shift = 32; - tmp.X_add_number = hi32.X_add_number << shift | lo32.X_add_number; - while ((tmp.X_add_number & 1) == 0) - { - tmp.X_add_number >>= 1; - freg++; - } - if (((tmp.X_add_number + 1) & tmp.X_add_number) == 0) /* (power-of-2 - 1) */ + /* Find the bit number of the lowest one bit, and store the + shifted value in hi/lo. */ + hi = (unsigned long) (hi32.X_add_number & 0xffffffff); + lo = (unsigned long) (lo32.X_add_number & 0xffffffff); + if (lo != 0) + { + bit = 0; + while ((lo & 1) == 0) + { + lo >>= 1; + ++bit; + } + lo |= (hi & (((unsigned long) 1 << bit) - 1)) << (32 - bit); + hi >>= bit; + } + else + { + bit = 32; + while ((hi & 1) == 0) + { + hi >>= 1; + ++bit; + } + lo = hi; + hi = 0; + } + + /* Optimize if the shifted value is a (power of 2) - 1. */ + if ((hi == 0 && ((lo + 1) & lo) == 0) + || (lo == 0xffffffff && ((hi + 1) & hi) == 0)) { - shift = COUNT_TOP_ZEROES((unsigned int)hi32.X_add_number); + shift = COUNT_TOP_ZEROES ((unsigned int) hi32.X_add_number); if (shift != 0) { + expressionS tmp; + + /* This instruction will set the register to be all + ones. */ tmp.X_op = O_constant; - tmp.X_add_number = (offsetT)-1; - macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j", reg, 0, - (int) BFD_RELOC_LO16); /* set all ones */ - if (freg != 0) + tmp.X_add_number = (offsetT) -1; + macro_build ((char *) NULL, counter, &tmp, "addiu", "t,r,j", + reg, 0, (int) BFD_RELOC_LO16); + if (bit != 0) { - freg += shift; + bit += shift; macro_build ((char *) NULL, counter, NULL, - (freg >= 32) ? "dsll32" : "dsll", + (bit >= 32) ? "dsll32" : "dsll", "d,w,<", reg, reg, - (freg >= 32) ? freg - 32 : freg); + (bit >= 32) ? bit - 32 : bit); } - macro_build ((char *) NULL, counter, NULL, (shift >= 32) ? "dsrl32" : "dsrl", - "d,w,<", reg, reg, (shift >= 32) ? shift - 32 : shift); + macro_build ((char *) NULL, counter, NULL, + (shift >= 32) ? "dsrl32" : "dsrl", + "d,w,<", reg, reg, + (shift >= 32) ? shift - 32 : shift); return; } } + + /* Sign extend hi32 before calling load_register, because we can + generally get better code when we load a sign extended value. */ + if ((hi32.X_add_number & 0x80000000) != 0) + hi32.X_add_number |= ~ (offsetT) 0xffffffff; load_register (counter, reg, &hi32, 0); freg = reg; }