--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -569,7 +569,7 @@ static char *save_stack_p;
 static i386_insn i;
 
 /* Possible templates for current insn.  */
-static const templates *current_templates;
+static templates current_templates;
 
 /* Per instruction expressionS buffers: max displacements & immediates.  */
 static expressionS disp_expressions[MAX_MEMORY_OPERANDS];
@@ -3101,6 +3101,20 @@ i386_mach (void)
 
 #include "opcodes/i386-tbl.h"
 
+static void
+op_lookup (const char *mnemonic)
+{
+   i386_op_off_t *pos = str_hash_find (op_hash, mnemonic);
+
+   if (pos != NULL)
+     {
+       current_templates.start = &i386_optab[pos[0]];
+       current_templates.end = &i386_optab[pos[1]];
+     }
+   else
+     current_templates.end = current_templates.start = NULL;
+}
+
 void
 md_begin (void)
 {
@@ -3111,16 +3125,12 @@ md_begin (void)
   op_hash = str_htab_create ();
 
   {
-    const insn_template *const *sets = i386_op_sets;
-    const insn_template *const *end = sets + ARRAY_SIZE (i386_op_sets) - 1;
+    const i386_op_off_t *cur = i386_op_sets;
+    const i386_op_off_t *end = cur + ARRAY_SIZE (i386_op_sets) - 1;
 
-    /* Type checks to compensate for the conversion through void * which
-       occurs during hash table insertion / lookup.  */
-    (void) sizeof (sets == &current_templates->start);
-    (void) sizeof (end == &current_templates->end);
-    for (; sets < end; ++sets)
-      if (str_hash_insert (op_hash, insn_name (*sets), sets, 0))
-	as_fatal (_("duplicate %s"), insn_name (*sets));
+    for (; cur < end; ++cur)
+      if (str_hash_insert (op_hash, insn_name (&i386_optab[*cur]), cur, 0))
+	as_fatal (_("duplicate %s"), insn_name (&i386_optab[*cur]));
   }
 
   /* Initialize reg_hash hash table.  */
@@ -5121,7 +5131,7 @@ md_assemble (char *line)
   const insn_template *t;
 
   /* Initialize globals.  */
-  current_templates = NULL;
+  current_templates.end = current_templates.start = NULL;
  retry:
   init_globals ();
 
@@ -5136,8 +5146,8 @@ md_assemble (char *line)
 	goto match_error;
       if (i.error != no_error)
 	{
-	  gas_assert (current_templates != NULL);
-	  if (may_need_pass2 (current_templates->start) && !i.suffix)
+	  gas_assert (current_templates.start != NULL);
+	  if (may_need_pass2 (current_templates.start) && !i.suffix)
 	    goto no_match;
 	  /* No point in trying a 2nd pass - it'll only find the same suffix
 	     again.  */
@@ -5146,7 +5156,7 @@ md_assemble (char *line)
 	}
       return;
     }
