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] Fuse microMIPS mh and mi operand types


Another patch making way for the MIPS operand rewrite.  The destination
pair in a microMIPS MOVEP instruction is encoded as a single 3-bit field.
At the moment we have separate operand types for each register in the pair:
"mh" and "mi".  This is OK because the first register in the pair is
always a 3-bit number, so the "mh" parser can stash the register in
the field for the "mi" parser to read back and process.

However, with the opcode rewrite it's more convenient to have one
operand type per opcode field rather than one operand type per
syntactic argument.  This patch makes "mh" stand for both registers
in the pair and gets rid of "mi".

Looks a bit ugly now, but IMO less so after the main patch.

Applied.

Richard


include/opcode/
	* mips.h: Remove "mi" documentation.  Update "mh" documentation.
	(OP_MASK_MI, OP_SH_MI, MICROMIPSOP_MASK_MI, MICROMIPSOP_MASK_MI):
	Delete.
	(INSN2_WRITE_GPR_MHI): Rename to...
	(INSN2_WRITE_GPR_MH): ...this.

opcodes/
	* micromips-opc.c (WR_mhi): Rename to..
	(WR_mh): ...this.
	(micromips_opcodes): Update "movep" entry accordingly.  Replace
	"mh,mi" with "mh".
	* mips-dis.c (micromips_to_32_reg_h_map): Rename to...
	(micromips_to_32_reg_h_map1): ...this.
	(micromips_to_32_reg_i_map): Rename to...
	(micromips_to_32_reg_h_map2): ...this.
	(print_micromips_insn): Remove "mi" case.  Print both registers
	in the pair for "mh".

gas/
	* config/tc-mips.c (mips32_to_micromips_reg_h_map): Delete.
	(micromips_to_32_reg_h_map): Rename to...
	(micromips_to_32_reg_h_map1): ...this.
	(micromips_to_32_reg_i_map): Rename to...
	(micromips_to_32_reg_h_map2): ...this.
	(mips_lookup_reg_pair): New function.
	(gpr_write_mask, macro): Adjust after above renaming.
	(validate_micromips_insn): Remove "mi" handling.
	(mips_ip): Likewise.  Parse both registers in a pair for "mh".

Index: include/opcode/mips.h
===================================================================
--- include/opcode/mips.h	2013-07-07 10:32:08.793375050 +0100
+++ include/opcode/mips.h	2013-07-07 10:33:34.080202509 +0100
@@ -279,8 +279,6 @@ #define OP_MASK_MG		0
 #define OP_SH_MG		0
 #define OP_MASK_MH		0
 #define OP_SH_MH		0
-#define OP_MASK_MI		0
-#define OP_SH_MI		0
 #define OP_MASK_MJ		0
 #define OP_SH_MJ		0
 #define OP_MASK_ML		0
@@ -685,8 +683,8 @@ #define INSN2_READ_PC		    0x08000000
 #define INSN2_UNCOND_BRANCH	    0x10000000
 /* Is a conditional branch insn. */
 #define INSN2_COND_BRANCH	    0x20000000
-/* Modifies the general purpose registers in MICROMIPSOP_*_MH/I.  */
-#define INSN2_WRITE_GPR_MHI	    0x40000000
+/* Modifies the general purpose registers in MICROMIPSOP_*_MH.  */
+#define INSN2_WRITE_GPR_MH	    0x40000000
 /* Reads the general purpose registers in MICROMIPSOP_*_MM/N.  */
 #define INSN2_READ_GPR_MMN	    0x80000000
 
@@ -1555,8 +1553,6 @@ #define MICROMIPSOP_MASK_MG		0x7
 #define MICROMIPSOP_SH_MG		0
 #define MICROMIPSOP_MASK_MH		0x7
 #define MICROMIPSOP_SH_MH		7
-#define MICROMIPSOP_MASK_MI		0x7
-#define MICROMIPSOP_SH_MI		7
 #define MICROMIPSOP_MASK_MJ		0x1f
 #define MICROMIPSOP_SH_MJ		0
 #define MICROMIPSOP_MASK_ML		0x7
