This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] MIPS: microMIPS ASE support


Hi Richard & all,

 I am back at last with updates to the change and I have combined two 
e-mails here again.  I hope this covers all the outstanding concerns and 
nothing from earlier correspondence has been lost unaddressed.

 Chao-ying, there are a couple of questions for you throughout -- would 
you please give them a thought?  And anyone, of course, please feel free 
to comment as you like.

> "Maciej W. Rozycki" <macro@codesourcery.com> writes:
> >
> >  Well, if we have code like this:
> >
> > 	branch	...
> > 	 LUI	...
> > 	insn	[...]
> >
> > (where for the purpose of this consideration BRANCH may also be a jump) 
> > then LUI cannot be entirely deleted and INSN moved into the slot of BRANCH 
> > no matter if INSN is a branch or an computational instruction.  All we can 
> > do in this case is to see if there is a corresponding BRANCHC instruction 
> > and use it to swap BRANCH with and then delete the LUI if so, or otherwise 
> > shrink the LUI to a 16-bit NOP if BRANCH permits or can be swapped with 
> > BRANCHS to permit a 16-bit delay-slot instruction.  If neither is 
> > possible, then the LUI is merely substituted with a 32-bit NOP (although 
> > the effect is purely cosmetical in this case; perhaps we should just back 
> > out).
> 
> Yeah, I see your point.  I was thinking that the code claims to "know"
> that the LUI and "insn" are both part of the same load address.  So if
> the branch was taken, the target of the LUI ought to be dead.  However,
> I agree that (even though the code does seem to assume that to some extent)
> the assumption is wrong.
> 
> E.g. you could have:
> 
> 	beqz	$2,1f
> 	lui	$4,%hi(foo)	<-- A
> 
> 	addiu	$4,$4,%lo(foo)	<-- B
> 	...
> 	jr      $31
> 2:	...
> 	lui	$4,%hi(foo)	<-- C
> 	...
> 1:	addiu   $4,$4,%lo(foo)	<-- D
> 
> In this case, the LO16 reloc for D might follow the HI16 reloc for C,
> and the LO16 reloc for B might follow the HI16 reloc for A.  AIUI, we'd
> consider relaxing A/B but not C/D.  In this case, turning A into a NOP
> is wrong, because $4 is still live at D.  If you agree then...
> 
> >  Also with the recent update to LUI relaxation code I think we should 
> > simply disallow the optimisation if a LUI is in a delay slot of an 
> > unconditional branch -- we have no way to verify the corresponding LO16 
> > reloc really belongs to this LUI instruction in that case.  This will let 
> > us simplify code (which has become a little bit hairy by now IMO) a little 
> > bit I would guess.  [FIXME]
> 
> ...maybe it would be simpler to drop the optimisation if the LUI is any
> kind of delay slot.  I think this would simply the code, and I don't think
> we'd then need to check for branch relocs.  We'd just have *_norel-like
> functions (although not called that any more) to check for every kind
> of branch.

 I have implemented these changes now, dropping the unsafe part of 
optimisation for the scenario you have listed.  I still have two concerns 
about this optimisation, but the optional nature of linker relaxation 
makes them reasonably unimportant IMO:

1. The resulting change of alignment may cause the linker produce bad code 
   or abort the process if microMIPS and standard MIPS code is mixed in 
   one object file and the latter turns out to become unaligned, e.g.

	.set	micromips
	.set	noreorder
	.align	2
	.globl	foo
	.ent	foo
foo:
	beqz32	$4, 0f
	 nop16
0:
	jalx	bar
	nop
	.end	foo

	.set	nomicromips
	.align	2
	.globl	bar
	.ent	bar
bar:
	nop
	.end	bar

   The piece above will fail to link, because BEQZ will be converted to 
   a BEQZC and the 16-bit NOP from its delay slot taken out.  As a result 
   bar() will become misaligned and the JALX will not be allowed.  If 
   there was no JALX, then linking might succeed if there were only 
   indirect calls to bar(), but the function would not be properly aligned 
   for standard MIPS execution.

2. Broken code is produced for cases like this:

	.set	noreorder
	lui	$4, 0x1234
	lui	$2, %hi(foo)
	bnez	$3, 0f
	 addiu	$2, %lo(foo)
	...

	lui	$4, %hi(foo)
0:
	jal	bar
	 addiu	$4, %lo(foo)

   where the resulting code:

	.set	noreorder
	lui	$4, 0x1234
	bnez	$3, 0f
	 addiu	$2, $pc, foo - .
	...

0:
	jal	bar
	 addiu	$4, $pc, foo - .

   obviously not being the same.  Such usage of HI16/LO16 relocations is 
   non-standard, but not disallowed.  OTOH searching the symbol tables for 
   the label (we could disable this relaxation if there's one at the
   instruction a LO16 relocation is against) is expensive.

 What do you think?  [FIXME]

On Sun, 2 Jan 2011, Richard Sandiford wrote:

> This is the second and final part of the review.
> 
> First of all, thanks for the great effort you've made to integrate the
> microMIPS macro code into macro().  This is much, much better than before,
> and should be far less of a maintenance burden.

 I hope so too and thanks for your extensive effort too.

> FWIW, I plan to review the follow-up patch based purely on whether
> it deals with the review comments.  Anything that we've collectively
> missed this far (and there's bound to be something) will just have to
> be fixed when someone trips over it.

 OK.

> I think the only change of any significant size that needs to be made
> is to move the place where we convert to microMIPS relocs (see below).
> Everything else is pretty small.

 Honestly the reloc conversion change was probably the smallest of all 
(barring formatting fixes). :/

> > @@ -1821,6 +1830,8 @@ the target word.  These are used on the 
> >  ENUM
> >    BFD_RELOC_GPREL16
> >  ENUMX
> > +  BFD_RELOC_MICROMIPS_GPREL16
> > +ENUMX
> >    BFD_RELOC_GPREL32
> >  ENUMDOC
> >    For systems that allocate a Global Pointer register, these are
> 
> You've now moved most of the new relocs into MIPS-specific areas, thanks,
> but some, like the one above, are still in generic lists.  Let's put:
> 
> ENUM
>   BFD_RELOC_MICROMIPS_7_PCREL_S1
> ENUMX
>   BFD_RELOC_MICROMIPS_10_PCREL_S1
> ENUMX
>   BFD_RELOC_MICROMIPS_16_PCREL_S1
> ENUMDOC
>   MicroMIPS PC-relative relocations.
> 
> before the main "MIPS ELF relocations." section, followed
> by a new section:
> 
> ENUM
>   BFD_RELOC_MICROMIPS_GPREL16
> ENUMX
>   BFD_RELOC_MICROMIPS_HI16
> ENUMX
>   BFD_RELOC_MICROMIPS_HI16_S
> ENUMX
>   BFD_RELOC_MICROMIPS_LO16
> ENUMDOC
>   MicroMIPS versions of generic BFD relocs.
> 
> Also, let's combine this:
> 
> > @@ -2182,6 +2193,11 @@ ENUMDOC
> >       simple reloc otherwise.
> >  
> >  ENUM
> > +  BFD_RELOC_MICROMIPS_JMP
> > +ENUMDOC
> > +  The microMIPS jump instruction.
> > +
> > +ENUM
> >    BFD_RELOC_MIPS16_JMP
> >  ENUMDOC
> >    The MIPS16 jump instruction.
> 
> with the MIPS_JMP entry, since you're doing the same with the other
> microMIPS versions of MIPS relocs.

 OK, but I had to remove the original documentation note.  The immediate 
argument is only shifted left by one bit in the microMIPS mode.

> > +  /* Whether we are assembling for the mipsMIPS processor.  0 if we are
> > +     not, 1 if we are, and -1 if the value has not been initialized.
> > +     Changed by `.set micromips' and `.set nomicromips', and the -mmicromips
> > +     and -mno-micromips command line options, and the default CPU.  */
> > +  int micromips;
> 
> Blind cut-&-paste.  "microMIPS ASE".
> 
> Let's leave the -1 case and:
> 
> > +/* Return true if the given CPU supports microMIPS.  */
> > +#define CPU_HAS_MICROMIPS(cpu)	0
> 
> out.  I think the CPU_HAS_MIPS16 stuff is derived from the original LSI
> TinyRisc support and wouldn't be used for ASEs.

 The microMIPS ASE provides for processors that do not support the 
standard MIPS instruction set.  These I think should default to the 
microMIPS mode.  I suspect someone will eventually implement such a 
processor as since we've got this code implemented here already I'd like 
to leave it as a placeholder.  I think it's not much of a burden, is it?

> > @@ -495,9 +515,11 @@ static int mips_32bitmode = 0;
> >     require nops to be inserted.  This applies to instructions marked
> >     INSN_LOAD_MEMORY_DELAY.  These nops are only required at MIPS ISA
> >     level I.  */
> > -#define gpr_interlocks \
> > -  (mips_opts.isa != ISA_MIPS1  \
> > -   || mips_opts.arch == CPU_R3900)
> > +#define gpr_interlocks                                \
> > +  (mips_opts.isa != ISA_MIPS1                         \
> > +   || mips_opts.arch == CPU_R3900                     \
> > +   || mips_opts.micromips                             \
> > +   )
> >  
> >  /* Whether the processor uses hardware interlocks to avoid delays
> >     required by coprocessor instructions, and thus does not require
> > @@ -512,6 +534,7 @@ static int mips_32bitmode = 0;
> >      && mips_opts.isa != ISA_MIPS2                     \
> >      && mips_opts.isa != ISA_MIPS3)                    \
> >     || mips_opts.arch == CPU_R4300                     \
> > +   || mips_opts.micromips                             \
> >     )
> >  
> >  /* Whether the processor uses hardware interlocks to protect reads
> > @@ -519,7 +542,10 @@ static int mips_32bitmode = 0;
> >     thus does not require nops to be inserted.  This applies to
> >     instructions marked INSN_COPROC_MEMORY_DELAY.  These nops are only
> >     requires at MIPS ISA level I.  */
> > -#define cop_mem_interlocks (mips_opts.isa != ISA_MIPS1)
> > +#define cop_mem_interlocks                            \
> > +  (mips_opts.isa != ISA_MIPS1                         \
> > +   || mips_opts.micromips                             \
> > +   )
> >  
> >  /* Is this a mfhi or mflo instruction?  */
> >  #define MF_HILO_INSN(PINFO) \
> 
> These changes are OK if they make life easier, but please add a comment
> saying why they do.

 No interlocks are ever needed for microMIPS code, even if building with 
-mips1 (the default).  I have added a note to this effect to the relevant 
comments.

> > +#define RELAX_MICROMIPS_ENCODE(type, is_16bit, uncond, link, toofar)	\
> > +  (0x40000000							\
> > +   | ((type) & 0xff)						\
> > +   | ((is_16bit) ? 0x100 : 0)					\
> > +   | ((uncond) ? 0x200 : 0)					\
> > +   | ((link) ? 0x400 : 0)					\
> > +   | ((toofar) ? 0x800 : 0))
> > +#define RELAX_MICROMIPS_P(i) (((i) & 0xc0000000) == 0x40000000)
> > +#define RELAX_MICROMIPS_TYPE(i) ((i) & 0xff)
> > +#define RELAX_MICROMIPS_USER_16BIT(i) (((i) & 0x100) != 0)
> > +#define RELAX_MICROMIPS_UNCOND(i) (((i) & 0x200) != 0)
> > +#define RELAX_MICROMIPS_LINK(i) (((i) & 0x400) != 0)
> > +#define RELAX_MICROMIPS_TOOFAR(i) (((i) & 0x800) != 0)
> > +#define RELAX_MICROMIPS_MARK_TOOFAR(i) ((i) | 0x800)
> > +#define RELAX_MICROMIPS_CLEAR_TOOFAR(i) ((i) & ~0x800)
> 
> Is there a need to create variant frags when the user has explicitly
> specified the instruction size?  I wouldn't have expected any relaxation
> to be necessary in that case, and it looks like the relaxation code does
> indeed return 2 whenever USER_16BIT is true.

 I suspect this has been copied over from MIPS16 code.  
RELAX_MIPS16_USER_SMALL seems to be used in a similar fashion.  Do you 
happen to know for sure why it has been implemented this way for MIPS16 
assembly?  My suspicion is we want to keep the relocation until the final 
relaxation so that if the final value turns out to fit afterwards (but not 
until then) in the forced-truncated immediate field of the instruction 
nothing is lost.

> If the bit really is needed, let's call the parameter "user_16bit"
> rather than "is_16bit", to match the use.

 Fixed.

> Add a comment saying what RELAX_MICROMIPS_TYPE is.  See the MIPS16
> comment as an example.
> 
> > +#define RELAX_MICROMIPS_EXTENDED(i) (((i) & 0x10000) != 0)
> > +#define RELAX_MICROMIPS_MARK_EXTENDED(i) ((i) | 0x10000)
> > +#define RELAX_MICROMIPS_CLEAR_EXTENDED(i) ((i) & ~0x10000)
> 
> Any particular reason why 0x10000 rather than 0x1000, which seems
> to be the first unused bit?  I would prefer to pack the used bits
> together so that it's easier to tell what's left.

 These weren't used anywhere.  I have discarded these macros.

> > +  /* True if the macro is in a 16-bit branch delay slot.  */
> > +  bfd_boolean delay_slot_16bit_p;
> > +
> > +  /* True if the macro is in a 32-bit branch delay slot.  */
> > +  bfd_boolean delay_slot_32bit_p;
> 
> I think it would be cleaner to have:
> 
>   /* If the macro is in a delay slot that requires a specific length
>      of instruction, this is that length, otherwise it is zero.  */
>   unsigned int delay_slot_length;

 Yes, marginally.  As this is similar to updates I have made elsewhere 
already, I have implemented your suggestion now.

> > +  /* For relaxable macros, fsize[0] is the length of the first instruction
> > +     of the first alternative in bytes and fsize[1] is the length of the
> > +     first instruction of the second alternative.
> > +     For non-relaxable macros, both elements give the length of the
> > +     first instruction in bytes.  */
> > +  unsigned int fsize[2];
> 
> Rename to "first_insn_sizes" ("sizes" rather than "size" because the
> plurality comes from having two alternatives).  Also add:
> 
>   The fields are zero if we haven't yet seen the first instruction.

 Fixed.

> > @@ -2374,22 +2736,21 @@ s_is_linkonce (symbolS *sym, segT from_s
> >    return linkonce;
> >  }
> >  
> > -/* Mark instruction labels in mips16 mode.  This permits the linker to
> > -   handle them specially, such as generating jalx instructions when
> > -   needed.  We also make them odd for the duration of the assembly, in
> > -   order to generate the right sort of code.  We will make them even
> > +/* Mark instruction labels in MIPS16/microMIPS mode.  This permits the
> > +   linker to handle them specially, such as generating jalx instructions
> > +   when needed.  We also make them odd for the duration of the assembly,
> > +   in order to generate the right sort of code.  We will make them even
> >     in the adjust_symtab routine, while leaving them marked.  This is
> >     convenient for the debugger and the disassembler.  The linker knows
> >     to make them odd again.  */
> >  
> >  static void
> > -mips16_mark_labels (void)
> > +mips_compressed_mark_labels (void)
> >  {
> >    segment_info_type *si = seg_info (now_seg);
> >    struct insn_label_list *l;
> >  
> > -  if (!mips_opts.mips16)
> > -    return;
> > +  gas_assert (HAVE_CODE_COMPRESSION);
> >  
> >    for (l = si->label_list; l != NULL; l = l->next)
> >     {
> > @@ -2397,16 +2758,22 @@ mips16_mark_labels (void)
> >  
> >  #if defined(OBJ_ELF) || defined(OBJ_MAYBE_ELF)
> >        if (IS_ELF)
> > -	S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
> > +	{
> > +	  if (mips_opts.mips16)
> > +	    S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
> > +	  else if (mips_opts.micromips)
> > +	    S_SET_OTHER (label, ELF_ST_SET_MICROMIPS (S_GET_OTHER (label)));
> > +	}
> >  #endif
> >        if ((S_GET_VALUE (label) & 1) == 0
> >  	/* Don't adjust the address if the label is global or weak, or
> >  	   in a link-once section, since we'll be emitting symbol reloc
> >  	   references to it which will be patched up by the linker, and
> > -	   the final value of the symbol may or may not be MIPS16.  */
> > +	   the final value of the symbol may or may not be MIPS16/microMIPS.  */
> >  	  && ! S_IS_WEAK (label)
> >  	  && ! S_IS_EXTERNAL (label)
> > -	  && ! s_is_linkonce (label, now_seg))
> > +	  && ! s_is_linkonce (label, now_seg)
> > +	  && HAVE_CODE_COMPRESSION)
> >  	S_SET_VALUE (label, S_GET_VALUE (label) | 1);
> >      }
> >  }
> 
> Looks like the addition of HAVE_CODE_COMPRESSION is redundant here,
> you've already asserted it in the previous hunk.

 Yes, cut & paste error, fixed.