-  t = current_templates->start;
+  t = current_templates.start;
   if (may_need_pass2 (t))
     {
       /* Make a copy of the full line in case we need to retry.  */
@@ -5204,7 +5214,7 @@ md_assemble (char *line)
 	 32-bit immediate and 64-bit operand size use sign-extended
 	 immediates (imm32s). Therefore these insns are special-cased, bypassing
 	 the normal handling of immediates here.  */
-      if (is_cpu(current_templates->start, CpuUSER_MSR))
+      if (is_cpu(current_templates.start, CpuUSER_MSR))
 	{
 	  for (j = 0; j < i.operands; j++)
 	    {
@@ -5233,7 +5243,7 @@ md_assemble (char *line)
 	  copy = NULL;
   no_match:
 	  pass1_err = i.error;
-	  pass1_mnem = insn_name (current_templates->start);
+	  pass1_mnem = insn_name (current_templates.start);
 	  goto retry;
 	}
 
@@ -5276,11 +5286,11 @@ md_assemble (char *line)
 	  break;
 	case unsupported:
 	  as_bad (_("unsupported instruction `%s'"),
-		  pass1_mnem ? pass1_mnem : insn_name (current_templates->start));
+		  pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
 	  return;
 	case unsupported_on_arch:
 	  as_bad (_("`%s' is not supported on `%s%s'"),
-		  pass1_mnem ? pass1_mnem : insn_name (current_templates->start),
+		  pass1_mnem ? pass1_mnem : insn_name (current_templates.start),
 		  cpu_arch_name ? cpu_arch_name : default_arch,
 		  cpu_sub_arch_name ? cpu_sub_arch_name : "");
 	  return;
@@ -5289,21 +5299,21 @@ md_assemble (char *line)
 	    {
 	      if (flag_code == CODE_64BIT)
 		as_bad (_("`%s%c' is not supported in 64-bit mode"),
-			pass1_mnem ? pass1_mnem : insn_name (current_templates->start),
+			pass1_mnem ? pass1_mnem : insn_name (current_templates.start),
 			mnem_suffix);
 	      else
 		as_bad (_("`%s%c' is only supported in 64-bit mode"),
-			pass1_mnem ? pass1_mnem : insn_name (current_templates->start),
+			pass1_mnem ? pass1_mnem : insn_name (current_templates.start),
 			mnem_suffix);
 	    }
 	  else
 	    {
 	      if (flag_code == CODE_64BIT)
 		as_bad (_("`%s' is not supported in 64-bit mode"),
-			pass1_mnem ? pass1_mnem : insn_name (current_templates->start));
+			pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
 	      else
 		as_bad (_("`%s' is only supported in 64-bit mode"),
-			pass1_mnem ? pass1_mnem : insn_name (current_templates->start));
+			pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
 	    }
 	  return;
 	case no_vex_encoding:
@@ -5350,14 +5360,14 @@ md_assemble (char *line)
 	  break;
 	case unsupported_vector_size:
 	  as_bad (_("vector size above %u required for `%s'"), 128u << vector_size,
-		  pass1_mnem ? pass1_mnem : insn_name (current_templates->start));
+		  pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
 	  return;
 	case internal_error:
 	  err_msg = _("internal error");
 	  break;
 	}
       as_bad (_("%s for `%s'"), err_msg,
-	      pass1_mnem ? pass1_mnem : insn_name (current_templates->start));
+	      pass1_mnem ? pass1_mnem : insn_name (current_templates.start));
       return;
     }
 