@@ -1696,9 +1692,7 @@ #define MICROMIPSOP_MASK_EVAOFFSET	0x1ff
         The same register used as both source and target.
    "mf" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MF) at bit 3
    "mg" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MG) at bit 0
-   "mh" MIPS registers 4, 5, 6 (MICROMIPSOP_*_MH) at bit 7
-   "mi" MIPS registers 5, 6, 7, 21, 22 (MICROMIPSOP_*_MI) at bit 7
-	("mh" and "mi" form a valid 3-bit register pair)
+   "mh" 3-bit MIPS register pair (MICROMIPSOP_*_MH) at bit 7
    "mj" 5-bit MIPS registers (MICROMIPSOP_*_MJ) at bit 0
    "ml" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_ML) at bit 4
    "mm" 3-bit MIPS registers 0, 2, 3, 16-20 (MICROMIPSOP_*_MM) at bit 1
Index: opcodes/micromips-opc.c
===================================================================
--- opcodes/micromips-opc.c	2013-07-07 10:32:08.794375060 +0100
+++ opcodes/micromips-opc.c	2013-07-07 10:33:34.081202518 +0100
@@ -42,7 +42,7 @@ #define RD_me	INSN2_READ_GPR_ME
 #define RD_mf	INSN2_MOD_GPR_MF
 #define WR_mf	INSN2_MOD_GPR_MF
 #define RD_mg	INSN2_READ_GPR_MG
-#define WR_mhi	INSN2_WRITE_GPR_MHI
+#define WR_mh	INSN2_WRITE_GPR_MH
 #define RD_mj	INSN2_READ_GPR_MJ
 #define WR_mj	INSN2_WRITE_GPR_MJ
 #define RD_ml	RD_mc	/* Reuse, since the bit position is the same.  */
@@ -703,10 +703,10 @@ const struct mips_opcode micromips_opcod
 {"mov.d",   "T,S",	0x5400207b, 0xfc00ffff,	WR_T|RD_S|FP_D,		0,		I1	},
 {"mov.s",   "T,S",	0x5400007b, 0xfc00ffff,	WR_T|RD_S|FP_S,		0,		I1	},
 {"mov.ps",  "T,S",	0x5400407b, 0xfc00ffff,	WR_T|RD_S|FP_D,		0,		I1	},
-{"movep",   "mh,mi,mm,mn",  0x8400,     0xfc01,	NODS,			WR_mhi|RD_mmn,	I1	},
+{"movep",   "mh,mm,mn",     0x8400,     0xfc01,	NODS,			WR_mh|RD_mmn,	I1	},
 /* This macro is after the real instruction so that it only matches with
    -minsn32.  */
-{"movep",   "mh,mi,mm,mn", 0, (int) M_MOVEP,	INSN_MACRO,		0,		I1	},
+{"movep",   "mh,mm,mn", 0, (int) M_MOVEP,	INSN_MACRO,		0,		I1	},
 {"movf",    "t,s,M",	0x5400017b, 0xfc001fff,	WR_t|RD_s|RD_CC|FP_S|FP_D, 0,		I1	},
 {"movf.d",  "T,S,M",	0x54000220, 0xfc001fff,	WR_T|RD_S|RD_CC|FP_D,	0,		I1	},
 {"movf.s",  "T,S,M",	0x54000020, 0xfc001fff,	WR_T|RD_S|RD_CC|FP_S,	0,		I1	},
Index: opcodes/mips-dis.c
===================================================================
--- opcodes/mips-dis.c	2013-07-07 10:32:08.796375080 +0100
+++ opcodes/mips-dis.c	2013-07-07 10:33:34.082202527 +0100
@@ -76,13 +76,11 @@ #define micromips_to_32_reg_f_map	mips16
 #define micromips_to_32_reg_g_map	mips16_to_32_reg_map
 
 /* The microMIPS registers with type h.  */
-static const unsigned int micromips_to_32_reg_h_map[] =
+static const unsigned int micromips_to_32_reg_h_map1[] =
 {
   5, 5, 6, 4, 4, 4, 4, 4
 };