> > +static char *
> > +micromips_label_name (void)
> > +{
> > +  char *p = micromips_target_name;
> > +  char symbol_name_temporary[24];
> > +  unsigned long l;
> > +  int i;
> > +
> > +  if (*p)
> > +    return p;
> > +
> > +  i = 0;
> > +  l = micromips_target_label;
> > +#ifdef LOCAL_LABEL_PREFIX
> > +  *p++ = LOCAL_LABEL_PREFIX;
> > +#endif
> [...]
> > +int
> > +mips_label_is_local (const char *name)
> > +{
> > +  return strchr (name, MICROMIPS_LABEL_CHAR) != NULL;
> > +}
> 
> Why is this change needed?  The default local-label detection should be
> enough for ELF targets, which always have a LOCAL_LABEL_PREFIX.

 I fail to see a justification, so I have removed this function.  
Chao-ying, do you have anything to add?

> > @@ -2915,7 +3367,8 @@ append_insn (struct mips_cl_insn *ip, ex
> >  	 out that the branch was out-of-range, we'll get an error.  */
> >        && !mips_opts.warn_about_macros
> >        && (mips_opts.at || mips_pic == NO_PIC)
> > -      && !mips_opts.mips16)
> > +      && !mips_opts.mips16
> > +      && !mips_opts.micromips)
> >      {
> >        relaxed_branch = TRUE;
> >        add_relaxed_insn (ip, (relaxed_branch_length
> 
> !HAVE_CODE_COMPRESSION

 Obviously.

> > +      if (mips_relax.sequence)
> > +	abort ();
> 
> gas_assert (!mips_relax.sequence);

 I sort of wonder why it is needed here in the first place, but not in 
any of the other blocks throughout this conditional, hmm...

> > +	      /* For microMIPS, disable reordering.  */
> > +	      || mips_opts.micromips
> 
> You should say whether this is for simplicity or by specification.
> Either way, a bit more detail would be welcome.  E.g. something like:
> 
> 	      /* microMIPS assembly language does not allow the assembler
> 	      	 to reorder instructions, even in .set reorder mode.
> 		 Delay slots are always filled with nops when .set reorder
> 		 is in effect.  */
> 
> (adjusted as appropriate if my guess is wrong).

 I believe the concerns are the same as with MIPS16 code -- so far we have 
failed to develop means to update DWARF-2 records accordingly and if a 
32-bit branch/jump is swapped with a 16-bit delay-slot instruction (or 
vice versa as it's permitted in microMIPS code, though not in MIPS16 one) 
then substandard debugging experience results from software breakpoints 
placed mid-through an instruction.

 So as much as we'd love to reorder we really can't without fixing GAS 
elsewhere.

 Hmm, it looks like the piece of code to disable MIPS16 reordering has 
never made its way upstream.  It should, unless we have a volunteer to fix 
GAS immediately, so while holding my breath and hoping that people won't 
fight over this challenge I extracted this piece now and updated this 
change accordingly.  It makes no sense to keep the two pieces separate.

 It also looks to me we shouldn't be checking for INSN_SYNC (that's a 
waste of one of the precious flags we're just running out of), INSN_ERET 
and INSN_DERET here explicitly.  These instructions should have their 
INSN_TRAP flag set instead -- and the flag should be renamed as I said 
previously to avoid confusion and reflect its actual meaning, i.e. "this 
instruction is forbidden in a branch delay slot".

> > +  /* If both delay slots are out of size, then emit the warning now.  */
> > +  if ((subtype & (RELAX_DELAY_SLOT_SIZE_FIRST | RELAX_DELAY_SLOT_SIZE_SECOND))
> > +      == (RELAX_DELAY_SLOT_SIZE_FIRST | RELAX_DELAY_SLOT_SIZE_SECOND))
> 
>   /* If both alternatives fail to fill a delay slot correctly,
>      emit the warning now.  */
>   if ((subtype & RELAX_DELAY_SLOT_SIZE_FIRST) != 0
>       && (subtype & RELAX_DELAY_SLOT_SIZE_SECOND) != 0)

 I expect that to produce marginally worse code, but I won't insist.  The 
comment update is OK of course.

> > +  hash = !mips_opts.micromips ? op_hash : micromips_op_hash;
> 
>   hash = mips_opts.micromips ? micromips_op_hash : op_hash;

 Applied.

> > @@ -3640,13 +4407,32 @@ macro_build (expressionS *ep, const char
> >        /* Search until we get a match for NAME.  It is assumed here that
> >  	 macros will never generate MDMX, MIPS-3D, or MT instructions.  */
> >        if (strcmp (fmt, mo->args) == 0
> > -	  && mo->pinfo != INSN_MACRO
> > -	  && is_opcode_valid (mo))
> > -	break;
> > +	  && mo->pinfo != INSN_MACRO)
> > +	{
> > +	  bfd_boolean ok;
> > +	  bfd_boolean size_ok;
> > +	  bfd_boolean delay_slot_ok;
> > +
> > +	  ok = is_opcode_valid (mo);
> > +	  size_ok = is_size_valid (mo);
> > +	  delay_slot_ok = is_delay_slot_valid (mo);
> > +	  if (ok && size_ok && (delay_slot_ok || secondpass))
> > +	    break;
> > +	  if (!delay_slot_ok && !twopass)
> > +	    {
> > +	      firstmo = mo;
> > +	      twopass = TRUE;
> > +	    }
> > +	}
> >  
> >        ++mo;
> > -      gas_assert (mo->name);
> > -      gas_assert (strcmp (name, mo->name) == 0);
> > +      if (!mo->name || strcmp (name, mo->name) != 0)
> > +	{
> > +	  gas_assert (twopass);
> > +	  gas_assert (!secondpass);
> > +	  secondpass = TRUE;
> > +	  mo = firstmo;
> > +	}
> >      }
> >  
> >    create_insn (&insn, mo);
> 
> Do we really need to do two passes here?  I would have expected
> to see something like:
> 
>       if (strcmp (fmt, mo->args) == 0
>           && mo->pinfo != INSN_MACRO
>           && is_opcode_valid (mo)
>           && is_size_valid (mo))
>         {
>           if (is_delay_slot_valid (mo))
>             break;
>           else if (!reserve_mo)
>             reserve_mo = mo;
>         }
> 
>       if (!mo->name || strcmp (name, mo->name) != 0)
>         {
>           /* All usable candidates violate the delay slot requirements
> 	     of the previous instruction.  Pick the first such candidate
> 	     anyway; we will issue an appropriate warning later.  */
>           gcc_assert (reserve_mo);
>           mo = reserve_mo;
>           break;
>         }
> 
> which IMO is simpler and clearer.

 Good point.  I have simplified it yet further though.

> > +	  if (!mips_opts.micromips)
> > +	    INSERT_OPERAND (0, RD, insn, va_arg (args, int));
> > +	  else
> > +	    INSERT_OPERAND (1, RS, insn, va_arg (args, int));
> 
> 	  if (mips_opts.micromips)
> 	    INSERT_OPERAND (1, RS, insn, va_arg (args, int));
> 	  else
> 	    INSERT_OPERAND (0, RD, insn, va_arg (args, int));

 You don't like negative statements, do you? ;)

> >  	case 'i':
> >  	case 'j':
> >  	  macro_read_relocs (&args, r);
> > -	  gas_assert (*r == BFD_RELOC_GPREL16
> > +	  gas_assert (mips_opts.micromips
> > +		      || *r == BFD_RELOC_GPREL16
> >  		      || *r == BFD_RELOC_MIPS_HIGHER
> >  		      || *r == BFD_RELOC_HI16_S
> >  		      || *r == BFD_RELOC_LO16
> >  		      || *r == BFD_RELOC_MIPS_GOT_OFST);
> > +	  gas_assert (!mips_opts.micromips
> > +		      || *r == BFD_RELOC_MICROMIPS_GPREL16
> > +		      || *r == BFD_RELOC_MICROMIPS_HIGHER
> > +		      || *r == BFD_RELOC_MICROMIPS_HI16_S
> > +		      || *r == BFD_RELOC_MICROMIPS_LO16
> > +		      || *r == BFD_RELOC_MICROMIPS_GOT_OFST);
> 
> Let's move the macro_read_relocs stuff inside append_insn rather than
> leaving the conversion to the callers.  You could then make append_insn
> keep a record of the original (non-microMIPS) reloc_type[0] too,
> which would simply some of the logic.  E.g. these changes would
> no longer be needed:
> 
> > -	  /* Tag symbols that have a R_MIPS16_26 relocation against them.  */
> > -	  if (reloc_type[0] == BFD_RELOC_MIPS16_JMP
> > +	  /* Tag symbols that have a R_MIPS16_26 or R_MICROMIPS_26_S1
> > +	     relocation against them.  */
> > +	  if ((reloc_type[0] == BFD_RELOC_MIPS16_JMP
> > +	       || reloc_type[0] == BFD_RELOC_MICROMIPS_JMP)
> >  	      && ip->fixp[0]->fx_addsy)
> >  	    *symbol_get_tc (ip->fixp[0]->fx_addsy) = 1;

 This actually would -- note that's BFD_RELOC_MIPS16_JMP and not 
BFD_RELOC_MIPS_JMP there.

> > @@ -3105,6 +3638,13 @@ append_insn (struct mips_cl_insn *ip, ex
> >  		  || reloc_type[0] == BFD_RELOC_MIPS_SCN_DISP
> >  		  || reloc_type[0] == BFD_RELOC_MIPS_REL16
> >  		  || reloc_type[0] == BFD_RELOC_MIPS_RELGOT
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_JMP
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_GPREL16
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_LITERAL
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_SUB
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_HIGHEST
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_HIGHER
> > +		  || reloc_type[0] == BFD_RELOC_MICROMIPS_SCN_DISP
> >  		  || reloc_type[0] == BFD_RELOC_MIPS16_GPREL
> >  		  || hi16_reloc_p (reloc_type[0])
> >  		  || lo16_reloc_p (reloc_type[0])))
> 
> You also wouldn't need micromips_percent_op.

 Done.  As this is a self-contained change and may possibly need further 
tweaks, I have made it a separate patch to apply on top of the rest of the 
fixes (and the original change).

 BTW, do you happen to know what the issue about BFD_RELOC_MIPS_SCN_DISP 
is?  We refer to it in a couple of places throughout GAS, but never 
actually generate it.  I realise BFD may have to handle the reloc for 
compatibility with other tools, but GAS?

> Sorry, I know this isn't what I said first time round, but it was much
> harder to see the wood for the trees before you'd integrated the macro
> code properly.

 Hmm, what can I say?

> > +  /* For microMIPS, check if the current instruction is not in
> > +     a delay slot that requires a 32-bit instruction.  */
> > +  if (mips_opts.micromips
> > +      && !(history[0].insn_mo->pinfo2 & INSN2_BRANCH_DELAY_32BIT))
> 
>   /* Prefer to use a 16-bit microMIPS instruction unless the previous
>      instruction specifically requires a 32-bit one.  */

 OK.

> > +   if CALL is set.  In the reorder mode the delay slot would be filled
> > +   with a nop anyway, so code produced is simply:
> > +	BR	<args>, <sym>
> 
> Add an explicit nop, since the code does.

 Good point.

> > +/* Emit a coprocessor branch macro specified by TYPE, using CC as
> > +   the condition code tested.  EP specifies the branch target.  */
> 
> "branch-likely macro".

 OK.

> > +/* Emit a two-argument branch macro specified by TYPE, using SREG as
> > +   the register tested.  EP specifies the branch target.  */
> > +
> > +static void
> > +macro_build_branch_rs (int type, expressionS *ep, unsigned int sreg)
> > +{
> > +  const char *brneg;
> > +  const char *br;
> > +  int likely = 0;
> > +  int call = 0;
> > +
> > +  switch (type)
> > +    {
> > +    case M_BGEZ:
> > +      br = "bgez";
> > +      break;
> > +    case M_BGEZL:
> > +      br = mips_opts.micromips ? "bgez" : "bgezl";
> > +      brneg = "bltz";
> > +      likely = 1;
> > +      break;
> > +    case M_BGEZALL:
> > +      gas_assert (mips_opts.micromips);
> > +      br = "bgezals";
> > +      brneg = "bltz";
> > +      likely = 1;
> > +      call = 1;
> > +      break;
> > +    case M_BGTZ:
> > +      br = "bgtz";
> > +      break;
> > +    case M_BGTZL:
> > +      br = mips_opts.micromips ? "bgtz" : "bgtzl";
> > +      brneg = "blez";
> > +      likely = 1;
> > +      break;
> > +    case M_BLEZ:
> > +      br = "blez";
> > +      break;
> > +    case M_BLEZL:
> > +      br = mips_opts.micromips ? "blez" : "blezl";
> > +      brneg = "bgtz";
> > +      likely = 1;
> > +      break;
> > +    case M_BLTZ:
> > +      br = "bltz";
> > +      break;
> > +    case M_BLTZL:
> > +      br = mips_opts.micromips ? "bltz" : "bltzl";
> > +      brneg = "bgez";
> > +      likely = 1;
> > +      break;
> > +    case M_BLTZALL:
> > +      gas_assert (mips_opts.micromips);
> > +      br = "bltzals";
> > +      brneg = "bgez";
> > +      likely = 1;
> > +      call = 1;
> > +      break;
> > +    default:
> > +      abort ();
> > +    }
> > +  if (mips_opts.micromips && likely)
> > +    macro_build_branch_likely (br, brneg, call, ep, "s,p", sreg, ZERO);
> > +  else
> > +    macro_build (ep, br, "s,p", sreg);
> > +}
> 
> No need for "likely".  Just initialise "brneg" to NULL and check for that.
> Same for macro_build_branch_rsrt.

 I'm not sure that is clearer, but I won't insist.  Adjusted.

> > +      if (!mips_opts.micromips)
> > +	label_expr.X_add_number = 8;
> > +      else
> > +	micromips_label_expr (&label_expr);
> 
>       if (mips_opts.micromips)
> 	micromips_label_expr (&label_expr);
>       else
> 	label_expr.X_add_number = 8;
> 
> (several occurences)

 Yes, same as somewhere above.  I've swapped all the negative conditions I 
could spot.

> > -	  macro_build (NULL, "jalr", "d,s", dreg, sreg);
> > +	  s = (!mips_opts.micromips || (mips_opts.noreorder && !cprestore)
> > +	       ? "jalr" : "jalrs");
> > +	  if (mips_opts.micromips && dreg == RA)
> > +	    macro_build (NULL, s, "mj", sreg);
> > +	  else
> > +	    macro_build (NULL, s, JALR_FMT, dreg, sreg);
> 
> Since we can use JALRS for mips_opts.noreorder && cprestore, I suppose
> the cprestore nop:
> 
>  		  if (mips_opts.noreorder)
> 		    macro_build (NULL, "nop", "");
> 
> ought to be conditional on !mips_opts.micromips.

 No, the delay slot always has to be explicitly filled here.  Otherwise 
you'll end up with LW $gp there (the instruction has a 16-bit variation 
too) -- that I fixed not so long ago.

 For the avoidance of doubt: all the call (linked jump/branch) 
instructions have a fixed-length delay slot that takes either 4 bytes (as 
with BGEZAL, BLTZAL, JAL, JALR and JALX instructions) or 2 bytes (as with 
BGEZALS, BLTZALS, JALS and JALRS).  All the other jump/branch instructions 
have an any-length delay slot except from compact jump/branch instructions 
that have none (these are BEQZC, BNEZC and JRC).  Overall the "S" suffix 
stands for a short delay slot and the "C" one means a compact jump/branch, 
i.e. no delay slot.

> > +	  /* A 12-bit offset field is too narrow to be used for a low-part
> > +	     relocation, so use the auxiliary register to load the full
> > +	     address provided if the A(b) format has been requested;
> > +	     load_address will produce the necessary relocations as code
> > +	     used with 16-bit offsets below would do.  Otherwise the o(b)
> > +	     format has been selected, so load the low part only and the
> > +	     relocation requested will have already been provided in
> > +	     offset_reloc, so just use that.  */
> 
> 	  /* A 12-bit offset field is too narrow to be used for a low-part
> 	     relocation, so load the whole address into the auxillary
> 	     register.  In the case of "A(b)" addresses, we first load
> 	     absolute address "A" into the register and then add base
> 	     register "b".  In the case of "o(b)" addresses, we simply
> 	     need to add 16-bit offset "o" to base register "b", and
> 	     offset_reloc already contains the relocations associated
> 	     with "o".  */

 OK.

> > +  hash = !mips_opts.micromips ? op_hash : micromips_op_hash;
> > +  past = (!mips_opts.micromips ? &mips_opcodes[NUMOPCODES]
> > +	  : &micromips_opcodes[bfd_micromips_num_opcodes]);
> 
>   if (mips_opts.micromips)
>     {
>       hash = micromips_op_hash;
>       past = &micromips_opcodes[bfd_micromips_num_opcodes];
>     }
>   else
>     {
>       hash = op_hash;
>       past = &mips_opcodes[NUMOPCODES];
>     }

 Not sure this is any better, but OK.

> > @@ -8688,32 +10234,50 @@ mips_ip (char *str, struct mips_cl_insn 
> >    argsStart = s = str + end;
> >    for (;;)
> >      {
> > +      bfd_boolean delay_slot_ok;
> > +      bfd_boolean size_ok;
> >        bfd_boolean ok;
> >  
> >        gas_assert (strcmp (insn->name, name) == 0);
> >  
> >        ok = is_opcode_valid (insn);
> > -      if (! ok)
> > +      size_ok = is_size_valid (insn);
> > +      delay_slot_ok = is_delay_slot_valid (insn);
> > +      if (!delay_slot_ok && !twopass)
> >  	{
> > -	  if (insn + 1 < &mips_opcodes[NUMOPCODES]
> > -	      && strcmp (insn->name, insn[1].name) == 0)
> > +	  firstinsn = insn;
> > +	  twopass = TRUE;
> > +	}
> > +      if (!ok || !size_ok || (!delay_slot_ok && !secondpass))
> > +	{
> > +	  static char buf[256];
> > +
> > +	  if (insn + 1 < past && strcmp (insn->name, insn[1].name) == 0)
> >  	    {
> >  	      ++insn;
> >  	      continue;
> >  	    }
> > -	  else
> > +	  if (twopass && !secondpass)
> >  	    {
> > -	      if (!insn_error)
> > -		{
> > -		  static char buf[100];
> > -		  sprintf (buf,
> > -			   _("opcode not supported on this processor: %s (%s)"),
> > -			   mips_cpu_info_from_arch (mips_opts.arch)->name,
> > -			   mips_cpu_info_from_isa (mips_opts.isa)->name);
> > -		  insn_error = buf;
> > -		}
> > -	      return;
> > +	      gas_assert (firstinsn);
> > +	      secondpass = TRUE;
> > +	      insn = firstinsn;
> > +	      continue;
> >  	    }
> > +
> > +	  if (insn_error)
> > +	    return;
> > +
> > +	  if (!ok)
> > +	    sprintf (buf, _("opcode not supported on this processor: %s (%s)"),
> > +		     mips_cpu_info_from_arch (mips_opts.arch)->name,
> > +		     mips_cpu_info_from_isa (mips_opts.isa)->name);
> > +	  else
> > +	    sprintf (buf, _("Unrecognized %u-bit version of microMIPS opcode"),
> > +		     8 * forced_insn_length);
> > +	  insn_error = buf;
> > +
> > +	  return;
> >  	}
> >  
> >        create_insn (ip, insn);
> 
> Same two-pass comment as before.

 Obviously this case is different as we have to pass all the matching 
instructions through the loop with the huge switch statement for argument 
matching too.  So it's not enough to pick the first one that does not meet 
the delay slot requirement and get away with that.  And the switch 
statement in its current form is not designed to make two successful 
parses possible.

 But having written that, I agree there is some room for improvement here 
even without redesigning the switch statement as in the second pass we do 
not have to pass instructions to the loop that were already checked in the 
firs pass.  I have updated this piece accordingly.

> > +		unsigned long mask = (!mips_opts.micromips
> > +				      ? OP_MASK_CODE
> > +				      : MICROMIPSOP_MASK_CODE);
> 
> 
> 		unsigned long mask = (mips_opts.micromips
> 				      ? MICROMIPSOP_MASK_CODE
> 				      : OP_MASK_CODE);
> 
> Several other cases.

 As above.

> > +	    case 'J':
> > +	      if (!mips_opts.micromips)
> > +		{		/* 19-bit WAIT code.  */
> > +		  my_getExpression (&imm_expr, s);
> > +		  check_absolute_expr (ip, &imm_expr);
> > +		  if ((unsigned long) imm_expr.X_add_number > OP_MASK_CODE19)
> > +		    {
> > +		      as_warn (_("Illegal 19-bit code (%lu)"),
> > +			       (unsigned long) imm_expr.X_add_number);
> > +		      imm_expr.X_add_number &= OP_MASK_CODE19;
> > +		    }
> > +		  INSERT_OPERAND (0, CODE19, *ip, imm_expr.X_add_number);
> > +		  imm_expr.X_op = O_absent;
> > +		  s = expr_end;
> > +		  continue;
> >  		}
> > -	      INSERT_OPERAND (CODE19, *ip, imm_expr.X_add_number);
> > -	      imm_expr.X_op = O_absent;
> > -	      s = expr_end;
> > -	      continue;
> > +	      goto do_reg;	/* ALNV.PS source register.  */
> 
> So 'J' is used for different things depending on micromips mode?
> Couldn't we use a different letter instead?

 Picked 'y' then.

 While doing this I noticed we have a bug.  In a sequence like this:

	alnv.ps	$f0, $f1, $f2, $3
	jalr	$3, $2

the ALNV.PS will get reordered into the delay slot.  This is obviously 
wrong.

 I'll post a trivial fix for standard MIPS code separately.  For microMIPS 
code we'd have to take one of the precious pinfo flags (which we've run 
out of, although one can be reclaimed with the SYNC change I mentioned 
above) for the purpose of this lone instruction and we don't do branch 
swapping anyway, so I've just disabled ALNV.PS reordering altogether.

> > +		      if (!mips_opts.micromips)
> > +			INSERT_OPERAND (0, RD, *ip, regno);
> > +		      else
> > +			INSERT_OPERAND (1, RS, *ip, regno);
> 
> 		      if (mips_opts.micromips)
> 			INSERT_OPERAND (1, RS, *ip, regno);
> 		      else
> 			INSERT_OPERAND (0, RD, *ip, regno);

 Ditto.

> > +		  if (!ok)
> > +		    {
> > +		      switch (*args++)
> 
> I realise you've copied this from elsewhere, but why "++"?
> The "for" loop increments "args", doesn't it?

 This is the same as for 'r', etc. (i.e. a register that's optional in the 
source if the destination is the same as the target).  Otherwise code 
like:

	andi16	$7, 65535
	addiu16	$31, 7

fails to assemble.  The thing is once we get to "65535", we still have a 
"," unconsumed in args.  I have rewritten it more properly though, adding 
a check for that "," too.

> > +		      if (c == 'e')
> > +			{
> > +			  regno = lastregno;
> > +			  s = s_reset;
> > +			  ++args;
> > +			}
> > +		      else if (c == 't')
> > +			{
> > +			  s = s_reset;
> > +			  ++args;
> > +			  continue;
> > +			}
> 
> I don't really understand these "args" adjustments either.

 Likewise:

	subu16	$2, $3
	xor16	$2, $3

> > +		    i = my_getSmallExpression (&imm_expr, imm_reloc, s);
> > +		    if ((i == 0 && (imm_expr.X_op != O_constant
> > +				    || (imm_expr.X_add_number & 3) != 0
> > +				    || imm_expr.X_add_number > (63 << 2)
> > +				    || imm_expr.X_add_number < (-64 << 2)))
> > +			|| i > 0)
> > +		      {
> > +			imm_expr.X_op = O_absent;
> > +			break;
> > +		      }
> > +		    immed = imm_expr.X_add_number >> 2;
> > +		    INSERT_OPERAND (1, IMMA, *ip, immed);
> > +		    imm_expr.X_op = O_absent;
> > +		    s = expr_end;
> > +		    continue;
> 
> Why set X_op to O_absent when rejecting this alternative?  What breaks
> if you leave the constant in imm_expr?  I couldn't see any similar
> error-handling code in this function.

 I believe the reason is if the offset does not fit for the purpose of 
this 16-bit encoding, then we'll fall back to a 32-bit one that uses 
offset_expr instead.  So we have to mark imm_expr absent not to confuse 
code elsewhere (in md_assemble(), presumably).  Yeah, I know in this case 
both should be equal, but it looks sloppy to me to use a stale value from 
a previous pass.  And obviously you wouldn't see this case before as no 
standard MIPS instruction switches from imm_expr to offset_expr between 
encodings.

 That written, I have given it some thinking and decided to use local 
variables instead removing any references to imm_expr and thus any issue 
about its usage.  We don't pass the results up to append_insn() from here 
in any case.

> Also:
> 
> 		    if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
> 			&& imm_expr.X_op == O_constant
> 			&& (imm_expr.X_add_number & 3) == 0
> 			&& imm_expr.X_add_number >= (-64 << 2)
> 			&& imm_expr.X_add_number <= (63 << 2))
> 		      {
> 			immed = imm_expr.X_add_number >> 2;
> 			INSERT_OPERAND (1, IMMA, *ip, immed);
> 			imm_expr.X_op = O_absent;
> 			s = expr_end;
> 			continue;
> 		      }
> 		    break;
> 
> seems more in keeping with other my_getSmallExpression users.

 I disagree, see 'i'/'j', 'o', etc.  The path of acceptance in almost all 
the case selectors of this switch statement is fall-through.  Any failure 
breaks midway through.

 I have adjusted this sequence slightly though and factored out 
conditions around the expression as the pattern repeats on and on 
throughout this switch statement.  This has led to quite nice code IMO.

> > +		    i = my_getSmallExpression (&imm_expr, imm_reloc, s);
> > +
> > +		    for (immb = 0; immb < 8; immb++)
> > +		      {
> > +			if (micromips_imm_b_map[immb]
> > +			    == imm_expr.X_add_number)
> > +			  break;
> > +		      }
> > +		    if ((i == 0 && (imm_expr.X_op != O_constant || immb == 8))
> > +			|| i > 0)
> > +		      {
> > +			imm_expr.X_op = O_absent;
> > +			break;
> > +		      }
> > +		    INSERT_OPERAND (1, IMMB, *ip, immb);
> > +		    imm_expr.X_op = O_absent;
> > +		    s = expr_end;
> > +		    continue;
> 
> Here too I'd prefer something like:
> 
> 		    if (my_getSmallExpression (&imm_expr, imm_reloc, s) == 0
> 			&& imm_expr.X_op == O_constant)
> 		      {
> 			for (immb = 0; immb < 8; immb++)
> 			  if (micromips_imm_b_map[immb]
> 			      == imm_expr.X_add_number)
> 			    break;
> 			if (immb < 8)
> 			  {
> 			    INSERT_OPERAND (1, IMMB, *ip, immb);
> 			    imm_expr.X_op = O_absent;
> 			    s = expr_end;
> 			    continue;
> 			  }
> 		      }
> 		    break;
> 
> which has the added benefit of only using X_add_number once we've
> established that it's meaningful.  Similar changes in the rest
> of the function.

 Likewise.  I agree about the imm_expr's usage and have taken it into 
account.

> > +		  /* If users want relax branch and don't specify to use
> > +		     16-bit instructions, we will not match this pattern.
> > +		     This will lead to matching 32-bit instructions, that
> > +		     will be relaxed later.  */
> > +		  if (mips_relax_branch && forced_insn_length != 2)
> > +		    break;
> 
> This seems a bit lame.  It should be easy to relax the 16-bit form
> in the same way as the 32-bit form.  We could use a bit in the
> relaxation opcode to say whether the extra relaxation should be
> enabled or not, i.e. a bit to record the relevant parts of this
> condition:
> 
> +	   && (pinfo & INSN_UNCOND_BRANCH_DELAY
> +	       || pinfo & INSN_COND_BRANCH_DELAY)
> +	   && mips_relax_branch
> +	   /* Don't try branch relaxation within .set nomacro, or within
> +	      .set noat if we use $at for PIC computations.  If it turns
> +	      out that the branch was out-of-range, we'll get an error.  */
> +	   && !mips_opts.warn_about_macros
> +	   && (mips_opts.at || mips_pic == NO_PIC)
> +	   && mips_opts.micromips
> +	   /* Don't try branch relaxation, when users specify 16-bit/32-bit
> +	      instructions.  */
> +	   && !forced_insn_length)
> 
> No need to do that as part of this patch, but let's at least put in
> a FIXME.

 Indeed; we have a preexisting bug here as well -- mips_opts.at may well 
be != ATREG.  (A similar bug is present in fix_loongson2f_jump() BTW).

 Actually I've thought it's lame enough to implement it.  In the course of 
which I discovered (and fixed) other three bugs, so I think it was worth 
the effort.  Sent as a sepate patch for the same reasons as the reloc 
change above.

> > +		case 'N':	/* Register list for lwm and swm.  */
> > +		  {
> > +		    unsigned int reg_list = 0;
> > +		    int immed = 0;
> > +		    unsigned int reg1 = 33;
> 
> Why 33 rather than 32?  Seems INVALID_REG could be used here for a bit
> of extra readability.

 No idea; this piece is now gone anyway.

> > +		    /* s0, ra
> > +		       s0, s1, ra
> > +		       s0, s1, s2, ra
> > +		       s0, s1, s2, s3, ra
> > +		       s0-s1, ra
> > +		       s0-s2, ra
> > +		       s0-s3, ra */
> 
> You also allow:
> 
>     s1, ra, s2, s0
> 
> (rightly IMO), so I don't think we gain much by listing the split-out ranges.
> Just:
> 
> 		    /* s0, ra
> 		       s0-s1, ra
> 		       s0-s2, ra
> 		       s0-s3, ra */
> 
> would be OK.

 I have rewritten it adding an explanatory comment.

> > +			s_reset = s;
> > +			SKIP_SPACE_TABS (s);
> > +			if (*s == ',')
> > +			  {
> > +			    reg1 = 33;
> > +			    ++s;
> > +			  }
> > +			else if (*s == '-')
> > +			  {
> > +			    reg1 = regno;
> > +			    ++s;
> > +			  }
> > +			SKIP_SPACE_TABS (s);
> > +			ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno);
> > +			if (!ok)
> > +			  {
> > +			    s = s_reset;
> > +			    break;
> > +			  }
> 
> Shouldn't we break out if *s isn't ',' or '-' and treat it as a syntax
> error ("reg_list = 0; break;")?

 We should break out, but that's not a syntax error as far as this handler 
is concerned.  It's up to code elsewhere to decide what the token to 
follow, if any, has to be based on args.  This is now handled properly.

> > +			    if (regno <= reg1)
> > +			      {
> > +				reg_list = 0;
> > +				break;
> > +			      }
> 
> Add a comment saying that this is an error condition.  But is there
> really anything wrong with $4-$4 (regno == reg1)?  The range is closed
> after all.

 Agreed, I have now allowed it under the "be liberal what you accept" 
principle.

> > +		      }
> > +		    if (i == 0 && imm_expr.X_op == O_constant
> > +			&& (imm_expr.X_add_number & 3) == 0
> > +			&& imm_expr.X_add_number >= (-4194304 << 2)
> > +			&& imm_expr.X_add_number <= (4194303 << 2))
> 
> I'm ashamed to say this decimal number wasn't in my mental power-of-2 list.
> Maybe a hex constant or (1 << n) would be better?  Feel free to leave it
> if you disagree though.

 I don't, actually.  Offhand, the decimal value is meaningless to me too.

> > +	    case 'n':		/* Register list for 32-bit lwm and swm.  */
> > +	      gas_assert (mips_opts.micromips);
> > +	      {
> > +		unsigned int reg_list = 0;
> > +		int immed = 0;
> > +		unsigned int reg1 = 33;
> > +
> 
> This register-range code needs to be split out into a separate function.
> It's the same as for 'N' above (except for the s8 handling, which would
> be OK-but-redundant for 'n' too), has the same apparent bug regarding
> syntax checking, and has the same questionable behaviour about
> single-register ranges.

 Agreed.  I have now reimplemented is almost from scratch.  While doing it 
I have noticed the arguments are actually wiped of whitespace at this 
point, so I have removed references to SKIP_SPACE_TABS().  It looks to me 
the macro and its two references in mips16_ip() can be removed altogether.

> > +		/* s0, ra
> > +		   s0, s1, ra
> > +		   s0, s1, s2, ra
> > +		   s0, s1, s2, s3, ra
> > +		   s0, s1, s2, s3, s4, ra
> > +		   s0, s1, s2, s3, s4, s5, ra
> > +		   s0, s1, s2, s3, s4, s5, s6, ra
> > +		   s0, s1, s2, s3, s4, s5, s6, s7, ra
> > +		   s0, s1, s2, s3, s4, s5, s6, s7, s8, ra
> > +		   ra,
> > +		   s0-s1, ra
> > +		   s0-s2, ra
> > +		   s0-s3, ra
> > +		   s0-s4, ra
> > +		   s0-s5, ra
> > +		   s0-s6, ra
> > +		   s0-s7, ra
> > +		   s0-s8, ra */
> 
> I'm hampered by the spec not being public yet, but it looks from the
> code as though RA's actually optional when S0 is present.  The comment
> implies otherwise.  Also:

 Both are optional, except at least one register has to be present and the 
range of static registers has to start at s0 and be contiguous.  (Though 
as a side note I'm not sure why a single register is officially supported 
by the ASE for this instruction at all -- being equivalent to LD/LW/SD/SW 
it could well be a reserved encoding.)

> > +		if (reg_list == 0x00010000)
> > +		  immed = 1;
> > +		else if (reg_list == 0x00030000)
> > +		  immed = 2;
> > +		else if (reg_list == 0x00070000)
> > +		  immed = 3;
> > +		else if (reg_list == 0x000f0000)
> > +		  immed = 4;
> > +		else if (reg_list == 0x001f0000)
> > +		  immed = 5;
> > +		else if (reg_list == 0x003f0000)
> > +		  immed = 6;
> > +		else if (reg_list == 0x007f0000)
> > +		  immed = 7;
> > +		else if (reg_list == 0x00ff0000)
> > +		  immed = 8;
> > +		else if (reg_list == 0x40ff0000)
> > +		  immed = 9;
> > +		else if (reg_list == 0x80000000)
> > +		  immed = 16;
> > +		else if (reg_list == 0x80010000)
> > +		  immed = 17;
> > +		else if (reg_list == 0x80030000)
> > +		  immed = 18;
> > +		else if (reg_list == 0x80070000)
> > +		  immed = 19;
> > +		else if (reg_list == 0x800f0000)
> > +		  immed = 20;
> > +		else if (reg_list == 0x801f0000)
> > +		  immed = 21;
> > +		else if (reg_list == 0x803f0000)
> > +		  immed = 22;
> > +		else if (reg_list == 0x807f0000)
> > +		  immed = 23;
> > +		else if (reg_list == 0x80ff0000)
> > +		  immed = 24;
> > +		else if (reg_list == 0xc0ff0000)
> > +		  immed = 25;
> > +		else
> > +		  break;
> 
> this could at least be simplified by testing the Sn and RA registers
> separately, then rejecting immed == 0.  But maybe the split-out function
> could return the Sn range in a more easily digestible form.

 No need to.  This can be easily dealt with with ffs(), benefitting hosts 
that have good support for this operation, such as MIPS architecture 
processors and their CLZ instruction :) (x86 has BSF and we care even less 
about any others, don't we?).

> > +	  /* For microMIPS we need to save the value to buf + 2.  */
> > +	  if (target_big_endian || fixP->fx_r_type == BFD_RELOC_MICROMIPS_LO16)
> >  	    buf += 2;
> 
> 	  /* 32-bit microMIPS instructions are divided into two 16-bit pieces.
> 	     Relocations always refer to the second piece, regardless of
> 	     endianness.  */
> 
> or something like that.  I'm sure there's a better term than "piece" here,
> what does the spec call it?

 Halfword.

> > +    fragp->fr_subtype
> > +      = toofar ? RELAX_MICROMIPS_MARK_TOOFAR (fragp->fr_subtype)
> > +	       : RELAX_MICROMIPS_CLEAR_TOOFAR (fragp->fr_subtype);
> 
> Non-standard alignment for ":"
> 
>     fragp->fr_subtype = (toofar
>     		      	 ? RELAX_MICROMIPS_MARK_TOOFAR (fragp->fr_subtype)
> 			 : RELAX_MICROMIPS_CLEAR_TOOFAR (fragp->fr_subtype);

 Fixed.

> > +      /* 00000000 <test>:
> > +            0:       405e 0006       bgez    $30,10 <test+0x10>
> > +            4:       0c00            nop
> > +            6:       fc3c 0002       lw      $1,2($28)
> > +                             6: R_MIPS_GOT16 .text
> > +            a:       3021 0011       addiu   $1,$1,17
> > +                             a: R_MIPS_LO16  .text
> > +            e:       4721            jalr    $1
> > +             ...
> > +
> > +         00020010 <test2>:
> > +            20010:       0c00            nop
> > +            20012:       0c00            nop
> > +       */
> > +
> > +      if (!fragp && update > 0)
> > +	length += 6;
> > +
> > +      if (mips_pic != NO_PIC)
> > +	{
> > +	  /* Additional space for PIC loading of target address.  */
> > +	  length += 6;
> > +	}
> > +
> > +      /* If branch is conditional.  */
> > +      if (fragp ? !RELAX_MICROMIPS_UNCOND (fragp->fr_subtype) : (update >= 0))
> > +	length += 6;
> > +    }
> 
> This really isn't written very clearly.  The comment has a single
> long-branch form, while the code has three if statements.  Say what
> you're counting in each case.

 The first conditional is bogus and also dead code.  It looks like it was 
copied from relaxed_branch_length() where it is used to handle 
branch-likely relaxation, further adjusted towards removal and then left.  
I have removed it altogether now.

 I've cooked up some comments for the remaining cases.  I decided to 
switch to the source notation and quoted instruction byte counts 
explicitly.

> > +  /* For microMIPS PC relative relocations, we cannot convert it to
> > +     against a section.  If we do, it will mess up the fixp->fx_offset.  */
> >    if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
> > -      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
> > +      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
> > +      || fixp->fx_r_type == BFD_RELOC_MICROMIPS_7_PCREL_S1
> > +      || fixp->fx_r_type == BFD_RELOC_MICROMIPS_10_PCREL_S1
> > +      || fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
> 
> "to be against a section".  That's not a helpful comment though.
> _How_ will it mess up fixp->fx_offset?  Give the reader a clue why
> the problem applies to BFD_RELOC_MICROMIPS_16_PCREL_S1 but not
> to something like BFD_RELOC_16_PCREL_S2.

 I have failed to spot any problems with this hunk reverted and I'm not 
sure what I should be looking for.  Therefore I feel a bit uneasy about 
removing it and only rephrased the comment without actually changing its 
meaning.  Chao-ying, do you have anything to add?

> > +	  if (RELAX_MICROMIPS_UNCOND (fragp->fr_subtype))
> > +	    goto uncond_micromips;
> 
> Ugh.  Either split out the code for unconditional branches into a subfunction,
> or put intervening code into a:
> 
> 	  if (!RELAX_MICROMIPS_UNCOND (fragp->fr_subtype))
> 
> block.  (Yes, I know the current relaxation code has the same kind of goto,
> but I would have raised just the same objection there.  If cut-&-paste really
> is necessary, the new code should still be defendable in its own right.)

 Fixed.

> > +      buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
> 
> Missing space before "fragp->fr_literal".  A few other occurences.

 Fixed.

> > +	  if (RELAX_MICROMIPS_LINK (fragp->fr_subtype))
> > +	    {
> > +	      /* Clear the and-link bit.  */
> > +	      gas_assert ((insn & 0xffa00000) == 0x40200000);
> > +
> > +	      /* bltzal		0x04100000	bgezal	0x04110000 */
> > +	      insn &= ~0x00200000;
> > +	    }
> 
> Excess cut-&-paste.  The opcodes in the comment are from the normal MIPS
> encoding, not the microMIPS one.  (Wondered at first why we were clearing
> a bit that, according to the comment, wasn't supposed to be set in the
> first place.)

 Worse yet, we don't handle BGEZALS and BLTZALS correctly.  Fixed that as 
well (and adjusted test cases to include these instructions).

> > +	  /* How many bytes in instructions we've already emitted?  */
> > +	  i = buf - (bfd_byte *)fragp->fr_literal - fragp->fr_fix;
> > +	  /* How many bytes in instructions from here to the end?  */
> > +	  i = fragp->fr_var - i;
> 
> I don't get this.  "buf" still equals "fragp->fr_literal + fragp->fr_fix",
> doesn't it?  We haven't emitted anything yet.  Seems to me that this is
> (and should be) the same as "i = fragp->fr_var".

 We fail to use compact branches here and rely on linker relaxation to do 
so.  This is inferior (especially as linker relaxation is optional; it 
doesn't handle all the cases either), but better than nothing.  It relies 
on the presence of relocations though, so I have rewritten this sequence 
to emit labels and use them as branch targets instead, getting rid of this 
piece you're questioning as a side effect altogether.

 For compact branches to be used here I think we need to add another flag 
to RELAX_MICROMIPS_ENCODE() so that 
relaxed_micromips_32bit_branch_length() can calculate the correct length 
(contrary to generic documentation the original opcode is not available in 
md_relax_frag() on the MIPS target and when we get to md_convert_frag() 
it's already too late for shrinking the frag.

 The lack of use of compact branches here does not make code produced 
incorrect though, so that makes it an option for future improvement and I 
will not work on it now. [FIXME]

> > +	uncond_micromips:
> > +	  if (mips_pic == NO_PIC)
> > +	    {
> > +	      /* j or jal.  */
> 
> "j(al) <sym>  R_MICROMIPS_26_S1"
> 
> to match the style of the other comments (and to give a bit more info).

 Adjusted as reasonable (though I fail to see a consistent style 
throughout this function).

> > +	      /* lw/ld $at, <sym>($gp)  R_MIPS_GOT16 */
> > +	      insn = 0xfc3c0000;
> > +	      exp.X_op = O_symbol;
> > +	      exp.X_add_symbol = fragp->fr_symbol;
> > +	      exp.X_add_number = fragp->fr_offset;
> 
> Add the "ld" case or fix the comment.  Also s/R_MIPS_GOT16/R_MICROMIPS_LO16/.
> 
> > +	      /* d/addiu $at, $at, <sym>  R_MIPS_LO16 */
> > +	      insn = 0x30210000;
> 
> Likewise "daddiu".

 I have added the alternative encodings.  Overall 64-bit support is quite 
rudimentary at most.

> > +      gas_assert (buf == (bfd_byte *)fragp->fr_literal
> > +			 + fragp->fr_fix + fragp->fr_var);
> 
> The "+" isn't indented far enough.

 There was a pair of brackets missing here actually.

> > Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips1-fp.d
> > ===================================================================
> > --- binutils-fsf-trunk-quilt.orig/gas/testsuite/gas/mips/mips1-fp.d	2010-12-07 00:05:05.000000000 +0000
> > +++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips1-fp.d	2010-12-07 00:14:47.000000000 +0000
> > @@ -9,4 +9,4 @@
> >  [0-9a-f]+ <.*>:
> >  .*:	46041000 	add.s	\$f0,\$f2,\$f4
> >  .*:	44420000 	cfc1	\$2,\$0
> > -#pass
> > +	\.\.\.
> > Index: binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips1-fp.s
> > ===================================================================
> > --- binutils-fsf-trunk-quilt.orig/gas/testsuite/gas/mips/mips1-fp.s	2010-12-07 00:05:05.000000000 +0000
> > +++ binutils-fsf-trunk-quilt/gas/testsuite/gas/mips/mips1-fp.s	2010-12-07 00:14:47.000000000 +0000
> > @@ -5,3 +5,7 @@
> >  foo:
> >  	add.s	$f0,$f2,$f4
> >  	cfc1	$2,$0
> > +
> > +# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
> > +	.align	2
> > +	.space	8
> 
> Leave out this kind of change.  I realise it's not the style you prefer,
> but what's there now is fine.  Same for:
> 
> * gas/testsuite/gas/mips/mips32r2-fp32.d
> * gas/testsuite/gas/mips/mips64.d

 Well, that's not merely a matter of style as #pass simply ignores any 
following rubbish GAS may have produced.  This forces a corresponding 
update to gas/testsuite/gas/mips/micromips@mips1-fp.d as the results 
differ between Linux and bare-iron targets.  I'd prefer to avoid adding 
new instances of #pass although I've just noticed the original change 
included some other too, so I've applied your suggestion reluctantly.  

 These test cases should really be all audited and unjustified uses of 
#pass removed -- I realise some people have difficulties following all 
the details of and good ways to deal with subtleties in this area and 
follow the path of least resistance, but we shouldn't be encouraging this 
kind of behaviour.  Especially as you seem to be quite picky elsewhere. ;)

> >        msubu   $11, $12
> >        mul     $13, $14, $15
> >        pref    4, ($16)
> > +      .set at
> >        pref    4, 32767($17)
> >        pref    4, -32768($18)
> > +      .set noat
> >        ssnop
> >  
> >  
> >        # privileged instructions
> >  
> >        cache   5, ($1)
> > +      .set at
> >        cache   5, 32767($2)
> >        cache   5, -32768($3)
> > -      .set at
> >        cache   5, 32768($4)
> >        cache   5, -32769($5)
> >        cache   5, 32768
> 
> We should really have separate noat tests for the prefs and caches
> that are no longer in a noat block (a bit like you did for the
> wait and sdbbp tests whose immediates have changed).
> 
> > -#define STO_MIPS_PLT		0x8
> > +#define STO_MIPS_PLT		(1 << 3)
> 
> Don't change the definitions of the existing constants; use hex constants
> for the new stuff instead.

 Well, STO_OPTIONAL already uses a shifted bit and I find this notation 
clearer.  Since code is already inconsistent I have updated it not to 
change the existing definitions, but kept newly-added ones as shifted 
bitfields.  I'm happy to keep code consistent, but if a piece is not, I 
will choose the style that suits me better, sorry.

> >  /* This value is used to mark PIC functions in an object that mixes
> > -   PIC and non-PIC.  */
> > -#define STO_MIPS_PIC		0x20
> > -#define ELF_ST_IS_MIPS_PIC(OTHER) \
> > -  (((OTHER) & ~ELF_ST_VISIBILITY (-1)) == STO_MIPS_PIC)
> > -#define ELF_ST_SET_MIPS_PIC(OTHER) \
> > -  (STO_MIPS_PIC | ELF_ST_VISIBILITY (OTHER))
> > +   PIC and non-PIC.  Note this bit overlaps with STO_MIPS16.  */
> > +#define STO_MIPS_PIC		(1 << 5)
> > +#define ELF_ST_IS_MIPS_PIC(other) (((other) & STO_MIPS_FLAGS) == STO_MIPS_PIC)
> > +#define ELF_ST_SET_MIPS_PIC(other) (((other) & ~STO_MIPS_FLAGS) | STO_MIPS_PIC)
> 
> /* This value is used to mark PIC functions in an object that mixes
>    PIC and non-PIC.  Note that this bit overlaps with STO_MIPS16,
>    although MIPS16 symbols are never considered to be MIPS_PIC.  */

 Applied.

> > +/* Whether code compression (either of the MIPS16 or the microMIPS ASEs)
> > +   has been indicated for a .text symbol.  */
> > +#define ELF_ST_IS_COMPRESSED(other) \
> > +  (ELF_ST_IS_MIPS16(other) || ELF_ST_IS_MICROMIPS(other))
> 
> The last line is missing a space before each "(other)".

 Fixed.

> > +/* microMIPS placeholders.  */
> 
> Should be a bit more descriptive.  E.g.:
> 
> /* Every MICROMIPSOP_X definition requires a corresponding OP_X
>    definition, and vice versa.  This simplifies various parts
>    of the operand handling in GAS.  The fields below only exist in
>    the microMIPS encoding, so define each one to have an empty range.  */
> 
> if indeed that's accurate.

 Yes, thanks.  Updated INSERT_OPERAND() and EXTRACT_OPERAND() macros rely 
on these definitions for cases where the ISA selector is hardcoded as code 
has to be syntactically correct even if optimised away.

> > +/* These are the bitmasks and shift counts used for the different
> > +   fields in the instruction formats.  Other than OP, no masks are
> > +   provided for the fixed portions of an instruction, since they are
> > +   not needed.  */
> 
> Seems like too much cut-&-paste: there isn't an OP field here.
> "Other than TARGET", perhaps, unless there are other opcode masks here.

 This looks like copied verbatim from the MIPS16 part.  The two parts are 
functionally equivalent and my understanding of the comment is no masks 
are provided for the non-operand parts of instruction.  I've left the 
comment as is; I'm not sure what TARGET might mean in this context, please 
elaborate.

> > +/* MIPS placeholders.  */
> 
> /* Placeholders for fields that only exist in the traditional 32-bit
>    instruction encoding; see the comment above for details.  */

 Thanks.

> > +   "mg" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MG) at bit 0
> > +   "mg" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MG) at bit 0
> 
> Doubled line.

 Fixed.

> > -      Elf_Internal_Ehdr *header;
> > +      Elf_Internal_Ehdr *header = elf_elfheader (info->section->owner);
> >  
> > -      header = elf_elfheader (info->section->owner);
> 
> What's there now is fine.

 Adjusted.

> > +			else
> > +			    iprintf (is, "UNKNOWN");
> 
> Excess indentation.

 Fixed.

> > +		     In microMIPS, we need to match instructions (mfc0, mtc0)
> > +		     by hand.  */
> 
> Something like:
> 
> 		     The microMIPS encoding does not have a coprocessor
> 		     identifier field as such, so we must work out the
> 		     coprocessor number by looking at the opcode.  */
> 
> might be more descriptive.

 OK, thanks.

> > +/* Return 1 if a symbol associated with the location being disassembled
> > +   indicates a compressed mode, either MIPS16 or microMIPS one.  Otherwise,
> > +   return 0.  */
> 
> Reads more naturally to me without "one".

 Both MIPS16 and microMIPS are adjectives; they need a noun or a pronoun.  
I realise this requirement is not met everywhere, but that doesn't mean we 
should add new such places IMO.

> > +  for (i = 0; i < info->num_symbols; i++)
> > +    {
> > +      pos = info->symtab_pos + i;
> > +
> > +      if (bfd_asymbol_flavour (info->symtab[pos]) != bfd_target_elf_flavour)
> > +	continue;
> > +
> > +      symbol = (elf_symbol_type *) info->symtab[pos];
> > +      if ((!micromips_ase
> > +	   && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
> > +	  || (micromips_ase
> > +	      && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
> > +	    return 1;
> > +    }
> 
> Why is a search necessary here, when the previous code was happy to
> look only at the first symbol?  I'm not saying the code is wrong,
> but a bit of commentary would be good.

 My feeling is previous code was not "happy", but simply untested (or to 
be more accurate, not tested satisfactorily).

 Symbols sharing the same address are sorted alphabetically here which 
becomes a problem when they include both objects and functions (or symbols 
derived from standard MIPS functions defined elsewhere).  Disassembly 
shouldn't yield different results based merely on the names of symbols 
chosen and given the semantics of the compressed annotation (it is only 
added to a function symbol if a genuine instruction has been emitted 
following immediately in the source code) I think it should take 
precedence, so we check if any symbol has one.

 Perhaps we should only check function symbols in case st_other is 
overloaded for object symbols, but I think that would be overengineering.  
Whoever adds any overlapping flags should be required to audit existing 
code; that shouldn't be too difficult to do.

> What problem is the ld-lib.exp change fixing?

 Currently you can't build the same source file multiple times with 
different flags.  See ld/testsuite/ld-mips-elf/mips16-and-micromips.d for 
a use case (and try it with the ld-lib.exp piece reverted).  I think the 
framework shouldn't be limiting the developer like this and making a copy 
of the source to work around the limitation sounds to me like the wrong 
direction to go.

 I made several adjustments and bug fixes as I saw fit on my own too and 
for documentation purposes included a commented out microMIPS64 48-bit LI 
instruction that takes a 32-bit signed immediate argument.

 While support for 64-bit microMIPS is only rudimentary and I don't plan 
to work on any improvement at the moment long-term we need to think about 
how to handle this instruction; the most straightforward approach would be 
to reliably extend match/mask to 64 bits.  Our 64-bit integer type support 
on 32-bit hosts seem to be lacking though and there are several places 
throughout GAS where such values are truncated.  It would increase the 
amount of space taken by opcode tables noticeably on 32-bit hosts too (but 
we already waste a lot of space by using a "long" type on 64-bit hosts 
where unnecessary).

 What fits best here are ISO C9x <stdint.h> types -- do you happen to know 
if binutils maintainers ever plan to deploy them?  We've been using 
autoconf since the beginning of time and it has straightforward ways to 
define replacement types of a required width and target code frequently 
operates on quantities that have a predefined width so making use of 
fixed-width types seems natural.

 I have made several obvious changes to the original diff to address 
modifications made to repository that are not included here as they were 
required for the patch to apply at all after a tree update in the first 
place.  All of them were mechanical; most notably <opcode/mips.h> INSN2_* 
have been renumbered according to additional flag consumption.  As 
mentioned earlier, we're running out of these flags now.

 Finally, for a reference, I'm including updated ChangeLogs.  They refer 
to the whole set of changes combined as the updates are not meant to be 
committed separately.  None of the separate bug fixes mentioned throughout 
are covered though; I'll be sending them with their corresponding entries 
and descriptions on their own shortly.

  Maciej

binutils-20110221-umips-fix.diff
binutils-20110221-umips-relax16.diff
binutils-20110221-umips-fix-reloc.diff
[Patches attached compressed due to their size.]

bfd/
2011-02-21  Chao-ying Fu  <fu@mips.com>
            Ilie Garbacea  <ilie@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>
            Joseph Myers  <joseph@codesourcery.com>
            Catherine Moore  <clm@codesourcery.com>

	* archures.c (bfd_mach_mips_micromips): New macro.
	* cpu-mips.c (I_micromips): New enum value.
	(arch_info_struct): Add bfd_mach_mips_micromips.
	* elfxx-mips.h (_bfd_mips_elf_is_target_special_symbol): New
	prototype.
	(_bfd_mips_elf_relax_section): Likewise.
	(_bfd_mips16_elf_reloc_unshuffle): Rename to...
	(_bfd_mips_elf_reloc_unshuffle): ... this.  Handle microMIPS
	ASE.
	(_bfd_mips16_elf_reloc_shuffle): Rename to...
	(_bfd_mips_elf_reloc_shuffle): ... this.  Handle microMIPS ASE.
	(gprel16_reloc_p): Handle microMIPS ASE.
	(literal_reloc_p): New function.
	* elf32-mips.c (elf_micromips_howto_table_rel): New variable.
	(_bfd_mips_elf32_gprel16_reloc): Handle microMIPS ASE.
	(mips16_gprel_reloc): Update for _bfd_mips_elf_reloc_unshuffle
	and _bfd_mips_elf_reloc_shuffle changes.
	(mips_elf_gprel32_reloc): Update comment.
	(micromips_reloc_map): New variable.
	(bfd_elf32_bfd_reloc_type_lookup): Handle microMIPS ASE.
	(mips_elf32_rtype_to_howto): Likewise.
	(mips_info_to_howto_rel): Likewise.
	(bfd_elf32_bfd_is_target_special_symbol): Define.
	(bfd_elf32_bfd_relax_section): Likewise.
	* elf64-mips.c (micromips_elf64_howto_table_rel): New variable.
	(micromips_elf64_howto_table_rela): Likewise.
	(mips16_gprel_reloc): Update for _bfd_mips_elf_reloc_unshuffle
	and _bfd_mips_elf_reloc_shuffle changes.
	(micromips_reloc_map): Likewise.
	(bfd_elf64_bfd_reloc_type_lookup): Handle microMIPS ASE.
	(bfd_elf64_bfd_reloc_name_lookup): Likewise.
	(mips_elf64_rtype_to_howto): Likewise.
	(bfd_elf64_bfd_is_target_special_symbol): Define.
	* elfn32-mips.c (elf_micromips_howto_table_rel): New variable.
	(elf_micromips_howto_table_rela): Likewise.
	(mips16_gprel_reloc): Update for _bfd_mips_elf_reloc_unshuffle
	and _bfd_mips_elf_reloc_shuffle changes.
	(micromips_reloc_map): Likewise.
	(bfd_elf32_bfd_reloc_type_lookup): Handle microMIPS ASE.
	(bfd_elf32_bfd_reloc_name_lookup): Likewise.
	(mips_elf_n32_rtype_to_howto): Likewise.
	(bfd_elf32_bfd_is_target_special_symbol): Define.
	* elfxx-mips.c (LA25_LUI_MICROMIPS_1): New macro.
	(LA25_LUI_MICROMIPS_2): Likewise.
	(LA25_J_MICROMIPS_1, LA25_J_MICROMIPS_2): Likewise.
	(LA25_ADDIU_MICROMIPS_1, LA25_ADDIU_MICROMIPS_2): Likewise.
	(TLS_RELOC_P): Handle microMIPS ASE.
	(mips_elf_create_stub_symbol): Adjust value of stub symbol if
	target is a microMIPS function.
	(micromips_reloc_p): New function.
	(micromips_reloc_shuffle_p): Likewise.
	(got16_reloc_p, call16_reloc_p): Handle microMIPS ASE.
	(got_disp_reloc_p, got_page_reloc_p): New functions.
	(got_ofst_reloc_p): Likewise.
	(got_hi16_reloc_p, got_lo16_reloc_p): Likewise.
	(call_hi16_reloc_p, call_lo16_reloc_p): Likewise.
	(hi16_reloc_p, lo16_reloc_p, jal_reloc_p): Handle microMIPS ASE.
	(micromips_branch_reloc_p): New function.
	(tls_gd_reloc_p, tls_ldm_reloc_p): Likewise.
	(tls_gottprel_reloc_p): Likewise.
	(_bfd_mips16_elf_reloc_unshuffle): Rename to...
	(_bfd_mips_elf_reloc_unshuffle): ... this.  Handle microMIPS
	ASE.
	(_bfd_mips16_elf_reloc_shuffle): Rename to...
	(_bfd_mips_elf_reloc_shuffle): ... this.  Handle microMIPS ASE.
	(_bfd_mips_elf_lo16_reloc): Handle microMIPS ASE.
	(mips_tls_got_index, mips_elf_got_page): Likewise.
	(mips_elf_create_local_got_entry): Likewise.
	(mips_elf_relocation_needs_la25_stub): Likewise.
	(mips_elf_calculate_relocation): Likewise.
	(mips_elf_perform_relocation): Likewise.
	(_bfd_mips_elf_symbol_processing): Likewise.
	(_bfd_mips_elf_add_symbol_hook): Likewise.
	(_bfd_mips_elf_link_output_symbol_hook): Likewise.
	(mips_elf_add_lo16_rel_addend): Likewise.
	(_bfd_mips_elf_check_relocs): Likewise.
	(mips_elf_adjust_addend): Likewise.
	(_bfd_mips_elf_relocate_section): Likewise.
	(mips_elf_create_la25_stub): Likewise.
	(_bfd_mips_vxworks_finish_dynamic_symbol): Likewise.
	(_bfd_mips_elf_gc_sweep_hook): Likewise.
	(_bfd_mips_elf_is_target_special_symbol): New function.
	(mips_elf_relax_delete_bytes): Likewise.
	(opcode_descriptor): New structure.
	(RA): New macro.
	(OP32_SREG, OP32_TREG, OP16_VALID_REG): Likewise.
	(b_insns_32, bc_insn_32, bz_insn_32, bzal_insn_32): New variables.
	(beq_insn_32): Likewise.
	(b_insn_16, bz_insn_16): New variables.
	(BZC32_REG_FIELD): New macro.
	(bz_rs_insns_32, bz_rt_insns_32): New variables.
	(bzc_insns_32, bz_insns_16):Likewise.
	(BZ16_REG, BZ16_REG_FIELD): New macros.
	(jal_insn_32_bd16, jal_insn_32_bd32): New variables.
	(jal_x_insn_32_bd32): Likewise.
	(j_insn_32, jalr_insn_32): Likewise.
	(ds_insns_32_bd16, ds_insns_32_bd32): Likewise.
	(jalr_insn_16_bd16, jalr_insn_16_bd32, jr_insn_16): Likewise.
	(JR16_REG): New macro.
	(ds_insns_16_bd16): New variable.
	(lui_insn): Likewise.
	(addiu_insn, addiupc_insn): Likewise.
	(ADDIUPC_REG_FIELD): New macro.
	(MOVE32_RD, MOVE32_RS): Likewise.
	(MOVE16_RD_FIELD, MOVE16_RS_FIELD): Likewise.
	(move_insns_32, move_insns_16): New variables.
	(nop_insn_32, nop_insn_16): Likewise.
	(MATCH): New macro.
	(find_match): New function.
	(check_br16_dslot, check_br32_dslot): Likewise.
	(check_br16, check_br32): Likewise.
	(IS_BITSIZE): New macro.
	(_bfd_mips_elf_relax_section): New function.
	(_bfd_mips_elf_merge_private_bfd_data): Disallow linking MIPS16
	and microMIPS modules together.
	(_bfd_mips_elf_print_private_bfd_data):	Handle microMIPS ASE.
	* reloc.c (BFD_RELOC_MICROMIPS_7_PCREL_S1): New relocation.
	(BFD_RELOC_MICROMIPS_10_PCREL_S1): Likewise.
	(BFD_RELOC_MICROMIPS_16_PCREL_S1): Likewise.
	(BFD_RELOC_MICROMIPS_GPREL16): Likewise.
	(BFD_RELOC_MICROMIPS_JMP, BFD_RELOC_MICROMIPS_HI16): Likewise.
	(BFD_RELOC_MICROMIPS_HI16_S): Likewise.
	(BFD_RELOC_MICROMIPS_LO16): Likewise.
	(BFD_RELOC_MICROMIPS_LITERAL): Likewise.
	(BFD_RELOC_MICROMIPS_GOT16): Likewise.
	(BFD_RELOC_MICROMIPS_CALL16): Likewise.
	(BFD_RELOC_MICROMIPS_GOT_HI16): Likewise.
	(BFD_RELOC_MICROMIPS_GOT_LO16): Likewise.
	(BFD_RELOC_MICROMIPS_CALL_HI16): Likewise.
	(BFD_RELOC_MICROMIPS_CALL_LO16): Likewise.
	(BFD_RELOC_MICROMIPS_SUB): Likewise.
	(BFD_RELOC_MICROMIPS_GOT_PAGE): Likewise.
	(BFD_RELOC_MICROMIPS_GOT_OFST): Likewise.
	(BFD_RELOC_MICROMIPS_GOT_DISP): Likewise.
	(BFD_RELOC_MICROMIPS_HIGHEST): Likewise.
	(BFD_RELOC_MICROMIPS_HIGHER): Likewise.
	(BFD_RELOC_MICROMIPS_SCN_DISP): Likewise.
	(BFD_RELOC_MICROMIPS_JALR): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_GD): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_LDM): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_GOTTPREL): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_TPREL_HI16): Likewise.
	(BFD_RELOC_MICROMIPS_TLS_TPREL_LO16): Likewise.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.

binutils/
2011-02-21  Chao-ying Fu  <fu@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* readelf.c (get_machine_flags): Handle microMIPS ASE.
	(get_mips_symbol_other): Likewise.

gas/
2011-02-21  Maciej W. Rozycki  <macro@codesourcery.com>
            Chao-ying Fu  <fu@mips.com>

	* config/tc-mips.h (mips_segment_info): Add one bit for
	microMIPS.
	(TC_LABEL_IS_LOCAL): New macro.
	(mips_label_is_local): New prototype.
	* config/tc-mips.c (S0, S7): New macros.
	(emit_branch_likely_macro): New variable.
	(mips_set_options): Add micromips.
	(mips_opts): Initialise micromips to -1.
	(file_ase_micromips): New variable.
	(CPU_HAS_MICROMIPS): New macro.
	(hilo_interlocks): Set for microMIPS too.
	(gpr_interlocks): Likewise.
	(cop_interlocks): Likewise.
	(cop_mem_interlocks): Likewise.
	(HAVE_CODE_COMPRESSION): New macro.
	(micromips_op_hash): New variable.
	(micromips_nop16_insn, micromips_nop32_insn): New variables.
	(NOP_INSN): Handle microMIPS ASE.
	(mips32_to_micromips_reg_b_map): New macro.
	(mips32_to_micromips_reg_c_map): Likewise.
	(mips32_to_micromips_reg_d_map): Likewise.
	(mips32_to_micromips_reg_e_map): Likewise.
	(mips32_to_micromips_reg_f_map): Likewise.
	(mips32_to_micromips_reg_g_map): Likewise.
	(mips32_to_micromips_reg_l_map): Likewise.
	(mips32_to_micromips_reg_n_map): Likewise.
	(mips32_to_micromips_reg_h_map): New variable.
	(mips32_to_micromips_reg_m_map): Likewise.
	(mips32_to_micromips_reg_q_map): Likewise.
	(micromips_to_32_reg_h_map): New variable.
	(micromips_to_32_reg_i_map): Likewise.
	(micromips_to_32_reg_m_map): Likewise.
	(micromips_to_32_reg_q_map): Likewise.
	(micromips_to_32_reg_b_map): New macro.
	(micromips_to_32_reg_c_map): Likewise.
	(micromips_to_32_reg_d_map): Likewise.
	(micromips_to_32_reg_e_map): Likewise.
	(micromips_to_32_reg_f_map): Likewise.
	(micromips_to_32_reg_g_map): Likewise.
	(micromips_to_32_reg_l_map): Likewise.
	(micromips_to_32_reg_n_map): Likewise.
	(micromips_imm_b_map, micromips_imm_c_map): New macros.
	(RELAX_DELAY_SLOT_16BIT): New macro.
	(RELAX_DELAY_SLOT_SIZE_FIRST): Likewise.
	(RELAX_DELAY_SLOT_SIZE_SECOND): Likewise.
	(RELAX_MICROMIPS_ENCODE, RELAX_MICROMIPS_P): New macros.
	(RELAX_MICROMIPS_TYPE, RELAX_MICROMIPS_AT): Likewise.
	(RELAX_MICROMIPS_U16BIT, RELAX_MICROMIPS_UNCOND): Likewise.
	(RELAX_MICROMIPS_COMPACT, RELAX_MICROMIPS_LINK): Likewise.
	(RELAX_MICROMIPS_RELAX32, RELAX_MICROMIPS_TOOFAR16): Likewise.
	(RELAX_MICROMIPS_MARK_TOOFAR16): Likewise.
	(RELAX_MICROMIPS_CLEAR_TOOFAR16): Likewise.
	(RELAX_MICROMIPS_TOOFAR32): Likewise.
	(RELAX_MICROMIPS_MARK_TOOFAR32): Likewise.
	(RELAX_MICROMIPS_CLEAR_TOOFAR32): Likewise.
	(INSERT_OPERAND, EXTRACT_OPERAND): Handle microMIPS ASE.
	(mips_macro_warning): Add delay_slot_16bit_p, delay_slot_32bit_p,
	fsize and insns.
	(mips_mark_labels): New function.
	(mips16_small, mips16_ext): Remove variables, replacing with...
	(forced_insn_size): ... this.
	(append_insn, mips16_ip): Update accordingly.
	(micromips_insn_length): New function.
	(insn_length): Return the length of microMIPS instructions.
	(mips_record_mips16_mode): Rename to...
	(mips_record_compressed_mode): ... this.  Handle microMIPS ASE.
	(install_insn): Handle microMIPS ASE.
	(reglist_lookup): New function.
	(is_size_valid, is_delay_slot_valid): Likewise.
	(md_begin): Handle microMIPS ASE.
	(md_assemble): Likewise.  Update for append_insn interface
	change.
	(micromips_reloc_p): New function.
	(got16_reloc_p): Handle microMIPS ASE.
	(hi16_reloc_p): Likewise.
	(lo16_reloc_p): Likewise.
	(matching_lo_reloc): Likewise.
	(insn_uses_reg, reg_needs_delay): Likewise.
	(mips_move_labels): Likewise.
	(mips16_mark_labels): Rename to...
	(mips_compressed_mark_labels): ... this.  Handle microMIPS ASE.
	(insns_between, nops_for_vr4130, nops_for_insn): Likewise.
	(fix_loongson2f_nop, fix_loongson2f_jump): Likewise.
	(MICROMIPS_LABEL_CHAR): New macro.
	(micromips_target_label, micromips_target_name): New variables.
	(micromips_label_name, micromips_label_expr): New functions.
	(micromips_label_inc, micromips_add_label): Likewise.
	(mips_label_is_local): Likewise.
	(micromips_map_reloc): Likewise.
	(append_insn): Add expansionp argument.  Handle microMIPS ASE.
	(start_noreorder, end_noreorder): Handle microMIPS ASE.
	(macro_start, macro_warning, macro_end): Likewise.
	(brk_fmt, cop12_fmt, jalr_fmt, lui_fmt): New variables.
	(mem12_fmt, mfhl_fmt, shft_fmt, trap_fmt): Likewise.
	(BRK_FMT, COP12_FMT, JALR_FMT, LUI_FMT): New macros.
	(MEM12_FMT, MFHL_FMT, SHFT_FMT, TRAP_FMT): Likewise.
	(macro_build): Handle microMIPS ASE.  Update for append_insn
	interface change.
	(mips16_macro_build): Update for append_insn interface change.
	(macro_build_jalr): Handle microMIPS ASE.
	(macro_build_lui): Likewise.  Simplify.
	(load_register): Handle microMIPS ASE.
	(load_address): Likewise.
	(move_register): Likewise.
	(macro_build_branch_likely): New function.
	(macro_build_branch_ccl): Likewise.
	(macro_build_branch_rs): Likewise.
	(macro_build_branch_rsrt): Likewise.
	(macro): Handle microMIPS ASE.
	(validate_micromips_insn): New function.
	(expr_const_in_range): Likewise.
	(mips_ip): Handle microMIPS ASE.
	(options): Add OPTION_MICROMIPS and OPTION_NO_MICROMIPS.
	(md_longopts): Add mmicromips and mno-micromips.
	(md_parse_option): Handle OPTION_MICROMIPS and
	OPTION_NO_MICROMIPS.
	(mips_after_parse_args): Handle microMIPS ASE.
	(md_pcrel_from): Handle microMIPS relocations.
	(mips_force_relocation): Likewise.
	(md_apply_fix): Likewise.
	(mips_align): Handle microMIPS ASE.
	(s_mipsset): Likewise.
	(s_cpload, s_cpsetup, s_cpreturn): Use relocation wrappers.
	(s_dtprel_internal): Likewise.
	(s_gpword, s_gpdword): Likewise.
	(s_insn): Handle microMIPS ASE.
	(s_mips_stab): Likewise.
	(relaxed_micromips_32bit_branch_length): New function.
	(relaxed_micromips_16bit_branch_length): New function.
	(md_estimate_size_before_relax): Handle microMIPS ASE.
	(mips_fix_adjustable): Likewise.
	(tc_gen_reloc): Handle microMIPS relocations.
	(mips_relax_frag): Handle microMIPS ASE.
	(md_convert_frag): Likewise.
	(mips_frob_file_after_relocs): Likewise.
	(mips_elf_final_processing): Likewise.
	(mips_nop_opcode): Likewise.
	(mips_handle_align): Likewise.
	(md_show_usage): Handle microMIPS options.
	* symbols.c (TC_LABEL_IS_LOCAL): New macro.
	(S_IS_LOCAL): Add a TC_LABEL_IS_LOCAL check.

	* doc/as.texinfo (Target MIPS options): Add -mmicromips and
	-mno-micromips.
	(-mmicromips, -mno-micromips): New options.
	* doc/c-mips.texi (-mmicromips, -mno-micromips): New options.
	(MIPS ISA): Document .set micromips and .set nomicromips.
	(MIPS insn): Update for microMIPS support.

gas/testsuite/
2011-02-21  Maciej W. Rozycki  <macro@codesourcery.com>
            Chao-ying Fu  <fu@mips.com>

	* gas/mips/micromips.d: New test.
	* gas/mips/micromips-branch-delay.d: Likewise.
	* gas/mips/micromips-branch-relax.d: Likewise.
	* gas/mips/micromips-branch-relax-pic.d: Likewise.
	* gas/mips/micromips-size-1.d: Likewise.
	* gas/mips/micromips-trap.d: Likewise.
	* gas/mips/micromips.l: New stderr output.
	* gas/mips/micromips-branch-delay.l: Likewise.
	* gas/mips/micromips-branch-relax.l: Likewise.
	* gas/mips/micromips-branch-relax-pic.l: Likewise.
	* gas/mips/micromips-size-0.l: New list test.
	* gas/mips/micromips-size-1.l: New stderr output.
	* gas/mips/micromips.s: New test source.
	* gas/mips/micromips-branch-delay.s: Likewise.
	* gas/mips/micromips-branch-relax.s: Likewise.
	* gas/mips/micromips-size-0.s: Likewise.
	* gas/mips/micromips-size-1.s: Likewise.
	* gas/mips/mips.exp: Run the new tests.

	* gas/mips/elf_ase_micromips.d: New test.
	* gas/mips/elf_ase_micromips-2.d: Likewise.
	* gas/mips/micromips@abs.d: Likewise.
	* gas/mips/micromips@add.d: Likewise.
	* gas/mips/micromips@and.d: Likewise.
	* gas/mips/micromips@beq.d: Likewise.
	* gas/mips/micromips@bge.d: Likewise.
	* gas/mips/micromips@bgeu.d: Likewise.
	* gas/mips/micromips@blt.d: Likewise.
	* gas/mips/micromips@bltu.d: Likewise.
	* gas/mips/micromips@branch-likely.d: Likewise.
	* gas/mips/micromips@branch-misc-1.d: Likewise.
	* gas/mips/micromips@branch-misc-2-64.d: Likewise.
	* gas/mips/micromips@branch-misc-2.d: Likewise.
	* gas/mips/micromips@branch-misc-2pic-64.d: Likewise.
	* gas/mips/micromips@branch-misc-2pic.d: Likewise.
	* gas/mips/micromips@branch-self.d: Likewise.
	* gas/mips/micromips@cache.d: Likewise.
	* gas/mips/micromips@daddi.d: Likewise.
	* gas/mips/micromips@dli.d: Likewise.
	* gas/mips/micromips@elf-jal.d: Likewise.
	* gas/mips/micromips@elf-rel2.d: Likewise.
	* gas/mips/micromips@elf-rel4.d: Likewise.
	* gas/mips/micromips@jal-svr4pic.d: Likewise.
	* gas/mips/micromips@jal-svr4pic-noreorder.d: Likewise.
	* gas/mips/micromips@lb-svr4pic-ilocks.d: Likewise.
	* gas/mips/micromips@li.d: Likewise.
	* gas/mips/micromips@mips1-fp.d: Likewise.
	* gas/mips/micromips@mips32-cp2.d: Likewise.
	* gas/mips/micromips@mips32-imm.d: Likewise.
	* gas/mips/micromips@mips32-sf32.d: Likewise.
	* gas/mips/micromips@mips32.d: Likewise.
	* gas/mips/micromips@mips32r2-cp2.d: Likewise.
	* gas/mips/micromips@mips32r2-fp32.d: Likewise.
	* gas/mips/micromips@mips32r2.d: Likewise.
	* gas/mips/micromips@mips4-branch-likely.d: Likewise.
	* gas/mips/micromips@mips4-fp.d: Likewise.
	* gas/mips/micromips@mips4.d: Likewise.
	* gas/mips/micromips@mips5.d: Likewise.
	* gas/mips/micromips@mips64-cp2.d: Likewise.
	* gas/mips/micromips@mips64.d: Likewise.
	* gas/mips/micromips@mips64r2.d: Likewise.
	* gas/mips/micromips@pref.d: Likewise.
	* gas/mips/micromips@rol-hw.d: Likewise.
	* gas/mips/micromips@uld2-eb.d: Likewise.
	* gas/mips/micromips@uld2-el.d: Likewise.
	* gas/mips/micromips@ulh2-eb.d: Likewise.
	* gas/mips/micromips@ulh2-el.d: Likewise.
	* gas/mips/micromips@ulw2-eb-ilocks.d: Likewise.
	* gas/mips/micromips@ulw2-el-ilocks.d: Likewise.
	* gas/mips/cache.d: Likewise.
	* gas/mips/daddi.d: Likewise.
	* gas/mips/mips32-imm.d: Likewise.
	* gas/mips/pref.d: Likewise.
	* gas/mips/elf-rel27.d: Handle microMIPS ASE.
	* gas/mips/l_d.d: Likewise.
	* gas/mips/l_d-n32.d: Likewise.
	* gas/mips/l_d-n64.d: Likewise.
	* gas/mips/ld.d: Likewise.
	* gas/mips/ld-n32.d: Likewise.
	* gas/mips/ld-n64.d: Likewise.
	* gas/mips/s_d.d: Likewise.
	* gas/mips/s_d-n32.d: Likewise.
	* gas/mips/s_d-n64.d: Likewise.
	* gas/mips/sd.d: Likewise.
	* gas/mips/sd-n32.d: Likewise.
	* gas/mips/sd-n64.d: Likewise.
	* gas/mips/mips32.d: Update immediates.
	* gas/mips/micromips@mips32-cp2.s: New test source.
	* gas/mips/micromips@mips32-imm.s: Likewise.
	* gas/mips/micromips@mips32r2-cp2.s: Likewise.
	* gas/mips/micromips@mips64-cp2.s: Likewise.
	* gas/mips/cache.s: Likewise.
	* gas/mips/daddi.s: Likewise.
	* gas/mips/mips32-imm.s: Likewise.
	* gas/mips/elf-rel4.s: Handle microMIPS ASE.
	* gas/mips/lb-pic.s: Likewise.
	* gas/mips/ld.s: Likewise.
	* gas/mips/mips32.s: Likewise.
	* gas/mips/mips.exp: Add the micromips arch.  Exclude mips16e
	from micromips.  Run mips32-imm.

	* gas/mips/jal-mask-11.d: New test.
	* gas/mips/jal-mask-12.d: Likewise.
	* gas/mips/micromips@jal-mask-11.d: Likewise.
	* gas/mips/jal-mask-1.s: Source for the new tests.
	* gas/mips/jal-mask-21.d: New test.
	* gas/mips/jal-mask-22.d: Likewise.
	* gas/mips/micromips@jal-mask-12.d: Likewise.
	* gas/mips/jal-mask-2.s: Source for the new tests.
	* gas/mips/mips.exp: Run the new tests.

	* gas/mips/mips16-e.d: Add --special-syms to `objdump'.
	* gas/mips/tmips16-e.d: Likewise.

	* gas/mips/and.s: Adjust padding.
	* gas/mips/beq.s: Likewise.
	* gas/mips/bge.s: Likewise.
	* gas/mips/bgeu.s: Likewise.
	* gas/mips/blt.s: Likewise.
	* gas/mips/bltu.s: Likewise.
	* gas/mips/branch-misc-2.s: Likewise.
	* gas/mips/jal.s: Likewise.
	* gas/mips/li.s: Likewise.
	* gas/mips/mips1-fp.s: Likewise.
	* gas/mips/mips32r2-fp32.s: Likewise.
	* gas/mips/mips64.s: Likewise.
	* gas/mips/mips4.s: Likewise.
	* gas/mips/mips4-fp.s: Likewise.
	* gas/mips/and.d: Update accordingly.
	* gas/mips/elf-jal.d: Likewise.
	* gas/mips/jal.d: Likewise.
	* gas/mips/li.d: Likewise.
	* gas/mips/mips1-fp.d: Likewise.
	* gas/mips/mips32r2-fp32.d: Likewise.
	* gas/mips/mips64.d: Likewise.

include/elf/
2011-02-21  Chao-ying Fu  <fu@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* mips.h (R_MICROMIPS_min): New relocations.
	(R_MICROMIPS_26_S1): Likewise.
	(R_MICROMIPS_HI16, R_MICROMIPS_LO16): Likewise.
	(R_MICROMIPS_GPREL16, R_MICROMIPS_LITERAL): Likewise.
	(R_MICROMIPS_GOT16, R_MICROMIPS_PC7_S1): Likewise.
	(R_MICROMIPS_PC10_S1, R_MICROMIPS_PC16_S1): Likewise.
	(R_MICROMIPS_CALL16, R_MICROMIPS_GOT_DISP): Likewise.
	(R_MICROMIPS_GOT_PAGE, R_MICROMIPS_GOT_OFST): Likewise.
	(R_MICROMIPS_GOT_HI16, R_MICROMIPS_GOT_LO16): Likewise.
	(R_MICROMIPS_SUB, R_MICROMIPS_HIGHER): Likewise.
	(R_MICROMIPS_HIGHEST, R_MICROMIPS_CALL_HI16): Likewise.
	(R_MICROMIPS_CALL_LO16, R_MICROMIPS_SCN_DISP): Likewise.
	(R_MICROMIPS_JALR, R_MICROMIPS_HI0_LO16): Likewise.
	(R_MICROMIPS_TLS_GD, R_MICROMIPS_TLS_LDM): Likewise.
	(R_MICROMIPS_TLS_DTPREL_HI, R_MICROMIPS_TLS_DTPREL_LO): Likewise.
	(R_MICROMIPS_TLS_GOTTPREL): Likewise.
	(R_MICROMIPS_TLS_TPREL_HI16): Likewise.
	(R_MICROMIPS_TLS_TPREL_LO16): Likewise.
	(R_MICROMIPS_GPREL7_S2, R_MICROMIPS_PC23_S2): Likewise.
	(R_MICROMIPS_max): Likewise.
	(EF_MIPS_ARCH_ASE_MICROMIPS): New macro.
	(STO_MIPS_ISA, STO_MIPS_FLAGS): Likewise.
	(ELF_ST_IS_MIPS_PLT, ELF_ST_SET_MIPS_PLT): Likewise.
	(STO_MICROMIPS): Likewise.
	(ELF_ST_IS_MICROMIPS, ELF_ST_SET_MICROMIPS): Likewise.
	(ELF_ST_IS_COMPRESSED): Likewise.
	(STO_MIPS_PLT, STO_MIPS_PIC): Rework.
	(ELF_ST_IS_MIPS_PIC, ELF_ST_SET_MIPS_PIC): Likewise.
	(STO_MIPS16, ELF_ST_IS_MIPS16, ELF_ST_SET_MIPS16): Likewise.

include/opcode/
2011-02-21  Chao-ying Fu  <fu@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* mips.h (OP_MASK_EXTLSB, OP_SH_EXTLSB): New macros.
	(OP_MASK_STYPE, OP_SH_STYPE): Likewise.
	(OP_MASK_CODE10, OP_SH_CODE10): Likewise.
	(OP_MASK_TRAP, OP_SH_TRAP): Likewise.
	(OP_MASK_OFFSET12, OP_SH_OFFSET12): Likewise.
	(OP_MASK_OFFSET10, OP_SH_OFFSET10): Likewise.
	(OP_MASK_RS3, OP_SH_RS3): Likewise.
	(OP_MASK_MB, OP_SH_MB, OP_MASK_MC, OP_SH_MC): Likewise.
	(OP_MASK_MD, OP_SH_MD, OP_MASK_ME, OP_SH_ME): Likewise.
	(OP_MASK_MF, OP_SH_MF, OP_MASK_MG, OP_SH_MG): Likewise.
	(OP_MASK_MJ, OP_SH_MJ, OP_MASK_ML, OP_SH_ML): Likewise.
	(OP_MASK_MP, OP_SH_MP, OP_MASK_MQ, OP_SH_MQ): Likewise.
	(OP_MASK_IMMA, OP_SH_IMMA, OP_MASK_IMMB, OP_SH_IMMB): Likewise.
	(OP_MASK_IMMC, OP_SH_IMMC, OP_MASK_IMMF, OP_SH_IMMF): Likewise.
	(OP_MASK_IMMG, OP_SH_IMMG, OP_MASK_IMMH, OP_SH_IMMH): Likewise.
	(OP_MASK_IMMI, OP_SH_IMMI, OP_MASK_IMMJ, OP_SH_IMMJ): Likewise.
	(OP_MASK_IMML, OP_SH_IMML, OP_MASK_IMMM, OP_SH_IMMM): Likewise.
	(OP_MASK_IMMN, OP_SH_IMMN, OP_MASK_IMMO, OP_SH_IMMO): Likewise.
	(OP_MASK_IMMP, OP_SH_IMMP, OP_MASK_IMMQ, OP_SH_IMMQ): Likewise.
	(OP_MASK_IMMU, OP_SH_IMMU, OP_MASK_IMMW, OP_SH_IMMW): Likewise.
	(OP_MASK_IMMX, OP_SH_IMMX, OP_MASK_IMMY, OP_SH_IMMY): Likewise.
	(INSN2_BRANCH_DELAY_16BIT, INSN2_BRANCH_DELAY_32BIT): New macros.
	(INSN2_WRITE_GPR_S, INSN2_READ_FPR_D): Likewise.
	(INSN2_MOD_GPR_MB, INSN2_MOD_GPR_MC, INSN2_MOD_GPR_MD): Likewise.
	(INSN2_MOD_GPR_ME, INSN2_MOD_GPR_MF, INSN2_MOD_GPR_MG): Likewise.
	(INSN2_MOD_GPR_MJ, INSN2_MOD_GPR_MP, INSN2_MOD_GPR_MQ): Likewise.
	(INSN2_MOD_SP, INSN2_READ_GPR_31): Likewise.
	(INSN2_READ_GP, INSN2_READ_PC): Likewise.
	(CPU_MICROMIPS): New macro.
	(M_BC1FL, M_BC1TL, M_BC2FL, M_BC2TL): New enum values.
	(M_BEQL, M_BGEZ, M_BGEZL, M_BGEZALL, M_BGTZ, M_BGTZL): Likewise.
	(M_BLEZ, M_BLEZL, M_BLTZ, M_BLTZL, M_BLTZALL, M_BNEL): Likewise.
	(M_CACHE_OB, M_JALS_1, M_JALS_2, M_JALS_A): Likewise.
	(M_LDC2_OB, M_LDL_OB, M_LDM_AB, M_LDM_OB): Likewise.
	(M_LDP_AB, M_LDP_OB, M_LDR_OB, M_LL_OB, M_LLD_OB): Likewise.
	(M_LWC2_OB, M_LWL_OB, M_LWM_AB, M_LWM_OB): Likewise.
	(M_LWP_AB, M_LWP_OB, M_LWR_OB): Likewise.
	(M_LWU_OB, M_PREF_OB, M_SC_OB, M_SCD_OB): Likewise.
	(M_SDC2_OB, M_SDL_OB, M_SDM_AB, M_SDM_OB): Likewise.
	(M_SDP_AB, M_SDP_OB, M_SDR_OB): Likewise.
	(M_SWC2_OB, M_SWL_OB, M_SWM_AB, M_SWM_OB): Likewise.
	(M_SWP_AB, M_SWP_OB, M_SWR_OB): Likewise.
	(MICROMIPSOP_MASK_MAJOR, MICROMIPSOP_SH_MAJOR): New macros.
	(MICROMIPSOP_MASK_IMMEDIATE, MICROMIPSOP_SH_IMMEDIATE): Likewise.
	(MICROMIPSOP_MASK_DELTA, MICROMIPSOP_SH_DELTA): Likewise.
	(MICROMIPSOP_MASK_CODE10, MICROMIPSOP_SH_CODE10): Likewise.
	(MICROMIPSOP_MASK_TRAP, MICROMIPSOP_SH_TRAP): Likewise.
	(MICROMIPSOP_MASK_SHAMT, MICROMIPSOP_SH_SHAMT): Likewise.
	(MICROMIPSOP_MASK_TARGET, MICROMIPSOP_SH_TARGET): Likewise.
	(MICROMIPSOP_MASK_EXTLSB, MICROMIPSOP_SH_EXTLSB): Likewise.
	(MICROMIPSOP_MASK_EXTMSBD, MICROMIPSOP_SH_EXTMSBD): Likewise.
	(MICROMIPSOP_MASK_INSMSB, MICROMIPSOP_SH_INSMSB): Likewise.
	(MICROMIPSOP_MASK_CODE, MICROMIPSOP_SH_CODE): Likewise.
	(MICROMIPSOP_MASK_CODE2, MICROMIPSOP_SH_CODE2): Likewise.
	(MICROMIPSOP_MASK_CACHE, MICROMIPSOP_SH_CACHE): Likewise.
	(MICROMIPSOP_MASK_SEL, MICROMIPSOP_SH_SEL): Likewise.
	(MICROMIPSOP_MASK_OFFSET12, MICROMIPSOP_SH_OFFSET12): Likewise.
	(MICROMIPSOP_MASK_3BITPOS, MICROMIPSOP_SH_3BITPOS): Likewise.
	(MICROMIPSOP_MASK_STYPE, MICROMIPSOP_SH_STYPE): Likewise.
	(MICROMIPSOP_MASK_OFFSET10, MICROMIPSOP_SH_OFFSET10): Likewise.
	(MICROMIPSOP_MASK_RS, MICROMIPSOP_SH_RS): Likewise.
	(MICROMIPSOP_MASK_RT, MICROMIPSOP_SH_RT): Likewise.
	(MICROMIPSOP_MASK_RD, MICROMIPSOP_SH_RD): Likewise.
	(MICROMIPSOP_MASK_FS, MICROMIPSOP_SH_FS): Likewise.
	(MICROMIPSOP_MASK_FT, MICROMIPSOP_SH_FT): Likewise.
	(MICROMIPSOP_MASK_FD, MICROMIPSOP_SH_FD): Likewise.
	(MICROMIPSOP_MASK_FR, MICROMIPSOP_SH_FR): Likewise.
	(MICROMIPSOP_MASK_RS3, MICROMIPSOP_SH_RS3): Likewise.
	(MICROMIPSOP_MASK_PREFX, MICROMIPSOP_SH_PREFX): Likewise.
	(MICROMIPSOP_MASK_BCC, MICROMIPSOP_SH_BCC): Likewise.
	(MICROMIPSOP_MASK_CCC, MICROMIPSOP_SH_CCC): Likewise.
	(MICROMIPSOP_MASK_COPZ, MICROMIPSOP_SH_COPZ): Likewise.
	(MICROMIPSOP_MASK_MB, MICROMIPSOP_SH_MB): Likewise.
	(MICROMIPSOP_MASK_MC, MICROMIPSOP_SH_MC): Likewise.
	(MICROMIPSOP_MASK_MD, MICROMIPSOP_SH_MD): Likewise.
	(MICROMIPSOP_MASK_ME, MICROMIPSOP_SH_ME): Likewise.
	(MICROMIPSOP_MASK_MF, MICROMIPSOP_SH_MF): Likewise.
	(MICROMIPSOP_MASK_MG, MICROMIPSOP_SH_MG): Likewise.
	(MICROMIPSOP_MASK_MJ, MICROMIPSOP_SH_MJ): Likewise.
	(MICROMIPSOP_MASK_ML, MICROMIPSOP_SH_ML): Likewise.
	(MICROMIPSOP_MASK_MP, MICROMIPSOP_SH_MP): Likewise.
	(MICROMIPSOP_MASK_MQ, MICROMIPSOP_SH_MQ): Likewise.
	(MICROMIPSOP_MASK_IMMA, MICROMIPSOP_SH_IMMA): Likewise.
	(MICROMIPSOP_MASK_IMMB, MICROMIPSOP_SH_IMMB): Likewise.
	(MICROMIPSOP_MASK_IMMC, MICROMIPSOP_SH_IMMC): Likewise.
	(MICROMIPSOP_MASK_IMMD, MICROMIPSOP_SH_IMMD): Likewise.
	(MICROMIPSOP_MASK_IMME, MICROMIPSOP_SH_IMME): Likewise.
	(MICROMIPSOP_MASK_IMMF, MICROMIPSOP_SH_IMMF): Likewise.
	(MICROMIPSOP_MASK_IMMG, MICROMIPSOP_SH_IMMG): Likewise.
	(MICROMIPSOP_MASK_IMMH, MICROMIPSOP_SH_IMMH): Likewise.
	(MICROMIPSOP_MASK_IMMI, MICROMIPSOP_SH_IMMI): Likewise.
	(MICROMIPSOP_MASK_IMMJ, MICROMIPSOP_SH_IMMJ): Likewise.
	(MICROMIPSOP_MASK_IMML, MICROMIPSOP_SH_IMML): Likewise.
	(MICROMIPSOP_MASK_IMMM, MICROMIPSOP_SH_IMMM): Likewise.
	(MICROMIPSOP_MASK_IMMN, MICROMIPSOP_SH_IMMN): Likewise.
	(MICROMIPSOP_MASK_IMMO, MICROMIPSOP_SH_IMMO): Likewise.
	(MICROMIPSOP_MASK_IMMP, MICROMIPSOP_SH_IMMP): Likewise.
	(MICROMIPSOP_MASK_IMMQ, MICROMIPSOP_SH_IMMQ): Likewise.
	(MICROMIPSOP_MASK_IMMU, MICROMIPSOP_SH_IMMU): Likewise.
	(MICROMIPSOP_MASK_IMMW, MICROMIPSOP_SH_IMMW): Likewise.
	(MICROMIPSOP_MASK_IMMX, MICROMIPSOP_SH_IMMX): Likewise.
	(MICROMIPSOP_MASK_IMMY, MICROMIPSOP_SH_IMMY): Likewise.
	(MICROMIPSOP_MASK_CODE, MICROMIPSOP_SH_CODE): Likewise.
	(MICROMIPSOP_MASK_CODE2, MICROMIPSOP_SH_CODE2): Likewise.
	(MICROMIPSOP_MASK_CACHE, MICROMIPSOP_SH_CACHE): Likewise.
	(MICROMIPSOP_MASK_CODE20, MICROMIPSOP_SH_CODE20): Likewise.
	(MICROMIPSOP_MASK_PERFREG, MICROMIPSOP_SH_PERFREG): Likewise.
	(MICROMIPSOP_MASK_CODE19, MICROMIPSOP_SH_CODE19): Likewise.
	(MICROMIPSOP_MASK_ALN, MICROMIPSOP_SH_ALN): Likewise.
	(MICROMIPSOP_MASK_VECBYTE, MICROMIPSOP_SH_VECBYTE): Likewise.
	(MICROMIPSOP_MASK_VECALIGN, MICROMIPSOP_SH_VECALIGN): Likewise.
	(MICROMIPSOP_MASK_DSPACC, MICROMIPSOP_SH_DSPACC): Likewise.
	(MICROMIPSOP_MASK_DSPACC_S, MICROMIPSOP_SH_DSPACC_S): Likewise.
	(MICROMIPSOP_MASK_DSPSFT, MICROMIPSOP_SH_DSPSFT): Likewise.
	(MICROMIPSOP_MASK_DSPSFT_7, MICROMIPSOP_SH_DSPSFT_7): Likewise.
	(MICROMIPSOP_MASK_SA3, MICROMIPSOP_SH_SA3): Likewise.
	(MICROMIPSOP_MASK_SA4, MICROMIPSOP_SH_SA4): Likewise.
	(MICROMIPSOP_MASK_IMM8, MICROMIPSOP_SH_IMM8): Likewise.
	(MICROMIPSOP_MASK_IMM10, MICROMIPSOP_SH_IMM10): Likewise.
	(MICROMIPSOP_MASK_WRDSP, MICROMIPSOP_SH_WRDSP): Likewise.
	(MICROMIPSOP_MASK_RDDSP, MICROMIPSOP_SH_RDDSP): Likewise.
	(MICROMIPSOP_MASK_BP, MICROMIPSOP_SH_BP): Likewise.
	(MICROMIPSOP_MASK_MT_U, MICROMIPSOP_SH_MT_U): Likewise.
	(MICROMIPSOP_MASK_MT_H, MICROMIPSOP_SH_MT_H): Likewise.
	(MICROMIPSOP_MASK_MTACC_T, MICROMIPSOP_SH_MTACC_T): Likewise.
	(MICROMIPSOP_MASK_MTACC_D, MICROMIPSOP_SH_MTACC_D): Likewise.
	(MICROMIPSOP_MASK_BBITIND, MICROMIPSOP_SH_BBITIND): Likewise.
	(MICROMIPSOP_MASK_CINSPOS, MICROMIPSOP_SH_CINSPOS): Likewise.
	(MICROMIPSOP_MASK_CINSLM1, MICROMIPSOP_SH_CINSLM1): Likewise.
	(MICROMIPSOP_MASK_SEQI, MICROMIPSOP_SH_SEQI): Likewise.
	(micromips_opcodes): New declaration.
	(bfd_micromips_num_opcodes): Likewise.

	* mips.h (INSN2_UNCOND_BRANCH, INSN2_COND_BRANCH): New macros.

	* mips.h (INSN2_MOD_GPR_MHI): New macro.
	(INSN2_MOD_GPR_MM, INSN2_MOD_GPR_MN): Likewise.
	(MICROMIPSOP_MASK_MH, MICROMIPSOP_SH_MH): Likewise.
	(MICROMIPSOP_MASK_MI, MICROMIPSOP_SH_MI): Likewise.
	(MICROMIPSOP_MASK_MM, MICROMIPSOP_SH_MM): Likewise.
	(MICROMIPSOP_MASK_MN, MICROMIPSOP_SH_MN): Likewise.

ld/testsuite/
2011-02-21  Catherine Moore  <clm@codesourcery.com>
            Chao-ying Fu  <fu@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* lib/ld-lib.exp (run_dump_test): Support distinct assembler
	flags for the same source named multiple times.
	* ld-mips-elf/jalx-1.s: New test source.
	* ld-mips-elf/jalx-1.d: New test output.
	* ld-mips-elf/jalx-1.ld: New test linker script.
	* ld-mips-elf/jalx-2-main.s: New test source.
	* ld-mips-elf/jalx-2-ex.s: Likewise.
	* ld-mips-elf/jalx-2-printf.s: Likewise.
	* ld-mips-elf/jalx-2.dd: New test output.
	* ld-mips-elf/jalx-2.ld: New test linker script.
	* ld-mips-elf/mips16-and-micromips.d: New test.
	* ld-mips-elf/mips-elf.exp: Run the new tests

opcodes/
2011-02-21  Chao-ying Fu  <fu@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* micromips-opc.c: New file.
	* mips-dis.c (micromips_to_32_reg_b_map): New array.
	(micromips_to_32_reg_c_map, micromips_to_32_reg_d_map): Likewise.
	(micromips_to_32_reg_e_map, micromips_to_32_reg_f_map): Likewise.
	(micromips_to_32_reg_g_map, micromips_to_32_reg_l_map): Likewise.
	(micromips_to_32_reg_q_map): Likewise.
	(micromips_imm_b_map, micromips_imm_c_map): Likewise.
	(micromips_ase): New variable.
	(is_micromips): New function.
	(set_default_mips_dis_options): Handle microMIPS ASE.
	(print_insn_micromips): New function.
	(is_compressed_mode_p): Likewise.
	(_print_insn_mips): Handle microMIPS instructions.
	* Makefile.am (CFILES): Add micromips-opc.c.
	* configure.in (bfd_mips_arch): Add micromips-opc.lo.
	* Makefile.in: Regenerate.
	* configure: Regenerate.

	* mips-dis.c (micromips_to_32_reg_h_map): New variable.
	(micromips_to_32_reg_i_map): Likewise.
	(micromips_to_32_reg_m_map): Likewise.
	(micromips_to_32_reg_n_map): New macro.

Attachment: binutils-20110221-umips-fix.diff.bz2
Description: Binary data

Attachment: binutils-20110221-umips-relax16.diff.bz2
Description: Binary data

Attachment: binutils-20110221-umips-fix-reloc.diff.bz2
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]