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]

[committed] Use operand structures for MIPS16


This patch just extends the previous one to handle MIPS16.

Tested on various targets and applied.

Richard


include/opcode/
	* mips.h (mips_operand_type): Add OP_ENTRY_EXIT_LIST and
	OP_SAVE_RESTORE_LIST.
	(decode_mips16_operand): Declare.

opcodes/
	* mips16-opc.c: Include mips-formats.h.
	(reg_0_map, reg_29_map, reg_31_map, reg_m16_map, reg32r_map): New
	static arrays.
	(decode_mips16_operand): New function.
	* mips-dis.c (mips16_to_32_reg_map, mips16_reg_names): Delete.
	(print_insn_arg): Handle OP_ENTRY_EXIT list.
	Abort for OP_SAVE_RESTORE_LIST.
	(print_mips16_insn_arg): Change interface.  Use mips_operand
	structures.  Delete GET_OP_S.  Move GET_OP definition to...
	(print_insn_mips16): ...here.  Call init_print_arg_state.
	Update the call to print_mips16_insn_arg.

Index: include/opcode/mips.h
===================================================================
*** include/opcode/mips.h	2013-07-14 14:27:21.315187381 +0100
--- include/opcode/mips.h	2013-07-14 14:30:14.183789493 +0100
*************** enum mips_operand_type {
*** 375,380 ****
--- 375,387 ----
       size determines whether the 16-bit or 32-bit encoding is required.  */
    OP_LWM_SWM_LIST,
  
+   /* The register list for an emulated MIPS16 ENTRY or EXIT instruction.  */
+   OP_ENTRY_EXIT_LIST,
+ 
+   /* The register list and frame size for a MIPS16 SAVE or RESTORE
+      instruction.  */
+   OP_SAVE_RESTORE_LIST,
+ 
    /* A 10-bit field VVVVVNNNNN used for octobyte and quadhalf instructions:
  
       V      Meaning
*************** #define MIPS16_INSN_COND_BRANCH		    0x0
*** 1680,1685 ****
--- 1687,1693 ----
     FP_D (never used)
     */
  
+ extern const struct mips_operand *decode_mips16_operand (char, bfd_boolean);
  extern const struct mips_opcode mips16_opcodes[];
  extern const int bfd_mips16_num_opcodes;
  
Index: opcodes/mips16-opc.c
===================================================================
*** opcodes/mips16-opc.c	2013-07-14 14:10:36.067297396 +0100
--- opcodes/mips16-opc.c	2013-07-14 14:30:45.097076313 +0100
***************
*** 23,28 ****
--- 23,138 ----
  #include "sysdep.h"
  #include <stdio.h>
  #include "opcode/mips.h"
+ #include "mips-formats.h"
+ 
+ static unsigned char reg_0_map[] = { 0 };
+ static unsigned char reg_29_map[] = { 29 };
+ static unsigned char reg_31_map[] = { 31 };
+ static unsigned char reg_m16_map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+ static unsigned char reg32r_map[] = {
+   0, 8, 16, 24,
+   1, 9, 17, 25,
+   2, 10, 18, 26,
+   3, 11, 19, 27,
+   4, 12, 20, 28,
+   5, 13, 21, 29,
+   6, 14, 22, 30,
+   7, 15, 23, 31
+ };
+ 
+ /* Return the meaning of operand character TYPE, or null if it isn't
+    recognized.  If the operand is affected by the EXTEND instruction,
+    EXTENDED_P selects between the extended and unextended forms.
+    The extended forms all have an lsb of 0.  */
+ 
+ const struct mips_operand *
+ decode_mips16_operand (char type, bfd_boolean extended_p)
+ {
+   switch (type)
+     {
+     case '0': MAPPED_REG (0, 0, GP, reg_0_map);
+ 
+     case 'L': SPECIAL (6, 5, ENTRY_EXIT_LIST);
+     case 'M': SPECIAL (7, 0, SAVE_RESTORE_LIST);
+     case 'P': SPECIAL (0, 0, PC);
+     case 'R': MAPPED_REG (0, 0, GP, reg_31_map);
+     case 'S': MAPPED_REG (0, 0, GP, reg_29_map);
+     case 'X': REG (5, 0, GP);
+     case 'Y': MAPPED_REG (5, 3, GP, reg32r_map);
+     case 'Z': MAPPED_REG (3, 0, GP, reg_m16_map);
+ 
+     case 'a': JUMP (26, 0, 2);
+     case 'e': UINT (11, 0);
+     case 'i': JALX (26, 0, 2);
+     case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST);
+     case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST);
+     case 'v': MAPPED_REG (3, 8, GP, reg_m16_map);
+     case 'w': MAPPED_REG (3, 5, GP, reg_m16_map);
+     case 'x': MAPPED_REG (3, 8, GP, reg_m16_map);
+     case 'y': MAPPED_REG (3, 5, GP, reg_m16_map);
+     case 'z': MAPPED_REG (3, 2, GP, reg_m16_map);
+     }
+ 
+   if (extended_p)
+     switch (type)
+       {
+       case '<': UINT (5, 0);
+       case '>': UINT (5, 0);
+       case '[': UINT (6, 0);
+       case ']': UINT (6, 0);
+ 
+       case '4': SINT (15, 0);
+       case '5': SINT (16, 0);
+       case '6': SINT (16, 0);
+       case '8': SINT (16, 0);
+ 
+       case 'A': PCREL (16, 0, 2, 0, TRUE, FALSE, FALSE);
+       case 'B': PCREL (16, 0, 3, 0, TRUE, FALSE, FALSE);
+       case 'C': SINT (16, 0);
+       case 'D': SINT (16, 0);
+       case 'E': PCREL (16, 0, 2, 0, TRUE, FALSE, FALSE);
+       case 'H': SINT (16, 0);
+       case 'K': SINT (16, 0);
+       case 'U': UINT (16, 0);
+       case 'V': SINT (16, 0);
+       case 'W': SINT (16, 0);
+ 
+       case 'j': SINT (16, 0);
+       case 'k': SINT (16, 0);
+       case 'p': BRANCH (16, 0, 1);
+       case 'q': BRANCH (16, 0, 1);
+       }
+   else
+     switch (type)
+       {
+       case '<': INT_ADJ (3, 2, 8, 0, FALSE);
+       case '>': INT_ADJ (3, 8, 8, 0, FALSE);
+       case '[': INT_ADJ (3, 2, 8, 0, FALSE);
+       case ']': INT_ADJ (3, 8, 8, 0, FALSE);
+ 
+       case '4': SINT (4, 0);
+       case '5': UINT (5, 0);
+       case '6': UINT (6, 5);
+       case '8': UINT (8, 0);
+ 
+       case 'A': PCREL (8, 0, 2, 2, FALSE, FALSE, FALSE);
+       case 'B': PCREL (5, 0, 3, 3, FALSE, FALSE, FALSE);
+       case 'C': INT_ADJ (8, 0, 255, 3, FALSE);	/* (0 .. 255) << 3 */
+       case 'D': INT_ADJ (5, 0, 31, 3, FALSE);	/* (0 .. 31) << 3 */
+       case 'E': PCREL (5, 0, 2, 2, FALSE, FALSE, FALSE);
+       case 'H': INT_ADJ (5, 0, 31, 1, FALSE);	/* (0 .. 31) << 1 */
+       case 'K': INT_ADJ (8, 0, 127, 3, FALSE);	/* (-128 .. 127) << 3 */
+       case 'U': UINT (8, 0);
+       case 'V': INT_ADJ (8, 0, 255, 2, FALSE);	/* (0 .. 255) << 2 */
+       case 'W': INT_ADJ (5, 0, 31, 2, FALSE);	/* (0 .. 31) << 2 */
+ 
+       case 'j': SINT (5, 0);
+       case 'k': SINT (8, 0);
+       case 'p': BRANCH (8, 0, 1);
+       case 'q': BRANCH (11, 0, 1);
+       }
+   return 0;
+ }
  
  /* This is the opcodes table for the mips16 processor.  The format of
     this table is intentionally identical to the one in mips-opc.c.
Index: opcodes/mips-dis.c
===================================================================
*** opcodes/mips-dis.c	2013-07-14 14:27:21.327187492 +0100
--- opcodes/mips-dis.c	2013-07-14 14:33:41.161710629 +0100
*************** struct mips_cp0sel_name
*** 51,65 ****
    const char * const name;
  };
  
- /* The mips16 registers.  */
- static const unsigned int mips16_to_32_reg_map[] =
- {
-   16, 17, 2, 3, 4, 5, 6, 7
- };
- 
- #define mips16_reg_names(rn)	mips_gpr_names[mips16_to_32_reg_map[rn]]
- 
- 
  static const char * const mips_gpr_names_numeric[32] =
  {
    "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
--- 51,56 ----
*************** print_insn_arg (struct disassemble_info
*** 1128,1133 ****
--- 1119,1172 ----
  	}
        break;
  
+     case OP_ENTRY_EXIT_LIST:
+       {
+ 	const char *sep;
+ 	unsigned int amask, smask;
+ 
+ 	sep = "";
+ 	amask = (uval >> 3) & 7;
+ 	if (amask > 0 && amask < 5)
+ 	  {
+ 	    infprintf (is, "%s", mips_gpr_names[4]);
+ 	    if (amask > 1)
+ 	      infprintf (is, "-%s", mips_gpr_names[amask + 3]);
+ 	    sep = ",";
+ 	  }
+ 
+ 	smask = (uval >> 1) & 3;
+ 	if (smask == 3)
+ 	  {
+ 	    infprintf (is, "%s??", sep);
+ 	    sep = ",";
+ 	  }
+ 	else if (smask > 0)
+ 	  {
+ 	    infprintf (is, "%s%s", sep, mips_gpr_names[16]);
+ 	    if (smask > 1)
+ 	      infprintf (is, "-%s", mips_gpr_names[smask + 15]);
+ 	    sep = ",";
+ 	  }
+ 
+ 	if (uval & 1)
+ 	  {
+ 	    infprintf (is, "%s%s", sep, mips_gpr_names[31]);
+ 	    sep = ",";
+ 	  }
+ 
+ 	if (amask == 5 || amask == 6)
+ 	  {
+ 	    infprintf (is, "%s%s", sep, mips_fpr_names[0]);
+ 	    if (amask == 6)
+ 	      infprintf (is, "-%s", mips_fpr_names[1]);
+ 	  }
+       }
+       break;
+ 
+     case OP_SAVE_RESTORE_LIST:
+       /* Should be handled by the caller due to extend behavior.  */
+       abort ();
+ 
      case OP_MDMX_IMM_REG:
        {
  	unsigned int vsel;
*************** #define GET_OP(insn, field)			\
*** 1351,1372 ****
  /* Disassemble an operand for a mips16 instruction.  */
  
  static void
! print_mips16_insn_arg (char type,
! 		       const struct mips_opcode *op,
! 		       int l,
! 		       bfd_boolean use_extend,
! 		       int extend,
! 		       bfd_vma memaddr,
! 		       struct disassemble_info *info)
  {
    const fprintf_ftype infprintf = info->fprintf_func;
    void *is = info->stream;
  
- #define GET_OP(insn, field) \
-   (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
- #define GET_OP_S(insn, field) \
-   ((GET_OP (insn, field) ^ ((MIPS16OP_MASK_##field >> 1) + 1)) \
-    - ((MIPS16OP_MASK_##field >> 1) + 1))
    switch (type)
      {
      case ',':
--- 1390,1411 ----
  /* Disassemble an operand for a mips16 instruction.  */
  
  static void
! print_mips16_insn_arg (struct disassemble_info *info,
! 		       struct mips_print_arg_state *state,
! 		       const struct mips_opcode *opcode,
! 		       char type, bfd_vma memaddr,
! 		       unsigned insn, bfd_boolean use_extend,
! 		       unsigned extend, bfd_boolean is_offset)
  {
    const fprintf_ftype infprintf = info->fprintf_func;
    void *is = info->stream;
+   const struct mips_operand *operand, *ext_operand;
+   unsigned int uval;
+   bfd_vma baseaddr;
+ 
+   if (!use_extend)
+     extend = 0;
  
    switch (type)
      {
      case ',':
*************** #define GET_OP_S(insn, field) \
*** 1375,1831 ****
        infprintf (is, "%c", type);
        break;
  
!     case 'y':
!     case 'w':
!       infprintf (is, "%s", mips16_reg_names (GET_OP (l, RY)));
!       break;
! 
!     case 'x':
!     case 'v':
!       infprintf (is, "%s", mips16_reg_names (GET_OP (l, RX)));
!       break;
! 
!     case 'z':
!       infprintf (is, "%s", mips16_reg_names (GET_OP (l, RZ)));
!       break;
! 
!     case 'Z':
!       infprintf (is, "%s", mips16_reg_names (GET_OP (l, MOVE32Z)));
!       break;
! 
!     case '0':
!       infprintf (is, "%s", mips_gpr_names[0]);
!       break;
! 
!     case 'S':
!       infprintf (is, "%s", mips_gpr_names[29]);
!       break;
  
!     case 'P':
!       infprintf (is, "$pc");
!       break;
  
!     case 'R':
!       infprintf (is, "%s", mips_gpr_names[31]);
!       break;
  
!     case 'X':
!       infprintf (is, "%s", mips_gpr_names[GET_OP (l, REGR32)]);
!       break;
  
!     case 'Y':
!       infprintf (is, "%s", mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
!       break;
! 
!     case '<':
!     case '>':
!     case '[':
!     case ']':
!     case '4':
!     case '5':
!     case 'H':
!     case 'W':
!     case 'D':
!     case 'j':
!     case '6':
!     case '8':
!     case 'V':
!     case 'C':
!     case 'U':
!     case 'k':
!     case 'K':
!     case 'p':
!     case 'q':
!     case 'A':
!     case 'B':
!     case 'E':
!       {
! 	int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
  
! 	shift = 0;
! 	signedp = 0;
! 	extbits = 16;
! 	pcrel = 0;
! 	extu = 0;
! 	branch = 0;
! 	switch (type)
! 	  {
! 	  case '<':
! 	    nbits = 3;
! 	    immed = GET_OP (l, RZ);
! 	    extbits = 5;
! 	    extu = 1;
! 	    break;
! 	  case '>':
! 	    nbits = 3;
! 	    immed = GET_OP (l, RX);
! 	    extbits = 5;
! 	    extu = 1;
! 	    break;
! 	  case '[':
! 	    nbits = 3;
! 	    immed = GET_OP (l, RZ);
! 	    extbits = 6;
! 	    extu = 1;
! 	    break;
! 	  case ']':
! 	    nbits = 3;
! 	    immed = GET_OP (l, RX);
! 	    extbits = 6;
! 	    extu = 1;
! 	    break;
! 	  case '4':
! 	    nbits = 4;
! 	    immed = GET_OP (l, IMM4);
! 	    signedp = 1;
! 	    extbits = 15;
! 	    break;
! 	  case '5':
! 	    nbits = 5;
! 	    immed = GET_OP (l, IMM5);
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 1;
! 	    break;
! 	  case 'H':
! 	    nbits = 5;
! 	    shift = 1;
! 	    immed = GET_OP (l, IMM5);
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 2;
! 	    break;
! 	  case 'W':
! 	    nbits = 5;
! 	    shift = 2;
! 	    immed = GET_OP (l, IMM5);
! 	    if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
! 		&& (op->pinfo & MIPS16_INSN_READ_SP) == 0)
  	      {
! 		info->insn_type = dis_dref;
! 		info->data_size = 4;
  	      }
! 	    break;
! 	  case 'D':
! 	    nbits = 5;
! 	    shift = 3;
! 	    immed = GET_OP (l, IMM5);
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 8;
! 	    break;
! 	  case 'j':
! 	    nbits = 5;
! 	    immed = GET_OP (l, IMM5);
! 	    signedp = 1;
! 	    break;
! 	  case '6':
! 	    nbits = 6;
! 	    immed = GET_OP (l, IMM6);
! 	    break;
! 	  case '8':
! 	    nbits = 8;
! 	    immed = GET_OP (l, IMM8);
! 	    break;
! 	  case 'V':
! 	    nbits = 8;
! 	    shift = 2;
! 	    immed = GET_OP (l, IMM8);
! 	    /* FIXME: This might be lw, or it might be addiu to $sp or
!                $pc.  We assume it's load.  */
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 4;
! 	    break;
! 	  case 'C':
! 	    nbits = 8;
! 	    shift = 3;
! 	    immed = GET_OP (l, IMM8);
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 8;
! 	    break;
! 	  case 'U':
! 	    nbits = 8;
! 	    immed = GET_OP (l, IMM8);
! 	    extu = 1;
! 	    break;
! 	  case 'k':
! 	    nbits = 8;
! 	    immed = GET_OP (l, IMM8);
! 	    signedp = 1;
! 	    break;
! 	  case 'K':
! 	    nbits = 8;
! 	    shift = 3;
! 	    immed = GET_OP (l, IMM8);
! 	    signedp = 1;
! 	    break;
! 	  case 'p':
! 	    nbits = 8;
! 	    immed = GET_OP (l, IMM8);
! 	    signedp = 1;
! 	    pcrel = 1;
! 	    branch = 1;
! 	    break;
! 	  case 'q':
! 	    nbits = 11;
! 	    immed = GET_OP (l, IMM11);
! 	    signedp = 1;
! 	    pcrel = 1;
! 	    branch = 1;
! 	    break;
! 	  case 'A':
! 	    nbits = 8;
! 	    shift = 2;
! 	    immed = GET_OP (l, IMM8);
! 	    pcrel = 1;
! 	    /* FIXME: This can be lw or la.  We assume it is lw.  */
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 4;
! 	    break;
! 	  case 'B':
! 	    nbits = 5;
! 	    shift = 3;
! 	    immed = GET_OP (l, IMM5);
! 	    pcrel = 1;
! 	    info->insn_type = dis_dref;
! 	    info->data_size = 8;
! 	    break;
! 	  case 'E':
! 	    nbits = 5;
! 	    shift = 2;
! 	    immed = GET_OP (l, IMM5);
! 	    pcrel = 1;
! 	    break;
! 	  default:
! 	    abort ();
! 	  }
  
! 	if (! use_extend)
! 	  {
! 	    if (signedp && immed >= (1 << (nbits - 1)))
! 	      immed -= 1 << nbits;
! 	    immed <<= shift;
! 	    if ((type == '<' || type == '>' || type == '[' || type == ']')
! 		&& immed == 0)
! 	      immed = 8;
! 	  }
! 	else
! 	  {
! 	    if (extbits == 16)
! 	      immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
! 	    else if (extbits == 15)
! 	      immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
! 	    else
! 	      immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
! 	    immed &= (1 << extbits) - 1;
! 	    if (! extu && immed >= (1 << (extbits - 1)))
! 	      immed -= 1 << extbits;
! 	  }
  
! 	if (! pcrel)
! 	  infprintf (is, "%d", immed);
! 	else
! 	  {
! 	    bfd_vma baseaddr;
  
! 	    if (branch)
! 	      {
! 		immed *= 2;
! 		baseaddr = memaddr + 2;
! 	      }
! 	    else if (use_extend)
! 	      baseaddr = memaddr - 2;
! 	    else
! 	      {
! 		int status;
! 		bfd_byte buffer[2];
  
! 		baseaddr = memaddr;
  
! 		/* If this instruction is in the delay slot of a jr
!                    instruction, the base address is the address of the
!                    jr instruction.  If it is in the delay slot of jalr
!                    instruction, the base address is the address of the
!                    jalr instruction.  This test is unreliable: we have
!                    no way of knowing whether the previous word is
!                    instruction or data.  */
! 		status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
! 						    info);
! 		if (status == 0
! 		    && (((info->endian == BFD_ENDIAN_BIG
! 			  ? bfd_getb16 (buffer)
! 			  : bfd_getl16 (buffer))
! 			 & 0xf800) == 0x1800))
! 		  baseaddr = memaddr - 4;
! 		else
! 		  {
! 		    status = (*info->read_memory_func) (memaddr - 2, buffer,
! 							2, info);
! 		    if (status == 0
  			&& (((info->endian == BFD_ENDIAN_BIG
  			      ? bfd_getb16 (buffer)
  			      : bfd_getl16 (buffer))
  			     & 0xf81f) == 0xe800))
! 		      baseaddr = memaddr - 2;
! 		  }
! 	      }
! 	    info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
! 	    if (pcrel && branch
! 		&& info->flavour == bfd_target_unknown_flavour)
! 	      /* For gdb disassembler, maintain odd address.  */
! 	      info->target |= 1;
! 	    (*info->print_address_func) (info->target, info);
! 	  }
!       }
!       break;
! 
!     case 'a':
!     case 'i':
!       {
! 	if (! use_extend)
! 	  extend = 0;
! 	l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
! 	if (type == 'a' && info->flavour == bfd_target_unknown_flavour)
! 	  /* For gdb disassembler, maintain odd address.  */
! 	  l |= 1;
!       }
!       info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
!       (*info->print_address_func) (info->target, info);
!       break;
! 
!     case 'l':
!     case 'L':
!       {
! 	int need_comma, amask, smask;
! 
! 	need_comma = 0;
! 
! 	l = GET_OP (l, IMM6);
! 
! 	amask = (l >> 3) & 7;
! 
! 	if (amask > 0 && amask < 5)
! 	  {
! 	    infprintf (is, "%s", mips_gpr_names[4]);
! 	    if (amask > 1)
! 	      infprintf (is, "-%s", mips_gpr_names[amask + 3]);
! 	    need_comma = 1;
! 	  }
! 
! 	smask = (l >> 1) & 3;
! 	if (smask == 3)
! 	  {
! 	    infprintf (is, "%s??", need_comma ? "," : "");
! 	    need_comma = 1;
! 	  }
! 	else if (smask > 0)
! 	  {
! 	    infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[16]);
! 	    if (smask > 1)
! 	      infprintf (is, "-%s", mips_gpr_names[smask + 15]);
! 	    need_comma = 1;
! 	  }
! 
! 	if (l & 1)
! 	  {
! 	    infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[31]);
! 	    need_comma = 1;
! 	  }
! 
! 	if (amask == 5 || amask == 6)
! 	  {
! 	    infprintf (is, "%s$f0", need_comma ? "," : "");
! 	    if (amask == 6)
! 	      infprintf (is, "-$f1");
! 	  }
!       }
!       break;
! 
!     case 'm':
!     case 'M':
!       /* MIPS16e save/restore.  */
!       {
!       int need_comma = 0;
!       int amask, args, statics;
!       int nsreg, smask;
!       int framesz;
!       int i, j;
! 
!       l = l & 0x7f;
!       if (use_extend)
!         l |= extend << 16;
! 
!       amask = (l >> 16) & 0xf;
!       if (amask == MIPS16_ALL_ARGS)
!         {
!           args = 4;
!           statics = 0;
!         }
!       else if (amask == MIPS16_ALL_STATICS)
!         {
!           args = 0;
!           statics = 4;
!         }
!       else
!         {
!           args = amask >> 2;
!           statics = amask & 3;
!         }
! 
!       if (args > 0) {
! 	  infprintf (is, "%s", mips_gpr_names[4]);
!           if (args > 1)
! 	    infprintf (is, "-%s", mips_gpr_names[4 + args - 1]);
!           need_comma = 1;
!       }
  
!       framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
!       if (framesz == 0 && !use_extend)
!         framesz = 128;
! 
!       infprintf (is, "%s%d", need_comma ? "," : "", framesz);
! 
!       if (l & 0x40)                   /* $ra */
! 	infprintf (is, ",%s", mips_gpr_names[31]);
! 
!       nsreg = (l >> 24) & 0x7;
!       smask = 0;
!       if (l & 0x20)                   /* $s0 */
!         smask |= 1 << 0;
!       if (l & 0x10)                   /* $s1 */
!         smask |= 1 << 1;
!       if (nsreg > 0)                  /* $s2-$s8 */
!         smask |= ((1 << nsreg) - 1) << 2;
! 
!       /* Find first set static reg bit.  */
!       for (i = 0; i < 9; i++)
!         {
!           if (smask & (1 << i))
!             {
! 	      infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
!               /* Skip over string of set bits.  */
!               for (j = i; smask & (2 << j); j++)
!                 continue;
!               if (j > i)
! 		infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
!               i = j + 1;
!             }
!         }
! 
!       /* Statics $ax - $a3.  */
!       if (statics == 1)
! 	infprintf (is, ",%s", mips_gpr_names[7]);
!       else if (statics > 0) 
! 	infprintf (is, ",%s-%s",
! 		   mips_gpr_names[7 - statics + 1],
! 		   mips_gpr_names[7]);
!       }
        break;
- 
-     default:
-       /* xgettext:c-format */
-       infprintf (is,
- 		 _("# internal disassembler error, "
- 		   "unrecognised modifier (%c)"),
- 		 type);
-       abort ();
      }
  }
  
--- 1414,1572 ----
        infprintf (is, "%c", type);
        break;
  
!     default:
!       operand = decode_mips16_operand (type, FALSE);
!       if (!operand)
! 	{
! 	  /* xgettext:c-format */
! 	  infprintf (is, _("# internal error, undefined operand in `%s %s'"),
! 		     opcode->name, opcode->args);
! 	  return;
! 	}
  
!       if (operand->type == OP_SAVE_RESTORE_LIST)
! 	{
! 	  /* Handle this case here because of the complex interation
! 	     with the EXTEND opcode.  */
! 	  unsigned int amask, nargs, nstatics, nsreg, smask, frame_size, i, j;
! 	  const char *sep;
  
! 	  amask = extend & 0xf;
! 	  if (amask == MIPS16_ALL_ARGS)
! 	    {
! 	      nargs = 4;
! 	      nstatics = 0;
! 	    }
! 	  else if (amask == MIPS16_ALL_STATICS)
! 	    {
! 	      nargs = 0;
! 	      nstatics = 4;
! 	    }
! 	  else
! 	    {
! 	      nargs = amask >> 2;
! 	      nstatics = amask & 3;
! 	    }
  
! 	  sep = "";
! 	  if (nargs > 0)
! 	    {
! 	      infprintf (is, "%s", mips_gpr_names[4]);
! 	      if (nargs > 1)
! 		infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
! 	      sep = ",";
! 	    }
  
! 	  frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
! 	  if (frame_size == 0 && !use_extend)
! 	    frame_size = 128;
! 	  infprintf (is, "%s%d", sep, frame_size);
! 
! 	  if (insn & 0x40)		/* $ra */
! 	    infprintf (is, ",%s", mips_gpr_names[31]);
! 
! 	  nsreg = (extend >> 8) & 0x7;
! 	  smask = 0;
! 	  if (insn & 0x20)		/* $s0 */
! 	    smask |= 1 << 0;
! 	  if (insn & 0x10)		/* $s1 */
! 	    smask |= 1 << 1;
! 	  if (nsreg > 0)		/* $s2-$s8 */
! 	    smask |= ((1 << nsreg) - 1) << 2;
  
! 	  for (i = 0; i < 9; i++)
! 	    if (smask & (1 << i))
  	      {
! 		infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
! 		/* Skip over string of set bits.  */
! 		for (j = i; smask & (2 << j); j++)
! 		  continue;
! 		if (j > i)
! 		  infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
! 		i = j + 1;
  	      }
! 	  /* Statics $ax - $a3.  */
! 	  if (nstatics == 1)
! 	    infprintf (is, ",%s", mips_gpr_names[7]);
! 	  else if (nstatics > 0)
! 	    infprintf (is, ",%s-%s",
! 		       mips_gpr_names[7 - nstatics + 1],
! 		       mips_gpr_names[7]);
! 	  break;
! 	}
  
!       if (is_offset && operand->type == OP_INT)
! 	{
! 	  const struct mips_int_operand *int_op;
  
! 	  int_op = (const struct mips_int_operand *) operand;
! 	  info->insn_type = dis_dref;
! 	  info->data_size = 1 << int_op->shift;
! 	}
  
!       if (operand->size == 26)
! 	/* In this case INSN is the first two bytes of the instruction
! 	   and EXTEND is the second two bytes.  */
! 	uval = ((insn & 0x1f) << 21) | ((insn & 0x3e0) << 11) | extend;
!       else
! 	{
! 	  /* Calculate the full field value.  */
! 	  uval = mips_extract_operand (operand, insn);
! 	  if (use_extend)
! 	    {
! 	      ext_operand = decode_mips16_operand (type, TRUE);
! 	      if (ext_operand != operand)
! 		{
! 		  operand = ext_operand;
! 		  if (operand->size == 16)
! 		    uval |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
! 		  else if (operand->size == 15)
! 		    uval |= ((extend & 0xf) << 11) | (extend & 0x7f0);
! 		  else
! 		    uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
! 		}
! 	    }
! 	}
  
!       baseaddr = memaddr + 2;
!       if (operand->type == OP_PCREL)
! 	{
! 	  const struct mips_pcrel_operand *pcrel_op;
  
! 	  pcrel_op = (const struct mips_pcrel_operand *) operand;
! 	  if (!pcrel_op->include_isa_bit && use_extend)
! 	    baseaddr = memaddr - 2;
! 	  else if (!pcrel_op->include_isa_bit)
! 	     {
! 	       bfd_byte buffer[2];
! 
! 	       /* If this instruction is in the delay slot of a JR
! 		  instruction, the base address is the address of the
! 		  JR instruction.  If it is in the delay slot of a JALR
! 		  instruction, the base address is the address of the
! 		  JALR instruction.  This test is unreliable: we have
! 		  no way of knowing whether the previous word is
! 		  instruction or data.  */
! 	       if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
! 		   && (((info->endian == BFD_ENDIAN_BIG
! 			 ? bfd_getb16 (buffer)
! 			 : bfd_getl16 (buffer))
! 			& 0xf800) == 0x1800))
! 		 baseaddr = memaddr - 4;
! 	       else if (info->read_memory_func (memaddr - 2, buffer, 2,
! 						info) == 0
  			&& (((info->endian == BFD_ENDIAN_BIG
  			      ? bfd_getb16 (buffer)
  			      : bfd_getl16 (buffer))
  			     & 0xf81f) == 0xe800))
! 		 baseaddr = memaddr - 2;
! 	       else
! 		 baseaddr = memaddr;
! 	     }
! 	}
  
!       print_insn_arg (info, state, opcode, operand, baseaddr, uval);
        break;
      }
  }
  
*************** print_insn_mips16 (bfd_vma memaddr, stru
*** 1859,1864 ****
--- 1600,1606 ----
    bfd_boolean use_extend;
    int extend = 0;
    const struct mips_opcode *op, *opend;
+   struct mips_print_arg_state state;
    void *is = info->stream;
  
    info->bytes_per_chunk = 2;
*************** print_insn_mips16 (bfd_vma memaddr, stru
*** 1869,1874 ****
--- 1611,1618 ----
    info->target = 0;
    info->target2 = 0;
  
+ #define GET_OP(insn, field) \
+   (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
    /* Decode PLT entry's GOT slot address word.  */
    if (is_mips16_plt_tail (info, memaddr))
      {
*************** print_insn_mips16 (bfd_vma memaddr, stru
*** 1979,1984 ****
--- 1723,1729 ----
  	  if (op->args[0] != '\0')
  	    infprintf (is, "\t");
  
+ 	  init_print_arg_state (&state);
  	  for (s = op->args; *s != '\0'; s++)
  	    {
  	      if (*s == ','
*************** print_insn_mips16 (bfd_vma memaddr, stru
*** 1997,2004 ****
  		  ++s;
  		  continue;
  		}
! 	      print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
! 				     info);
  	    }
  
  	  /* Figure out branch instruction type and delay slot information.  */
--- 1742,1749 ----
  		  ++s;
  		  continue;
  		}
! 	      print_mips16_insn_arg (info, &state, op, *s, memaddr, insn,
! 				     use_extend, extend, s[1] == '(');
  	    }
  
  	  /* Figure out branch instruction type and delay slot information.  */
*************** print_insn_mips16 (bfd_vma memaddr, stru
*** 2018,2024 ****
  	  return length;
  	}
      }
- #undef GET_OP_S
  #undef GET_OP
  
    if (use_extend)
--- 1763,1768 ----


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