-
-/* The microMIPS registers with type i.  */
-static const unsigned int micromips_to_32_reg_i_map[] =
+static const unsigned int micromips_to_32_reg_h_map2[] =
 {
   6, 7, 7, 21, 22, 5, 6, 7
 };
@@ -2716,13 +2714,10 @@ #define GET_OP_S(insn, field) \
 		      break;
 
 		    case 'h':
-		      regno = micromips_to_32_reg_h_map[GET_OP (insn, MH)];
-		      infprintf (is, "%s", mips_gpr_names[regno]);
-		      break;
-
-		    case 'i':
-		      regno = micromips_to_32_reg_i_map[GET_OP (insn, MI)];
+		      regno = micromips_to_32_reg_h_map1[GET_OP (insn, MH)];
 		      infprintf (is, "%s", mips_gpr_names[regno]);
+		      regno = micromips_to_32_reg_h_map2[GET_OP (insn, MH)];
+		      infprintf (is, ",%s", mips_gpr_names[regno]);
 		      break;
 
 		    case 'j':
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c	2013-07-07 10:32:08.804375159 +0100
+++ gas/config/tc-mips.c	2013-07-07 10:35:38.247359024 +0100
@@ -779,15 +779,6 @@ #define mips32_to_micromips_reg_g_map	mi
 #define mips32_to_micromips_reg_l_map	mips32_to_16_reg_map
 
 #define X ILLEGAL_REG