@@ -5710,7 +5720,7 @@ parse_insn (const char *line, char *mnem
 {
   const char *l = line, *token_start = l;
   char *mnem_p;
-  bool pass1 = !current_templates;
+  bool pass1 = !current_templates.start;
   int supported;
   const insn_template *t;
   char *dot_p = NULL;
@@ -5771,47 +5781,47 @@ parse_insn (const char *line, char *mnem
 	}
 
       /* Look up instruction (or prefix) via hash table.  */
-      current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
+      op_lookup (mnemonic);
 
       if (*l != END_OF_INSN
 	  && (!is_space_char (*l) || l[1] != END_OF_INSN)
-	  && current_templates
-	  && current_templates->start->opcode_modifier.isprefix)
+	  && current_templates.start
+	  && current_templates.start->opcode_modifier.isprefix)
 	{
-	  supported = cpu_flags_match (current_templates->start);
+	  supported = cpu_flags_match (current_templates.start);
 	  if (!(supported & CPU_FLAGS_64BIT_MATCH))
 	    {
 	      as_bad ((flag_code != CODE_64BIT
 		       ? _("`%s' is only supported in 64-bit mode")
 		       : _("`%s' is not supported in 64-bit mode")),
-		      insn_name (current_templates->start));
+		      insn_name (current_templates.start));
 	      return NULL;
 	    }
 	  if (supported != CPU_FLAGS_PERFECT_MATCH)
 	    {
 	      as_bad (_("`%s' is not supported on `%s%s'"),
-		      insn_name (current_templates->start),
+		      insn_name (current_templates.start),
 		      cpu_arch_name ? cpu_arch_name : default_arch,
 		      cpu_sub_arch_name ? cpu_sub_arch_name : "");
 	      return NULL;
 	    }
 	  /* If we are in 16-bit mode, do not allow addr16 or data16.
 	     Similarly, in 32-bit mode, do not allow addr32 or data32.  */
-	  if ((current_templates->start->opcode_modifier.size == SIZE16
-	       || current_templates->start->opcode_modifier.size == SIZE32)
+	  if ((current_templates.start->opcode_modifier.size == SIZE16
+	       || current_templates.start->opcode_modifier.size == SIZE32)
 	      && flag_code != CODE_64BIT
-	      && ((current_templates->start->opcode_modifier.size == SIZE32)
+	      && ((current_templates.start->opcode_modifier.size == SIZE32)
 		  ^ (flag_code == CODE_16BIT)))
 	    {
 	      as_bad (_("redundant %s prefix"),
-		      insn_name (current_templates->start));
+		      insn_name (current_templates.start));
 	      return NULL;
 	    }
 
-	  if (current_templates->start->base_opcode == PSEUDO_PREFIX)
+	  if (current_templates.start->base_opcode == PSEUDO_PREFIX)
 	    {
 	      /* Handle pseudo prefixes.  */
-	      switch (current_templates->start->extension_opcode)
+	      switch (current_templates.start->extension_opcode)
 		{
 		case Prefix_Disp8:
 		  /* {disp8} */
@@ -5860,21 +5870,21 @@ parse_insn (const char *line, char *mnem
 	  else
 	    {
 	      /* Add prefix, checking for repeated prefixes.  */
-	      switch (add_prefix (current_templates->start->base_opcode))
+	      switch (add_prefix (current_templates.start->base_opcode))
 		{
 		case PREFIX_EXIST:
 		  return NULL;
 		case PREFIX_DS:
-		  if (is_cpu (current_templates->start, CpuIBT))
-		    i.notrack_prefix = insn_name (current_templates->start);
+		  if (is_cpu (current_templates.start, CpuIBT))
+		    i.notrack_prefix = insn_name (current_templates.start);
 		  break;
 		case PREFIX_REP:
-		  if (is_cpu (current_templates->start, CpuHLE))
-		    i.hle_prefix = insn_name (current_templates->start);
-		  else if (is_cpu (current_templates->start, CpuMPX))
-		    i.bnd_prefix = insn_name (current_templates->start);
+		  if (is_cpu (current_templates.start, CpuHLE))
+		    i.hle_prefix = insn_name (current_templates.start);
+		  else if (is_cpu (current_templates.start, CpuMPX))
+		    i.bnd_prefix = insn_name (current_templates.start);
 		  else
-		    i.rep_prefix = insn_name (current_templates->start);
+		    i.rep_prefix = insn_name (current_templates.start);
 		  break;
 		default:
 		  break;
@@ -5890,7 +5900,7 @@ parse_insn (const char *line, char *mnem
   if (prefix_only)
     return token_start;
 
-  if (!current_templates)
+  if (!current_templates.start)
     {
       /* Deprecated functionality (new code should use pseudo-prefixes instead):
 	 Check if we should swap operand or force 32bit displacement in
@@ -5926,12 +5936,12 @@ parse_insn (const char *line, char *mnem
 	goto check_suffix;
       mnem_p = dot_p;
       *dot_p = '\0';
-      current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
+      op_lookup (mnemonic);
     }
 
-  if (!current_templates || !pass1)
+  if (!current_templates.start || !pass1)
     {
-      current_templates = NULL;
+      current_templates.start = NULL;
 
     check_suffix:
       if (mnem_p > mnemonic)
@@ -5948,8 +5958,7 @@ parse_insn (const char *line, char *mnem
 	      case QWORD_MNEM_SUFFIX:
 		i.suffix = mnem_p[-1];
 	      mnem_p[-1] = '\0';
-	      current_templates
-		= (const templates *) str_hash_find (op_hash, mnemonic);
+	      op_lookup (mnemonic);
 	      break;
 	    case SHORT_MNEM_SUFFIX:
 	    case LONG_MNEM_SUFFIX:
@@ -5957,8 +5966,7 @@ parse_insn (const char *line, char *mnem
 		{
 		  i.suffix = mnem_p[-1];
 		  mnem_p[-1] = '\0';
-		  current_templates
-		    = (const templates *) str_hash_find (op_hash, mnemonic);
+		  op_lookup (mnemonic);
 		}
 	      break;
 
@@ -5971,8 +5979,7 @@ parse_insn (const char *line, char *mnem
 		  else
 		    i.suffix = LONG_MNEM_SUFFIX;
 		  mnem_p[-1] = '\0';
-		  current_templates
-		    = (const templates *) str_hash_find (op_hash, mnemonic);
+		  op_lookup (mnemonic);
 		}
 	      /* For compatibility reasons accept MOVSD and CMPSD without
 	         operands even in AT&T mode.  */
@@ -5980,12 +5987,11 @@ parse_insn (const char *line, char *mnem
 		       || (is_space_char (*l) && l[1] == END_OF_INSN))
 		{
 		  mnem_p[-1] = '\0';
-		  current_templates
-		    = (const templates *) str_hash_find (op_hash, mnemonic);
-		  if (current_templates != NULL
+		  op_lookup (mnemonic);
+		  if (current_templates.start != NULL
 		      /* MOVS or CMPS */
-		      && (current_templates->start->base_opcode | 2) == 0xa6
-		      && current_templates->start->opcode_space
+		      && (current_templates.start->base_opcode | 2) == 0xa6
+		      && current_templates.start->opcode_space
 			 == SPACE_BASE
 		      && mnem_p[-2] == 's')
 		    {
@@ -5995,7 +6001,7 @@ parse_insn (const char *line, char *mnem
 		    }
 		  else
 		    {
-		      current_templates = NULL;
+		      current_templates.start = NULL;
 		      mnem_p[-1] = 'd';
 		    }
 		}
@@ -6003,7 +6009,7 @@ parse_insn (const char *line, char *mnem
 	    }
 	}
 
-      if (!current_templates)
+      if (!current_templates.start)
 	{
 	  if (pass1)
 	    as_bad (_("no such instruction: `%s'"), token_start);
@@ -6011,8 +6017,8 @@ parse_insn (const char *line, char *mnem
 	}
     }
 
-  if (current_templates->start->opcode_modifier.jump == JUMP
-      || current_templates->start->opcode_modifier.jump == JUMP_BYTE)
+  if (current_templates.start->opcode_modifier.jump == JUMP
+      || current_templates.start->opcode_modifier.jump == JUMP_BYTE)
     {
       /* Check for a branch hint.  We allow ",pt" and ",pn" for
 	 predict taken and predict not taken respectively.
@@ -6046,7 +6052,7 @@ parse_insn (const char *line, char *mnem
 
   /* Check if instruction is supported on specified architecture.  */
   supported = 0;
-  for (t = current_templates->start; t < current_templates->end; ++t)
+  for (t = current_templates.start; t < current_templates.end; ++t)
     {
       supported |= cpu_flags_match (t);
 
@@ -6313,7 +6319,7 @@ optimize_imm (void)
 	       /* A more generic (but also more involved) way of dealing
 		  with the special case(s) would be to go look for
 		  DefaultSize attributes on any of the templates.  */
-	       && current_templates->start->mnem_off != MN_push))
+	       && current_templates.start->mnem_off != MN_push))
     guess_suffix = LONG_MNEM_SUFFIX;
 
   for (op = i.operands; --op >= 0;)
@@ -6387,7 +6393,7 @@ optimize_imm (void)
 	       than those matching the insn suffix.  */
 	    {
 	      i386_operand_type mask, allowed;
-	      const insn_template *t = current_templates->start;
+	      const insn_template *t = current_templates.start;
 
 	      operand_type_set (&mask, 0);
 	      switch (guess_suffix)
@@ -6410,7 +6416,7 @@ optimize_imm (void)
 		}
 
 	      allowed = operand_type_and (t->operand_types[op], mask);
-	      while (++t < current_templates->end)
+	      while (++t < current_templates.end)
 		{
 		  allowed = operand_type_or (allowed, t->operand_types[op]);
 		  allowed = operand_type_and (allowed, mask);
@@ -7034,7 +7040,7 @@ match_template (char mnem_suffix)
   found_reverse_match = 0;
   addr_prefix_disp = -1;
 
-  for (t = current_templates->start; t < current_templates->end; t++)
+  for (t = current_templates.start; t < current_templates.end; t++)
     {
       addr_prefix_disp = -1;
       found_reverse_match = 0;
@@ -7483,11 +7489,11 @@ match_template (char mnem_suffix)
 	 Vxy / Exy constructs: There are 3 suffix-less EVEX forms, the latter
 	 two of which may fall back to their two corresponding VEX forms.  */
       j = t->mnem_off != MN_vcvtneps2bf16 ? 1 : 2;
-      if ((t == current_templates->start || j > 1)
+      if ((t == current_templates.start || j > 1)
 	  && t->opcode_modifier.disp8memshift
 	  && !t->opcode_modifier.vex
 	  && !need_evex_encoding ()
-	  && t + j < current_templates->end
+	  && t + j < current_templates.end
 	  && t[j].opcode_modifier.vex)
 	{
 	  i386_cpu_flags cpu;
@@ -7515,7 +7521,7 @@ match_template (char mnem_suffix)
 
 #undef progress
 
-  if (t == current_templates->end)
+  if (t == current_templates.end)
     {
       /* We found no match.  */
       i.error = specific_error;
@@ -10942,7 +10948,6 @@ s_insn (int dummy ATTRIBUTE_UNUSED)
   unsigned int j;
   valueT val;
   bool vex = false, xop = false, evex = false;
-  static const templates tt = { &i.tm, &i.tm + 1 };
 
   init_globals ();
 
@@ -10960,7 +10965,8 @@ s_insn (int dummy ATTRIBUTE_UNUSED)
     }
   line += end - line;
 
-  current_templates = &tt;
+  current_templates.start = &i.tm;
+  current_templates.end = &i.tm + 1;
   i.tm.mnem_off = MN__insn;
   i.tm.extension_opcode = None;
 
@@ -12177,8 +12183,8 @@ i386_displacement (char *disp_start, cha
   operand_type_set (&bigdisp, 0);
   if (i.jumpabsolute
       || i.types[this_operand].bitfield.baseindex
-      || (current_templates->start->opcode_modifier.jump != JUMP
-	  && current_templates->start->opcode_modifier.jump != JUMP_DWORD))
+      || (current_templates.start->opcode_modifier.jump != JUMP
+	  && current_templates.start->opcode_modifier.jump != JUMP_DWORD))
     {
       i386_addressing_mode ();
       override = (i.prefix[ADDR_PREFIX] != 0);
@@ -12199,24 +12205,18 @@ i386_displacement (char *disp_start, cha
 	 dependent upon data size, but is never dependent upon address size.
 	 Also make sure to not unintentionally match against a non-PC-relative
 	 branch template.  */
-      static templates aux_templates;
-      const insn_template *t = current_templates->start;
+      const insn_template *t = current_templates.start;
       bool has_intel64 = false;
 
-      aux_templates.start = t;
-      while (++t < current_templates->end)
+      while (++t < current_templates.end)
 	{
 	  if (t->opcode_modifier.jump
-	      != current_templates->start->opcode_modifier.jump)
+	      != current_templates.start->opcode_modifier.jump)
 	    break;
 	  if ((t->opcode_modifier.isa64 >= INTEL64))
 	    has_intel64 = true;
 	}
-      if (t < current_templates->end)
-	{
-	  aux_templates.end = t;
-	  current_templates = &aux_templates;
-	}
+      current_templates.end = t;
 
       override = (i.prefix[DATA_PREFIX] != 0);
       if (flag_code == CODE_64BIT)
@@ -12389,7 +12389,7 @@ i386_finalize_displacement (segT exp_seg
     }
 #endif
 
-  else if (current_templates->start->opcode_modifier.jump == JUMP_BYTE)
+  else if (current_templates.start->opcode_modifier.jump == JUMP_BYTE)
     i.types[this_operand].bitfield.disp8 = 1;
 
   /* Check if this is a displacement only operand.  */
@@ -12413,7 +12413,7 @@ i386_addressing_mode (void)
   if (i.prefix[ADDR_PREFIX])
     addr_mode = flag_code == CODE_32BIT ? CODE_16BIT : CODE_32BIT;
   else if (flag_code == CODE_16BIT
-	   && is_cpu (current_templates->start, CpuMPX)
+	   && is_cpu (current_templates.start, CpuMPX)
 	   /* Avoid replacing the "16-bit addressing not allowed" diagnostic
 	      from md_assemble() by "is not a valid base/index expression"
 	      when there is a base and/or index.  */
@@ -12486,7 +12486,7 @@ i386_index_check (const char *operand_st
 {
   const char *kind = "base/index";
   enum flag_code addr_mode = i386_addressing_mode ();
-  const insn_template *t = current_templates->end - 1;
+  const insn_template *t = current_templates.end - 1;
 
   if (t->opcode_modifier.isstring)
     {
@@ -12553,7 +12553,7 @@ i386_index_check (const char *operand_st
     }
   else
     {
-      t = current_templates->start;
+      t = current_templates.start;
 
       if (addr_mode != CODE_16BIT)
 	{
@@ -12678,7 +12678,7 @@ i386_att_operand (char *operand_string)
   /* We check for an absolute prefix (differentiating,
      for example, 'jmp pc_relative_label' from 'jmp *absolute_label'.  */
   if (*op_string == ABSOLUTE_PREFIX
-      && current_templates->start->opcode_modifier.jump)
+      && current_templates.start->opcode_modifier.jump)
     {
       ++op_string;
       if (is_space_char (*op_string))
@@ -12710,7 +12710,7 @@ i386_att_operand (char *operand_string)
 
 	  /* Handle case of %es:*foo.  */
 	  if (!i.jumpabsolute && *op_string == ABSOLUTE_PREFIX
-	      && current_templates->start->opcode_modifier.jump)
+	      && current_templates.start->opcode_modifier.jump)
 	    {
 	      ++op_string;
 	      if (is_space_char (*op_string))
@@ -12767,7 +12767,7 @@ i386_att_operand (char *operand_string)
 	    if (i.rounding.type == RC_NamesTable[j].type)
 	      break;
 	  as_bad (_("`%s': misplaced `{%s}'"),
-		  insn_name (current_templates->start), RC_NamesTable[j].name);
+		  insn_name (current_templates.start), RC_NamesTable[j].name);
 	  return 0;
 	}
     }
@@ -12789,7 +12789,7 @@ i386_att_operand (char *operand_string)
       if (i.rounding.type != rc_none)
 	{
 	  as_bad (_("`%s': RC/SAE operand must follow immediate operands"),
-		  insn_name (current_templates->start));
+		  insn_name (current_templates.start));
 	  return 0;
 	}
     }
@@ -12802,7 +12802,7 @@ i386_att_operand (char *operand_string)
 	      && i.op[0].regs->reg_type.bitfield.class != Reg))
 	{
 	  as_bad (_("`%s': misplaced `%s'"),
-		  insn_name (current_templates->start), operand_string);
+		  insn_name (current_templates.start), operand_string);
 	  return 0;
 	}
     }
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -345,7 +345,7 @@ i386_intel_simplify_register (expression
     intel_state.base = i386_regtab + reg_num;
   else if (!intel_state.index)
     {
-      const insn_template *t = current_templates->start;
+      const insn_template *t = current_templates.start;
 
       if (intel_state.in_scale
 	  || i386_regtab[reg_num].reg_type.bitfield.baseindex
@@ -614,7 +614,7 @@ i386_intel_operand (char *operand_string
       if (i.imm_operands)
 	{
 	  as_bad (_("`%s': RC/SAE operand must precede immediate operands"),
-		  insn_name (current_templates->start));
+		  insn_name (current_templates.start));
 	  return 0;
 	}
 
@@ -687,7 +687,7 @@ i386_intel_operand (char *operand_string
     return 0;
 
   if (intel_state.op_modifier != O_absent
-      && current_templates->start->mnem_off != MN_lea)
+      && current_templates.start->mnem_off != MN_lea)
     {
       i.types[this_operand].bitfield.unspecified = 0;
 
@@ -702,22 +702,22 @@ i386_intel_operand (char *operand_string
 	  i.types[this_operand].bitfield.word = 1;
 	  if (got_a_float == 2)	/* "fi..." */
 	    suffix = SHORT_MNEM_SUFFIX;
-	  else if (current_templates->start->mnem_off != MN_lar
-		   && current_templates->start->mnem_off != MN_lsl
-		   && current_templates->start->mnem_off != MN_arpl)
+	  else if (current_templates.start->mnem_off != MN_lar
+		   && current_templates.start->mnem_off != MN_lsl
+		   && current_templates.start->mnem_off != MN_arpl)
 	    suffix = WORD_MNEM_SUFFIX;
 	  break;
 
 	case O_dword_ptr:
 	  i.types[this_operand].bitfield.dword = 1;
-	  if ((insn_name (current_templates->start)[0] == 'l'
-	       && insn_name (current_templates->start)[2] == 's'
-	       && insn_name (current_templates->start)[3] == 0)
-	      || current_templates->start->mnem_off == MN_bound)
+	  if ((insn_name (current_templates.start)[0] == 'l'
+	       && insn_name (current_templates.start)[2] == 's'
+	       && insn_name (current_templates.start)[3] == 0)
+	      || current_templates.start->mnem_off == MN_bound)
 	    suffix = WORD_MNEM_SUFFIX;
 	  else if (flag_code != CODE_32BIT
-		   && (current_templates->start->opcode_modifier.jump == JUMP
-		       || current_templates->start->opcode_modifier.jump
+		   && (current_templates.start->opcode_modifier.jump == JUMP
+		       || current_templates.start->opcode_modifier.jump
 			  == JUMP_DWORD))
 	    {
 	      i.far_branch = true;
@@ -731,11 +731,11 @@ i386_intel_operand (char *operand_string
 
 	case O_fword_ptr:
 	  i.types[this_operand].bitfield.fword = 1;
-	  if (current_templates->start->mnem_off == MN_les
-	      || current_templates->start->mnem_off == MN_lds
-	      || current_templates->start->mnem_off == MN_lss
-	      || current_templates->start->mnem_off == MN_lfs
-	      || current_templates->start->mnem_off == MN_lgs)
+	  if (current_templates.start->mnem_off == MN_les
+	      || current_templates.start->mnem_off == MN_lds
+	      || current_templates.start->mnem_off == MN_lss
+	      || current_templates.start->mnem_off == MN_lfs
+	      || current_templates.start->mnem_off == MN_lgs)
 	    suffix = LONG_MNEM_SUFFIX;
 	  else if (!got_a_float)
 	    {
@@ -747,7 +747,7 @@ i386_intel_operand (char *operand_string
 
 	case O_qword_ptr: /* O_mmword_ptr */
 	  i.types[this_operand].bitfield.qword = 1;
-	  if (current_templates->start->mnem_off == MN_bound
+	  if (current_templates.start->mnem_off == MN_bound
 	      || got_a_float == 1)	/* "f..." */
 	    suffix = LONG_MNEM_SUFFIX;
 	  else
@@ -759,10 +759,10 @@ i386_intel_operand (char *operand_string
 	  if (got_a_float)
 	    break;
 	  if (flag_code == CODE_64BIT
-	      && (current_templates->start->operand_types[0].bitfield.fword
-		  || current_templates->start->operand_types[0].bitfield.tbyte
-		  || current_templates->start->opcode_modifier.jump == JUMP_DWORD
-		  || current_templates->start->opcode_modifier.jump == JUMP))
+	      && (current_templates.start->operand_types[0].bitfield.fword
+		  || current_templates.start->operand_types[0].bitfield.tbyte
+		  || current_templates.start->opcode_modifier.jump == JUMP_DWORD
+		  || current_templates.start->opcode_modifier.jump == JUMP))
 	    suffix = QWORD_MNEM_SUFFIX; /* l[fgs]s, [ls][gi]dt, call, jmp */
 	  else
 	    i.types[this_operand].bitfield.byte = 1; /* cause an error */
@@ -794,8 +794,8 @@ i386_intel_operand (char *operand_string
 	  i.far_branch = true;
 	  /* FALLTHROUGH */
 	case O_near_ptr:
-	  if (current_templates->start->opcode_modifier.jump != JUMP
-	      && current_templates->start->opcode_modifier.jump != JUMP_DWORD)
+	  if (current_templates.start->opcode_modifier.jump != JUMP
+	      && current_templates.start->opcode_modifier.jump != JUMP_DWORD)
 	    {
 	      /* cause an error */
 	      i.types[this_operand].bitfield.byte = 1;
@@ -814,11 +814,11 @@ i386_intel_operand (char *operand_string
 	 REX.W) is going to be derived from it.  For this we check whether the
 	 given suffix is valid for any of the candidate templates.  */
       if (suffix && suffix != i.suffix
-	  && current_templates->start->mnem_off != MN_bound)
+	  && current_templates.start->mnem_off != MN_bound)
 	{
 	  const insn_template *t;
 
-	  for (t = current_templates->start; t < current_templates->end; ++t)
+	  for (t = current_templates.start; t < current_templates.end; ++t)
 	    {
 	      /* Operands haven't been swapped yet.  */
 	      unsigned int op = t->operands - 1 - this_operand;
@@ -879,7 +879,7 @@ i386_intel_operand (char *operand_string
 	      break;
 	    }
 
-	  if (t == current_templates->end)
+	  if (t == current_templates.end)
 	    suffix = 0;
 	}
 
@@ -893,9 +893,9 @@ i386_intel_operand (char *operand_string
     }
 
   /* Operands for jump/call need special consideration.  */
-  if (current_templates->start->opcode_modifier.jump == JUMP
-      || current_templates->start->opcode_modifier.jump == JUMP_DWORD
-      || current_templates->start->opcode_modifier.jump == JUMP_INTERSEGMENT)
+  if (current_templates.start->opcode_modifier.jump == JUMP
+      || current_templates.start->opcode_modifier.jump == JUMP_DWORD
+      || current_templates.start->opcode_modifier.jump == JUMP_INTERSEGMENT)
     {
       bool jumpabsolute = false;
 
@@ -1005,7 +1005,7 @@ i386_intel_operand (char *operand_string
 	    if (i.rounding.type == RC_NamesTable[j].type)
 	      break;
 	  as_bad (_("`%s': misplaced `{%s}'"),
-		  insn_name (current_templates->start), RC_NamesTable[j].name);
+		  insn_name (current_templates.start), RC_NamesTable[j].name);
 	  return 0;
 	}
     }
@@ -1031,9 +1031,9 @@ i386_intel_operand (char *operand_string
 	     ljmp	0x9090,0x90909090
 	   */
 
-	  if ((current_templates->start->opcode_modifier.jump == JUMP_INTERSEGMENT
-	       || current_templates->start->opcode_modifier.jump == JUMP_DWORD
-	       || current_templates->start->opcode_modifier.jump == JUMP)
+	  if ((current_templates.start->opcode_modifier.jump == JUMP_INTERSEGMENT
+	       || current_templates.start->opcode_modifier.jump == JUMP_DWORD
+	       || current_templates.start->opcode_modifier.jump == JUMP)
 	      && this_operand == 1
 	      && intel_state.seg == NULL
 	      && i.mem_operands == 1
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -1883,23 +1883,26 @@ process_i386_opcodes (FILE *table)
 
   /* Generate opcode sets array.  */
   fprintf (table, "\n/* i386 opcode sets table.  */\n\n");
-  fprintf (table, "static const insn_template *const i386_op_sets[] =\n{\n");
-  fprintf (table, "  i386_optab,\n");
+  fprintf (table, "typedef unsigned short i386_op_off_t;\n");
+  fprintf (table, "static const i386_op_off_t i386_op_sets[] =\n{\n ");
 
   for (nr = j = 0; j < i; j++)
     {
       struct opcode_entry *next = &opcode_array[j]->entry;
 
+      if ((j + 1) % 8 != 0)
+	fprintf (table, "%5u,", nr);
+      else
+	fprintf (table, "%5u,\n ", nr);
       do
 	{
 	  ++nr;
 	  next = next->next;
 	}
       while (next);
-      fprintf (table, "  i386_optab + %u,\n", nr);
     }
 
-  fprintf (table, "};\n");
+  fprintf (table, "%5u\n};\n", nr);
 
   /* Emit mnemonics and associated #define-s.  */
   qsort (opcode_array, i, sizeof (*opcode_array), mnemonic_cmp);