-/* reg type h: 4, 5, 6.  */
-static const int mips32_to_micromips_reg_h_map[] =
-{
-  X, X, X, X, 4, 5, 6, X,
-  X, X, X, X, X, X, X, X,
-  X, X, X, X, X, X, X, X,
-  X, X, X, X, X, X, X, X
-};
-
 /* reg type m: 0, 17, 2, 3, 16, 18, 19, 20.  */
 static const int mips32_to_micromips_reg_m_map[] =
 {
@@ -819,13 +810,11 @@ #define micromips_to_32_reg_f_map	mips16
 #define micromips_to_32_reg_g_map	mips16_to_32_reg_map
 
 /* The microMIPS registers with type h.  */
-static const unsigned int micromips_to_32_reg_h_map[] =
+static const unsigned int micromips_to_32_reg_h_map1[] =
 {
   5, 5, 6, 4, 4, 4, 4, 4
 };
-
-/* The microMIPS registers with type i.  */
-static const unsigned int micromips_to_32_reg_i_map[] =
+static const unsigned int micromips_to_32_reg_h_map2[] =
 {
   6, 7, 7, 21, 22, 5, 6, 7
 };
@@ -2591,6 +2580,19 @@ reglist_lookup (char **s, unsigned int t
   return ok && reglist != 0;
 }
 
+static unsigned int
+mips_lookup_reg_pair (unsigned int regno1, unsigned int regno2,
+		      const unsigned int *map1, const unsigned int *map2,
+		      unsigned int count)
+{
+  unsigned int i;
+
+  for (i = 0; i < count; i++)
+    if (map1[i] == regno1 && map2[i] == regno2)
+      return i;
+  return ILLEGAL_REG;
+}
+
 /* Return TRUE if opcode MO is valid on the currently selected ISA, ASE
    and architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
 
@@ -3503,10 +3505,10 @@ gpr_write_mask (const struct mips_cl_ins
     {
       if (pinfo2 & INSN2_WRITE_GPR_MB)
 	mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
-      if (pinfo2 & INSN2_WRITE_GPR_MHI)
+      if (pinfo2 & INSN2_WRITE_GPR_MH)
 	{
-	  mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
-	  mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+	  mask |= 1 << micromips_to_32_reg_h_map1[EXTRACT_OPERAND (1, MH, *ip)];
+	  mask |= 1 << micromips_to_32_reg_h_map2[EXTRACT_OPERAND (1, MH, *ip)];
 	}
       if (pinfo2 & INSN2_WRITE_GPR_MJ)
 	mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
@@ -9843,8 +9845,8 @@ macro (struct mips_cl_insn *ip, char *st
     case M_MOVEP:
       gas_assert (mips_opts.micromips);
       gas_assert (mips_opts.insn32);
-      dreg = micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
-      breg = micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+      dreg = micromips_to_32_reg_h_map1[EXTRACT_OPERAND (1, MH, *ip)];
+      breg = micromips_to_32_reg_h_map2[EXTRACT_OPERAND (1, MH, *ip)];
       sreg = micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
       treg = micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
       move_register (dreg, sreg);
@@ -11110,7 +11112,6 @@ #define USE_BITS(field) \
 	  case 'f': USE_BITS (MF);	break;
 	  case 'g': USE_BITS (MG);	break;
 	  case 'h': USE_BITS (MH);	break;
-	  case 'i': USE_BITS (MI);	break;
 	  case 'j': USE_BITS (MJ);	break;
 	  case 'l': USE_BITS (ML);	break;
 	  case 'm': USE_BITS (MM);	break;
@@ -11287,7 +11288,7 @@ mips_ip (char *str, struct mips_cl_insn
   char c = 0;
   struct mips_opcode *insn;
   char *argsStart;
-  unsigned int regno;
+  unsigned int regno, regno2;
   unsigned int lastregno;
   unsigned int destregno = 0;
   unsigned int lastpos = 0;
@@ -13141,7 +13142,6 @@ mips_ip (char *str, struct mips_cl_insn
 		case 'f':
 		case 'g':
 		case 'h':
-		case 'i':
 		case 'j':
 		case 'l':
 		case 'm':
@@ -13264,47 +13264,32 @@ mips_ip (char *str, struct mips_cl_insn
 			break;
 
 		      case 'h':
-			regno = mips32_to_micromips_reg_h_map[regno];
-			break;
-
-		      case 'i':
-			switch (EXTRACT_OPERAND (1, MI, *ip))
+			s += strspn (s, " \t");
+			if (*s != ',')
 			  {
-			    case 4:
-			      if (regno == 21)
-				regno = 3;
-			      else if (regno == 22)
-				regno = 4;
-			      else if (regno == 5)
-				regno = 5;
-			      else if (regno == 6)
-				regno = 6;
-			      else if (regno == 7)
-				regno = 7;
-			      else
-				regno = ILLEGAL_REG;
-			      break;
-
-			    case 5:
-			      if (regno == 6)
-				regno = 0;
-			      else if (regno == 7)
-				regno = 1;
-			      else
-				regno = ILLEGAL_REG;
-			      break;
-
-			    case 6:
-			      if (regno == 7)
-				regno = 2;
-			      else
-				regno = ILLEGAL_REG;
-			      break;
-
-			    default:
-			      regno = ILLEGAL_REG;
-			      break;
+			    regno = ILLEGAL_REG;
+			    break;
 			  }
+			++s;
+			s += strspn (s, " \t");
+			ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, &regno2);
+			if (!ok)
+			  {
+			    regno = ILLEGAL_REG;
+			    break;
+			  }
+			if (regno2 == AT && mips_opts.at)
+			  {
+			    if (mips_opts.at == ATREG)
+			      as_warn (_("Used $at without \".set noat\""));
+			    else
+			      as_warn (_("Used $%u with \".set at=$%u\""),
+				       regno2, mips_opts.at);
+			  }
+			regno = (mips_lookup_reg_pair
+				 (regno, regno2,
+				  micromips_to_32_reg_h_map1,
+				  micromips_to_32_reg_h_map2, 8));
 			break;
 
 		      case 'l':
@@ -13381,10 +13366,6 @@ mips_ip (char *str, struct mips_cl_insn
 			INSERT_OPERAND (1, MH, *ip, regno);
 			break;
 
-		      case 'i':
-			INSERT_OPERAND (1, MI, *ip, regno);
-			break;
-
 		      case 'j':
 			INSERT_OPERAND (1, MJ, *ip, regno);
 			break;


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