text: // Warning! autogenerated file, do what you want.
  #include "arm/ARMtoStringCustom.h"
  
  #include <string>
  #include <cstdlib>
  #include <cstdio>
  #include <cstring>
  
  #include "arm/ARMDisassembler.h"
  #include "arm/ARMUtilities.h"
  #include "arm/gen/ARMDecodingTable.h"
  #include "arm/gen/ARMtoString.h"
  #include "Utilities.h"
  
  using namespace Disassembler;
  
  std::string c_dt_QDd_i_imm3_imm4(const char *opname, const Disassembler::ARMInstruction *ins) {
      std::string dt = dt_str(ins);
      uint64_t imm = ins->imm64;
  
      if (dt == "I8")
          imm &= 0xff;
  
      else if (dt == "I16")
          imm &= 0xffff;
  
      else if (dt == "I32")
          imm &= 0xffffffff;
  
      else if (dt == "F32")
          imm &= 0xffffffff;
  
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, #",
          opname,
          dt.c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str()
      );
  
      if (dt == "F32") {
          char tmp[128];
          snprintf(tmp, sizeof(tmp), "%.6e", *(float *) &imm);
          strcat(buffer, tmp);
      } else {
          strcat(buffer, integer_to_string(imm, true).c_str());
      }
  
      return std::string(buffer);
  }
  
  std::string c_rt_rn_rm(const char *opname, const Disassembler::ARMInstruction *ins) {
  	// OPNAME{<c>} <Rt>, [<Rn>, +/-<Rm>]              Offset: index==TRUE, wback==FALSE
  	// OPNAME{<c>} <Rt>, [<Rn>, +/-<Rm>]!             Pre-indexed: index==TRUE, wback==TRUE
  	// OPNAME{<c>} <Rt>, [<Rn>], +/-<Rm>              Post-indexed: index==FALSE, wback==TRUE
  	char op_name[64];
  	if (ins->index == false && ins->wback == true) {
  	    snprintf(op_name, sizeof(op_name),
  	            "%s%s %s, [%s], %s%s",
  				opname,
  	            c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str()
  	    );
  	} else {
  	    snprintf(op_name, sizeof(op_name),
  	            "%s%s %s, [%s, %s%s]%s",
  				opname,
  	            c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str(),
  				ins->wback ? "!" : ""
  	    );
  	}
  
      return std::string(op_name);
  }
  
  std::string c_rt_rn_rm_shift(const char *opname, const Disassembler::ARMInstruction *ins, bool adds=false) {
      // OPNAME{<c>}{<q>} <Rt>, [<Rn>, <Rm>{, <shift>}]  Offset: index==TRUE, wback==FALSE
      // OPNAME{<c>}{<q>} <Rt>, [<Rn>, <Rm>{, <shift>}]! Pre-indexed: index==TRUE, wback==TRUE
      // OPNAME{<c>}{<q>} <Rt>, [<Rn>], <Rm>{, <shift>}  Post-indexed: index==FALSE, wback==TRUE
      char op_name[64] = {0}, op_args[64] = {0};
      if (ins->index == false && ins->wback == true) {
          snprintf(op_name, sizeof(op_name),
                  "%s%s %s, [%s], %s",
                  opname,
                  c_str(ins).c_str(),
                  regular_reg_str(ins->t).c_str(),
                  regular_reg_str(ins->n).c_str(),
                  regular_reg_str(ins->m).c_str()
          );
  
          if (ins->shift_n) {
              snprintf(op_args, sizeof(op_args), ", %s",
                      shift_str(ins->shift_t, ins->shift_n).c_str()
              );
          } else {
              strcpy(op_args, "");
          }
      } else {
          snprintf(op_name, sizeof(op_name),
                  "%s%s %s, [%s, %s",
                  opname,
                  c_str(ins).c_str(),
                  regular_reg_str(ins->t).c_str(),
                  regular_reg_str(ins->n).c_str(),
                  regular_reg_str(ins->m).c_str()
          );
  
          if (ins->shift_n) {
              snprintf(op_args, sizeof(op_args), ", %s",
                      shift_str(ins->shift_t, ins->shift_n).c_str()
              );
          }
  
          strcat(op_args, ins->wback ? "]!" : "]");
      }
  
      return std::string(op_name) + std::string(op_args);
  }
  
  std::string c_rt_rt2_rn_rm(const char *opname, const Disassembler::ARMInstruction *ins) {
  	// OPNAME{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, +/-<Rm>]  Offset: index==TRUE, wback==FALSE
  	// OPNAME{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, +/-<Rm>]! Pre-indexed: index==TRUE, wback==TRUE
  	// OPNAME{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], +/-<Rm>  Post-indexed: index==FALSE, wback==TRUE
      char op_name[64], op_args[64];
  
      snprintf(op_name, sizeof(op_name),
              "%s%s %s, %s, [%s",
              opname,
              c_str(ins).c_str(),
  			regular_reg_str(ins->t).c_str(),
  			regular_reg_str(ins->t2).c_str(),
  			regular_reg_str(ins->n).c_str()
      );
  
      if (ins->index == true && ins->wback == false) {
          snprintf(op_args, sizeof(op_args), ", %s%s]",
                  !ins->add ? "-" : "",
                  regular_reg_str(ins->m).c_str()
          );
      } else if (ins->index == true && ins->wback == true) {
          snprintf(op_args, sizeof(op_args), ", %s%s]%s",
                  !ins->add ? "-" : "",
                  regular_reg_str(ins->m).c_str(),
                  ins->wback ? "!" : ""
          );
  
      } else if (ins->index == false && ins->wback == true) {
          snprintf(op_args, sizeof(op_args), "], %s%s",
                  !ins->add ? "-" : "",
                  regular_reg_str(ins->m).c_str()
          );
      }
  
  
      return std::string(op_name) + std::string(op_args);
  }
  
  std::string c_rt_rn_sign_rm_shift(const char *opname, const Disassembler::ARMInstruction *ins) {
  	// OPNAME{<c>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]  Offset: index==TRUE, wback==FALSE
  	// OPNAME{<c>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! Pre-indexed: index==TRUE, wback==TRUE
  	// OPNAME{<c>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>}  Post-indexed: index==FALSE, wback==TRUE
  	char op_name[64], op_args[64];
  	if (ins->index == false && ins->wback == true) {
  	    snprintf(op_name, sizeof(op_name),
  	            "%s%s %s, [%s], %s%s",
  				opname,
  	            c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str()
  	    );
  
  	    if (ins->shift_n) {
  			snprintf(op_args, sizeof(op_args), ", %s",
  					shift_str(ins->shift_t, ins->shift_n).c_str()
  			);
  	    } else {
  	    	strcpy(op_args, "");
  	    }
  	} else {
  	    snprintf(op_name, sizeof(op_name),
  	            "%s%s %s, [%s, %s%s",
  				opname,
  	            c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str()
  	    );
  
  	    if (ins->shift_n) {
  			snprintf(op_args, sizeof(op_args), ", %s]",
  					shift_str(ins->shift_t, ins->shift_n).c_str()
  			);
  	    } else {
  	    	strcpy(op_args, "]");
  	    }
  
          strcat(op_args, ins->wback ? "!" :  "");
  	}
  
      return std::string(op_name) + std::string(op_args);
  }
  
  std::string c_rt_rn_imm(const char *opname, const Disassembler::ARMInstruction *ins) {
  	// OPNAME{<c>} <Rt>, [<Rn> {, #+/-<imm>}] Offset: index==TRUE, wback==FALSE
  	// OPNAME{<c>} <Rt>, [<Rn>, #+/-<imm>]!   Pre-indexed: index==TRUE, wback==TRUE
  	// OPNAME{<c>} <Rt>, [<Rn>], #+/-<imm>    Post-indexed: index==FALSE, wback==TRUE
  	char op_name[64], op_args[64];
  
  	snprintf(op_name, sizeof(op_name),
  	        "%s%s %s, [%s",
  			opname,
  	        c_str(ins).c_str(),
  			regular_reg_str(ins->t).c_str(),
  			regular_reg_str(ins->n).c_str()
  	);
  
  	if (ins->index == true && ins->wback == false) {
  		if (ins->imm32) {
  			snprintf(op_args, sizeof(op_args), ", #%s%s]",
  					!ins->add ? "-" : "",
  					integer_to_string(ins->imm32).c_str()
  			);
  		} else {
              strncpy(op_args, "]", sizeof(op_args) - 1);
  		}
  	} else if (ins->index == true && ins->wback == true) {
  		snprintf(op_args, sizeof(op_args), ", #%s%s]%s",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str(),
  				ins->wback ? "!" : ""
  		);
  
  	} else if (ins->index == false && ins->wback == true) {
  		snprintf(op_args, sizeof(op_args), "], #%s%s",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str()
  		);
  	}
  
  	return std::string(op_name) + std::string(op_args);
  
  }
  
  std::string c_rt_rt2_rn_imm(const char *opname, const Disassembler::ARMInstruction *ins) {
  	// OPNAME{<c>} <Rt>, <Rt2>, [<Rn> {, #+/-<imm>}] Offset: index==TRUE, wback==FALSE
  	// OPNAME{<c>} <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!   Pre-indexed: index==TRUE, wback==TRUE
  	// OPNAME{<c>} <Rt>, <Rt2>, [<Rn>], #+/-<imm>    Post-indexed: index==FALSE, wback==TRUE
      char op_name[64], op_args[64];
  
      snprintf(op_name, sizeof(op_name),
              "%s%s %s, %s, [%s",
  			opname,
              c_str(ins).c_str(),
  			regular_reg_str(ins->t).c_str(),
  			regular_reg_str(ins->t2).c_str(),
  			regular_reg_str(ins->n).c_str()
      );
  
      if (ins->index == true && ins->wback == false) {
      	if (ins->imm32) {
      		snprintf(op_args, sizeof(op_args), ", #%s%s]",
      				!ins->add ? "-" : "",
      				integer_to_string(ins->imm32).c_str()
      		);
      	}
          else {
              strncpy(op_args, "]", sizeof(op_args) - 1);
      	}
      } else if (ins->index == true && ins->wback == true) {
  		snprintf(op_args, sizeof(op_args), ", #%s%s]%s",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str(),
  				ins->wback ? "!" : ""
  		);
  
      } else if (ins->index == false && ins->wback == true) {
  		snprintf(op_args, sizeof(op_args), "], #%s%s",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str()
  		);
      }
  
      return std::string(op_name) + std::string(op_args);
  
  }
  
  std::string c_coproc_crd_rn_imm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // OPNAME{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>{, #+/-<imm>}] Offset.       P = 1, W = 0.
      // OPNAME{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>, #+/-<imm>]!  Pre-indexed.  P = 1, W = 1.
      // OPNAME{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], #+/-<imm>   Post-indexed. P = 0, W = 1.
      // OPNAME{2}{L}{<c>}{<q>} <coproc>, <CRd>, [<Rn>], <option>    Unindexed.    P = 0, W = 0, U = 1.
  	bool is_2 = (ins->encoding == eEncodingT2 || ins->encoding == eEncodingA2);
      char op_name[64], op_args[64];
      snprintf(op_name, sizeof(op_name),
              "%s%s%s%s%s %s, %s, [%s",
  			opname,
  			is_2 ? "2" : "",
  			ins->D ? "L" : "",
              ins->encoding == eEncodingA2 ? "" : c_str(ins).c_str(),
  			"",
  			coproc_str(ins->coproc).c_str(),
  			coproc_reg_str(ins->CRd).c_str(),
  			regular_reg_str(ins->n).c_str()
      );
  
  
  	if (ins->P == 1 && ins->W == 0) {
  		if (ins->imm32) {
  			snprintf(op_args, sizeof(op_args), ", #%s%s]",
  					!ins->add ? "-" : "",
  					integer_to_string(ins->imm32).c_str()
  			);
  		} else {
              strncpy(op_args, "]", sizeof(op_args) - 1);
  		}
  	} else if (ins->P == 1 && ins->W == 1) {
  		snprintf(op_args, sizeof(op_args), ", #%s%s]!",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str()
  		);
  	} else if (ins->P == 0 && ins->W == 1) {
  		snprintf(op_args, sizeof(op_args), "], #%s%s",
  				!ins->add ? "-" : "",
  				integer_to_string(ins->imm32).c_str()
  		);
  	} else if (ins->P == 0 && ins->W == 0 && ins->U == 1) {
  		snprintf(op_args, sizeof(op_args), "], %s",
  				option_str(ins).c_str()
  		);
  	}
  
      return std::string(op_name) + std::string(op_args);
  }
  
  // Instruction: IT
  // Encoding: T1
  std::string decode_it_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	// IT{<x>{<y>{<z>}}} <firstcond> Not permitted in IT block
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "IT");
  
      std::string conds;
  
      // (3 - the number of trailing zeros) is the number of then / else.
      unsigned trailing_zeros = __builtin_ctz(ins->mask);
      unsigned CondBit0 = ins->firstcond & 1;
      for (unsigned position = trailing_zeros + 1; position < 3 + 1; ++position) {
          conds = (((ins->mask >> position) & 1) == CondBit0 ? "T" : "E") + conds;
      }
  
      // I'm a lazy bastard.
      ARMInstruction copy = *ins;
      copy.cond = ins->firstcond;
  
      strcat(buffer, conds.c_str());
      strcat(buffer, " ");
      strcat(buffer, ARMCondCodeToString((cond_t) ins->firstcond));
      return std::string(buffer);
  }
  
  // Instruction: LDC, LDC2 (immediate)
  // Encoding: T1
  std::string decode_ldc_ldc2_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("LDC", ins);
  }
  
  // Instruction: LDC, LDC2 (immediate)
  // Encoding: A1
  std::string decode_ldc_ldc2_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("LDC", ins);
  }
  
  // Instruction: LDC, LDC2 (immediate)
  // Encoding: T2
  std::string decode_ldc_ldc2_immediate_t2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("LDC", ins);
  }
  
  // Instruction: LDC, LDC2 (immediate)
  // Encoding: A2
  std::string decode_ldc_ldc2_immediate_a2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("LDC", ins);
  }
  
  // Instruction: LDC, LDC2 (literal)
  // Encoding: T1
  std::string decode_ldc_ldc2_literal_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	// LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, <label>         Normal form with P = 1, W = 0
  	// LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [PC, #+/-<imm>] Alternative form with P = 1, W = 0
  	// LDC{2}{L}{<c>}{<q>} <coproc>, <CRd>, [PC], <option>  Unindexed form with P = 0, U = 1, W = 0,
  	bool is_2 = (ins->encoding == eEncodingT2 || ins->encoding == eEncodingA2);
  	char buffer1[64];
  	char buffer2[64];
      snprintf(buffer1, sizeof(buffer1),
      		"LDC%s%s%s %s, %s, ",
      		is_2 ? "2" : "",
      		ins->D ? "L" : "",
      		ins->encoding == eEncodingA2 ? "" : c_str(ins).c_str(),
  			coproc_str(ins->coproc).c_str(),
  			coproc_reg_str(ins->CRd).c_str()
      );
  
  
  	if (ins->P == 1 && ins->W == 0) {
          if (ins->imm32 || ins->add == 0) {
              snprintf(buffer2, sizeof(buffer2), "[pc, #%s%s]",
                  ins->add ? "" : "-",
                  integer_to_string(ins->imm32).c_str());
          } else {
              strcpy(buffer2, "[pc]");
          }
  	} else if (ins->P == 0 && ins->U == 1 && ins->W == 0) {
  		snprintf(buffer2, sizeof(buffer2), "[PC], %s", option_str(ins).c_str());
  	}
  
  
      return std::string(buffer1) + std::string(buffer2);
  }
  
  // Instruction: LDC, LDC2 (literal)
  // Encoding: A1
  std::string decode_ldc_ldc2_literal_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_ldc_ldc2_literal_t1_to_string(ins);
  }
  
  // Instruction: LDC, LDC2 (literal)
  // Encoding: T2
  std::string decode_ldc_ldc2_literal_t2_to_string(const Disassembler::ARMInstruction *ins) {
  	return decode_ldc_ldc2_literal_t1_to_string(ins);
  }
  
  // Instruction: LDC, LDC2 (literal)
  // Encoding: A2
  std::string decode_ldc_ldc2_literal_a2_to_string(const Disassembler::ARMInstruction *ins) {
  	return decode_ldc_ldc2_literal_t1_to_string(ins);
  }
  
  // Instruction: LDM/LDMIA/LDMFD (Thumb)
  // Encoding: T1
  std::string decode_ldm_ldmia_ldmfd_thumb_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	// LDM<c> <Rn>!, <registers> <Rn> not included in <registers>
  	// LDM<c> <Rn> , <registers> <Rn> included in <registers>
      char buffer[64];
      snprintf(buffer, sizeof(buffer),
      		"LDM%s %s%s, %s",
  			c_str(ins).c_str(),
  			regular_reg_str(ins->n).c_str(),
  			get_bit(ins->registers, ins->n) ? "" : "!",
  			registers_str(ins->registers).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: LDR (immediate, Thumb)
  // Encoding: T4
  std::string decode_ldr_immediate_thumb_t4_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDR", ins);
  }
  
  // Instruction: LDR (immediate, ARM)
  // Encoding: A1
  std::string decode_ldr_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDR", ins);
  }
  
  // Instruction: LDR (register, ARM)
  // Encoding: A1
  std::string decode_ldr_register_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_sign_rm_shift("LDR", ins);
  }
  
  // Instruction: LDRB (immediate, Thumb)
  // Encoding: T3
  std::string decode_ldrb_immediate_thumb_t3_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRB", ins);
  }
  
  // Instruction: LDRB (immediate, ARM)
  // Encoding: A1
  std::string decode_ldrb_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRB", ins);
  }
  
  // Instruction: LDRB (register)
  // Encoding: A1
  std::string decode_ldrb_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_sign_rm_shift("LDRB", ins);
  }
  
  // Instruction: LDRD (immediate)
  // Encoding: T1
  std::string decode_ldrd_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_imm("LDRD", ins);
  }
  
  // Instruction: LDRD (immediate)
  // Encoding: A1
  std::string decode_ldrd_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_imm("LDRD", ins);
  }
  
  // Instruction: LDRD (register)
  // Encoding: A1
  std::string decode_ldrd_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_rm("LDRD", ins);
  }
  
  // Instruction: LDRH (immediate, Thumb)
  // Encoding: T3
  std::string decode_ldrh_immediate_thumb_t3_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRH", ins);
  }
  
  // Instruction: LDRH (immediate, ARM)
  // Encoding: A1
  std::string decode_ldrh_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRH", ins);
  }
  
  // Instruction: LDRH (register)
  // Encoding: A1
  std::string decode_ldrh_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_rm("LDRH", ins);
  }
  
  // Instruction: LDRSB (immediate)
  // Encoding: T2
  std::string decode_ldrsb_immediate_t2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRSB", ins);
  }
  
  // Instruction: LDRSB (immediate)
  // Encoding: A1
  std::string decode_ldrsb_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_rt_rn_imm("LDRSB", ins);
  }
  
  // Instruction: LDRSB (register)
  // Encoding: A1
  std::string decode_ldrsb_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_rm("LDRSB", ins);
  }
  
  // Instruction: LDRSH (immediate)
  // Encoding: T2
  std::string decode_ldrsh_immediate_t2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("LDRSH", ins);
  }
  
  // Instruction: LDRSH (immediate)
  // Encoding: A1
  std::string decode_ldrsh_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_rt_rn_imm("LDRSH", ins);
  }
  
  // Instruction: LDRSH (register)
  // Encoding: A1
  std::string decode_ldrsh_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_rm("LDRSH", ins);
  }
  
  // Instruction: PKH
  // Encoding: T1
  std::string decode_pkh_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_pkh_a1_to_string(ins);
  }
  
  // Instruction: PKH
  // Encoding: A1
  std::string decode_pkh_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	// PKHBT{<c>}{<q>} {<Rd>,} <Rn>, <Rm> {, LSL #<imm>} tbform == false
  	// PKHTB{<c>}{<q>} {<Rd>,} <Rn>, <Rm> {, ASR #<imm>} tbform == true
      char buffer[64];
      snprintf(buffer, sizeof(buffer),
      		"PKH%s%s %s, %s, %s",
  			ins->tbform ? "TB" : "BT",
  			c_str(ins).c_str(),
  			regular_reg_str(ins->d).c_str(),
  			regular_reg_str(ins->n).c_str(),
  			regular_reg_str(ins->m).c_str()
  	);
  
      if (ins->shift_n) {
      	strncat(buffer, ", ", sizeof(buffer) - 1);
      	strncat(buffer, shift_str(ins->shift_t, ins->shift_n).c_str(), sizeof(buffer) - 1);
      }
  
  
      return std::string(buffer);
  }
  
  // Instruction: STC, STC2
  // Encoding: T1
  std::string decode_stc_stc2_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("STC", ins);
  }
  
  // Instruction: STC, STC2
  // Encoding: A1
  std::string decode_stc_stc2_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("STC", ins);
  }
  
  // Instruction: STC, STC2
  // Encoding: T2
  std::string decode_stc_stc2_t2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("STC", ins);
  }
  
  // Instruction: STC, STC2
  // Encoding: A2
  std::string decode_stc_stc2_a2_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_coproc_crd_rn_imm("STC", ins);
  }
  
  // Instruction: STR (immediate, Thumb)
  // Encoding: T4
  std::string decode_str_immediate_thumb_t4_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STR", ins);
  }
  
  // Instruction: STR (immediate, ARM)
  // Encoding: A1
  std::string decode_str_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STR", ins);
  }
  
  // Instruction: STR (register)
  // Encoding: A1
  std::string decode_str_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_sign_rm_shift("STR", ins);
  }
  
  // Instruction: STRB (immediate, Thumb)
  // Encoding: T3
  std::string decode_strb_immediate_thumb_t3_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STRB", ins);
  }
  
  // Instruction: STRB (immediate, ARM)
  // Encoding: A1
  std::string decode_strb_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STRB", ins);
  }
  
  // Instruction: STRB (register)
  // Encoding: A1
  std::string decode_strb_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_sign_rm_shift("STRB", ins);
  }
  
  // Instruction: STRD (immediate)
  // Encoding: T1
  std::string decode_strd_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_imm("STRD", ins);
  }
  
  // Instruction: STRD (immediate)
  // Encoding: A1
  std::string decode_strd_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_imm("STRD", ins);
  }
  
  // Instruction: STRD (register)
  // Encoding: A1
  std::string decode_strd_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rt2_rn_rm("STRD", ins);
  }
  
  // Instruction: STRH (immediate, Thumb)
  // Encoding: T3
  std::string decode_strh_immediate_thumb_t3_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STRH", ins);
  }
  
  // Instruction: STRH (immediate, ARM)
  // Encoding: A1
  std::string decode_strh_immediate_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	return c_rt_rn_imm("STRH", ins);
  }
  
  // Instruction: STRH (register)
  // Encoding: A1
  std::string decode_strh_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
  	// STRH<c> <Rt>, [<Rn>,+/-<Rm>]{!}
  	// STRH<c> <Rt>, [<Rn>],+/-<Rm>
  	char buffer[64];
  	if (ins->index == true) {
  		snprintf(buffer, sizeof(buffer), "STRH%s %s, [%s, %s%s]%s",
  				c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str(),
                  ins->wback ? "!" : ""
  		);
  	} else {
  		snprintf(buffer, sizeof(buffer), "STRH%s %s, [%s], %s%s",
  				c_str(ins).c_str(),
  				regular_reg_str(ins->t).c_str(),
  				regular_reg_str(ins->n).c_str(),
  				!ins->add ? "-" : "",
  				regular_reg_str(ins->m).c_str()
  		);
  	}
  
  
      return std::string(buffer);
  }
  
  // Instruction: VABA, VABAL
  // Encoding: T1
  std::string decode_vaba_vabal_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vaba_vabal_a1_to_string(ins);
  }
  
  
  // Instruction: VABA, VABAL
  // Encoding: A1
  std::string decode_vaba_vabal_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VABA<c>.<dt> <Qd>, <Qn>, <Qm> Q==1
      // VABA<c>.<dt> <Dd>, <Dn>, <Dm> Q==0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABA.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VABA, VABAL
  // Encoding: T2
  std::string decode_vaba_vabal_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vaba_vabal_a2_to_string(ins);
  }
  
  
  // Instruction: VABA, VABAL
  // Encoding: A2
  std::string decode_vaba_vabal_a2_to_string(const Disassembler::ARMInstruction *ins) {
      // VABAL<c>.<dt> <Qd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABAL.%s %s, %s, %s",
          dt_str(ins).c_str(),
          quad_reg_str(ins->d >> 1).c_str(),
          double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VABD, VABDL (integer)
  // Encoding: T1
  std::string decode_vabd_vabdl_integer_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VABD<c>.<dt> <Qd>, <Qn>, <Qm> Q==1
      // VABD<c>.<dt> <Dd>, <Dn>, <Dm> Q==0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABD.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VABD, VABDL (integer)
  // Encoding: A1
  std::string decode_vabd_vabdl_integer_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vabd_vabdl_integer_t1_to_string(ins);
  }
  
  // Instruction: VABD (floating-point)
  // Encoding: T1
  std::string decode_vabd_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VABD<c>.F32 <Qd>, <Qn>, <Qm> Q==1
      // VABD<c>.F32 <Dd>, <Dn>, <Dm> Q==0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABD.F32 %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VABD (floating-point)
  // Encoding: A1
  std::string decode_vabd_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vabd_floating_point_t1_to_string(ins);
  }
  
  
  // Instruction: VABS
  // Encoding: T1
  std::string decode_vabs_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VABS<c>.<dt> <Qd>, <Qm>
      // VABS<c>.<dt> <Dd>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABS.%s %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VABS
  // Encoding: A1
  std::string decode_vabs_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vabs_t1_to_string(ins);
  }
  
  // Instruction: VABS
  // Encoding: T2
  std::string decode_vabs_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VABS<c>.F64 <Dd>, <Dm>
      // VABS<c>.F32 <Sd>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VABS%s.%s %s, %s",
          c_str(ins).c_str(),
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VABS
  // Encoding: A2
  std::string decode_vabs_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vabs_t2_to_string(ins);
  }
  
  // Instruction: VACGE, VACGT, VACLE, VACLT
  // Encoding: T1
  std::string decode_vacge_vacgt_vacle_vaclt_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // V<op><c>.F32 <Qd>, <Qn>, <Qm>
      // V<op><c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "V%s.F32 %s, %s, %s",
          ins->op ? "ACGT" : "ACGE",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VACGE, VACGT, VACLE, VACLT
  // Encoding: A1
  std::string decode_vacge_vacgt_vacle_vaclt_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vacge_vacgt_vacle_vaclt_t1_to_string(ins);
  }
  
  // Instruction: VADD
  // Encoding: T1
  std::string decode_vadd_integer_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VADD<c>.<dt> <Qd>, <Qn>, <Qm>
      // VADD<c>.<dt> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VADD.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VADD
  // Encoding: A1
  std::string decode_vadd_integer_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vadd_integer_t1_to_string(ins);
  }
  
  // Instruction: VADD (floating-point)
  // Encoding: T1
  std::string decode_vadd_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VADD<c>.F32 <Qd>, <Qn>, <Qm>
      // VADD<c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VADD.F32 %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VADD (floating-point)
  // Encoding: A1
  std::string decode_vadd_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vadd_floating_point_t1_to_string(ins);
  }
  
  // Instruction: VADD (floating-point)
  // Encoding: T2
  std::string decode_vadd_floating_point_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VADD<c>.F64 <Dd>, <Dn>, <Dm>
      // VADD<c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VADD%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VADD (floating-point)
  // Encoding: A2
  std::string decode_vadd_floating_point_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vadd_floating_point_t2_to_string(ins);
  }
  
  // Instruction: VADDL, VADDW
  // Encoding: T1
  std::string decode_vaddl_vaddw_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VADDL<c>.<dt> <Qd>, <Dn>, <Dm>
      // VADDW<c>.<dt> <Qd>, <Qn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VADD%s.%s %s, %s, %s",
          (ins->op) ? "W" : "L",
          dt_str(ins).c_str(),
          quad_reg_str(ins->d >> 1).c_str(),
          (ins->op) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VADDL, VADDW
  // Encoding: A1
  std::string decode_vaddl_vaddw_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vaddl_vaddw_t1_to_string(ins);
  }
  
  // Instruction: VAND (register)
  // Encoding: T1
  std::string decode_vand_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VAND<c> <Qd>, <Qn>, <Qm>
      // VAND<c> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VAND %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VAND (register)
  // Encoding: A1
  std::string decode_vand_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vand_register_t1_to_string(ins);
  }
  
  // Instruction: VBIC (immediate)
  // Encoding: T1
  std::string decode_vbic_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VBIC<c>.<dt> <Qd>, #<imm>
      // VBIC<c>.<dt> <Dd>, #<imm>
      return c_dt_QDd_i_imm3_imm4("VBIC", ins);
  }
  
  // Instruction: VBIC (immediate)
  // Encoding: A1
  std::string decode_vbic_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VBIC", ins);
  }
  
  // Instruction: VBIC (register)
  // Encoding: T1
  std::string decode_vbic_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VBIC<c> <Qd>, <Qn>, <Qm>
      // VBIC<c> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VBIC %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VBIC (register)
  // Encoding: A1
  std::string decode_vbic_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vbic_register_t1_to_string(ins);
  }
  
  // Instruction: VBIF, VBIT, VBSL
  // Encoding: T1
  std::string decode_vbif_vbit_vbsl_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // V<op><c> <Qd>, <Qn>, <Qm>
      // V<op><c> <Dd>, <Dn>, <Dm>
      const char *op = "INVALID";
      if (ins->op == 3) op = "BIF";
      else if (ins->op == 2) op = "BIT";
      else if (ins->op == 1) op = "BSL";
  
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "V%s %s, %s, %s",
          op,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VBIF, VBIT, VBSL
  // Encoding: A1
  std::string decode_vbif_vbit_vbsl_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vbif_vbit_vbsl_t1_to_string(ins);
  }
  
  // Instruction: VCEQ (register)
  // Encoding: T1
  std::string decode_vceq_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCEQ<c>.<dt> <Qd>, <Qn>, <Qm>   <dt> an integer type
      // VCEQ<c>.<dt> <Dd>, <Dn>, <Dm>   <dt> an integer type
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCEQ.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCEQ (register)
  // Encoding: A1
  std::string decode_vceq_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vceq_register_t1_to_string(ins);
  }
  
  // Instruction: VCEQ (register)
  // Encoding: T2
  std::string decode_vceq_register_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VCEQ<c>.F32 <Qd>, <Qn>, <Qm>
      // VCEQ<c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCEQ.F32 %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCEQ (register)
  // Encoding: A2
  std::string decode_vceq_register_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vceq_register_t2_to_string(ins);
  }
  
  std::string c_dt_QDd_QDm_0(const char *opname, const Disassembler::ARMInstruction *ins) {
      // <op><c>.<dt> <Qd>, <Qm>, #0
      // <op><c>.<dt> <Dd>, <Dm>, #0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, #0",
          opname,
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCEQ (immediate #0)
  // Encoding: T1
  std::string decode_vceq_immediate_0_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCEQ<c>.<dt> <Qd>, <Qm>, #0
      // VCEQ<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCEQ", ins);
  }
  
  // Instruction: VCEQ (immediate #0)
  // Encoding: A1
  std::string decode_vceq_immediate_0_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCEQ<c>.<dt> <Qd>, <Qm>, #0
      // VCEQ<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCEQ", ins);
  }
  
  // Instruction: VCGE (register)
  // Encoding: T1
  std::string decode_vcge_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGE<c>.<dt> <Qd>, <Qn>, <Qm> <dt> an integer type
      // VCGE<c>.<dt> <Dd>, <Dn>, <Dm> <dt> an integer type
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCGE.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  
  }
  
  // Instruction: VCGE (register)
  // Encoding: A1
  std::string decode_vcge_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcge_register_t1_to_string(ins);
  }
  
  // Instruction: VCGE (register)
  // Encoding: T2
  std::string decode_vcge_register_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGE<c>.F32 <Qd>, <Qn>, <Qm>
      // VCGE<c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCGE.F32 %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCGE (register)
  // Encoding: A2
  std::string decode_vcge_register_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcge_register_t2_to_string(ins);
  }
  
  // Instruction: VCGE (immediate #0)
  // Encoding: T1
  std::string decode_vcge_immediate_0_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGE<c>.<dt> <Qd>, <Qm>, #0
      // VCGE<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCGE", ins);
  }
  
  // Instruction: VCGE (immediate #0)
  // Encoding: A1
  std::string decode_vcge_immediate_0_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGE<c>.<dt> <Qd>, <Qm>, #0
      // VCGE<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCGE", ins);
  }
  
  // Instruction: VCGT (register)
  // Encoding: T1
  std::string decode_vcgt_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGT<c>.<dt> <Qd>, <Qn>, <Qm> <dt> an integer type
      // VCGT<c>.<dt> <Dd>, <Dn>, <Dm> <dt> an integer type
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCGT.%s %s, %s, %s",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCGT (register)
  // Encoding: A1
  std::string decode_vcgt_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcgt_register_t1_to_string(ins);
  }
  
  // Instruction: VCGT (register)
  // Encoding: T2
  std::string decode_vcgt_register_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGT<c>.F32 <Qd>, <Qn>, <Qm>
      // VCGT<c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCGT.F32 %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCGT (register)
  // Encoding: A2
  std::string decode_vcgt_register_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcgt_register_t2_to_string(ins);
  }
  
  // Instruction: VCGT (immediate #0)
  // Encoding: T1
  std::string decode_vcgt_immediate_0_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGT<c>.<dt> <Qd>, <Qm>, #0
      // VCGT<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCGT", ins);
  }
  
  // Instruction: VCGT (immediate #0)
  // Encoding: A1
  std::string decode_vcgt_immediate_0_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCGT<c>.<dt> <Qd>, <Qm>, #0
      // VCGT<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCGT", ins);
  }
  
  // Instruction: VCLE (immediate #0)
  // Encoding: T1
  std::string decode_vcle_immediate_0_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLE<c>.<dt> <Qd>, <Qm>, #0
      // VCLE<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCLE", ins);
  }
  
  // Instruction: VCLE (immediate #0)
  // Encoding: A1
  std::string decode_vcle_immediate_0_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLE<c>.<dt> <Qd>, <Qm>, #0
      // VCLE<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCLE", ins);
  }
  
  std::string c_dt_QDd_QDm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // <opname><c>.<dt> <Qd>, <Qm>
      // <opname><c>.<dt> <Dd>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s",
          opname,
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCLS
  // Encoding: T1
  std::string decode_vcls_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLS<c>.<dt> <Qd>, <Qm>
      // VCLS<c>.<dt> <Dd>, <Dm>
      return c_dt_QDd_QDm("VCLS", ins);
  }
  
  // Instruction: VCLS
  // Encoding: A1
  std::string decode_vcls_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLS<c>.<dt> <Qd>, <Qm>
      // VCLS<c>.<dt> <Dd>, <Dm>
      return c_dt_QDd_QDm("VCLS", ins);
  }
  
  // Instruction: VCLT (immediate #0)
  // Encoding: T1
  std::string decode_vclt_immediate_0_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLT<c>.<dt> <Qd>, <Qm>, #0
      // VCLT<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCLT", ins);
  }
  
  // Instruction: VCLT (immediate #0)
  // Encoding: A1
  std::string decode_vclt_immediate_0_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLT<c>.<dt> <Qd>, <Qm>, #0
      // VCLT<c>.<dt> <Dd>, <Dm>, #0
      return c_dt_QDd_QDm_0("VCLT", ins);
  }
  
  // Instruction: VCLZ
  // Encoding: T1
  std::string decode_vclz_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLZ<c>.<dt> <Qd>, <Qm>
      // VCLZ<c>.<dt> <Dd>, <Dm>
      return c_dt_QDd_QDm("VCLZ", ins);
  }
  
  // Instruction: VCLZ
  // Encoding: A1
  std::string decode_vclz_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCLZ<c>.<dt> <Qd>, <Qm>
      // VCLZ<c>.<dt> <Dd>, <Dm>
      return c_dt_QDd_QDm("VCLZ", ins);
  }
  
  // Instruction: VCMP, VCMPE
  // Encoding: T1
  std::string decode_vcmp_vcmpe_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCMP{E}<c>.F64 <Dd>, <Dm>
      // VCMP{E}<c>.F32 <Sd>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCMP%s%s.%s %s, %s",
          (ins->E) ? "E" : "",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCMP, VCMPE
  // Encoding: A1
  std::string decode_vcmp_vcmpe_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCMP{E}<c>.F64 <Dd>, <Dm> Encoding T1/A1, sz = 1
      // VCMP{E}<c>.F32 <Sd>, <Sm> Encoding T1/A1, sz = 0
      return decode_vcmp_vcmpe_t1_to_string(ins);
  }
  
  // Instruction: VCMP, VCMPE
  // Encoding: T2
  std::string decode_vcmp_vcmpe_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VCMP{E}<c>.F64 <Dd>, #0.0
      // VCMP{E}<c>.F32 <Sd>, #0.0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCMP%s%s.%s %s, #0",
          (ins->E) ? "E" : "",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCMP, VCMPE
  // Encoding: A2
  std::string decode_vcmp_vcmpe_a2_to_string(const Disassembler::ARMInstruction *ins) {
      // VCMP{E}<c>.F64 <Dd>, #0.0
      // VCMP{E}<c>.F32 <Sd>, #0.0
      return decode_vcmp_vcmpe_t2_to_string(ins);
  }
  
  // Instruction: VCNT
  // Encoding: T1
  std::string decode_vcnt_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCNT<c>.8 <Qd>, <Qm>
      // VCNT<c>.8 <Dd>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCNT.8 %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCNT
  // Encoding: A1
  std::string decode_vcnt_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCNT<c>.8 <Qd>, <Qm>
      // VCNT<c>.8 <Dd>, <Dm>
      return decode_vcnt_t1_to_string(ins);
  }
  
  // Instruction: VCVT (between floating-point and integer, AdvancedSIMD)
  // Encoding: T1
  std::string decode_vcvt_between_floating_point_and_integer_advancedsimd_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.<Td>.<Tm> <Qd>, <Qm>
      // VCVT<c>.<Td>.<Tm> <Dd>, <Dm>
      // .S32.F32 encoded as op = 0b10, size = 0b10.
      // .U32.F32 encoded as op = 0b11, size = 0b10.
      // .F32.S32 encoded as op = 0b00, size = 0b10.
      // .F32.U32 encoded as op = 0b01, size = 0b10.
      char buffer[128];
      const char *dt = "INVALID";
      if (ins->op == 2 && ins->size == 2) dt = "S32.F32";
      else if (ins->op == 3 && ins->size == 2) dt = "U32.F32";
      else if (ins->op == 0 && ins->size == 2) dt = "F32.S32";
      else if (ins->op == 1 && ins->size == 2) dt = "F32.U32";
  
      snprintf(buffer, sizeof(buffer), "VCVT.%s %s, %s",
          dt,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between floating-point and integer, AdvancedSIMD)
  // Encoding: A1
  std::string decode_vcvt_between_floating_point_and_integer_advancedsimd_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.<Td>.<Tm> <Qd>, <Qm>
      // VCVT<c>.<Td>.<Tm> <Dd>, <Dm>
      return decode_vcvt_between_floating_point_and_integer_advancedsimd_t1_to_string(ins);
  }
  
  // Instruction: VCVT, VCVTR (between floating-point and integer, Floating-point)
  // Encoding: T1
  std::string decode_vcvt_vcvtr_between_floating_point_and_integer_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT{R}{<c>}.S32.F64 <Sd>, <Dm> opc2='101',sz=1
      // VCVT{R}{<c>}.S32.F32 <Sd>, <Sm> opc2='101',sz=0
      // VCVT{R}{<c>}.U32.F64 <Sd>, <Dm> opc2='100',sz=1
      // VCVT{R}{<c>}.U32.F32 <Sd>, <Sm> opc2='100',sz=0
      // VCVT{<c>}.F64.<Tm>   <Dd>, <Sm> opc2='000',sz=1
      // VCVT{<c>}.F32.<Tm>   <Sd>, <Sm> opc2='000',sz=0
      // R = op
      char buffer[128];
      const char *dt = "INVALID";
      if      (ins->opc2 == 5 && get_bit(ins->opcode, 8) == 1) dt = "S32.F64";
      else if (ins->opc2 == 5 && get_bit(ins->opcode, 8) == 0) dt = "S32.F32";
      else if (ins->opc2 == 4 && get_bit(ins->opcode, 8) == 1) dt = "U32.F64";
      else if (ins->opc2 == 4 && get_bit(ins->opcode, 8) == 0) dt = "U32.F32";
      else if (ins->opc2 == 0 && get_bit(ins->opcode, 8) == 1) dt = (ins->op == 1) ? "F64.S32" : "F64.U32";
      else if (ins->opc2 == 0 && get_bit(ins->opcode, 8) == 0) dt = (ins->op == 1) ? "F32.S32" : "F32.U32";
  
      snprintf(buffer, sizeof(buffer), "VCVT%s%s.%s %s, %s",
          (!ins->op && ins->to_integer) ? "R" : "",
          c_str(ins).c_str(),
          dt,
          (ins->opc2 == 0 && get_bit(ins->opcode, 8) == 1) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          ((ins->opc2 == 5 || ins->opc2 == 4) && (get_bit(ins->opcode, 8) == 1)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT, VCVTR (between floating-point and integer, Floating-point)
  // Encoding: A1
  std::string decode_vcvt_vcvtr_between_floating_point_and_integer_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcvt_vcvtr_between_floating_point_and_integer_floating_point_t1_to_string(ins);
  }
  
  // Instruction: VCVT (between floating-point and fixed-point, AdvancedSIMD)
  // Encoding: T1
  std::string decode_vcvt_between_floating_point_and_fixed_point_advancedsimd_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.<Td>.<Tm> <Qd>, <Qm>, #<fbits>
      // VCVT<c>.<Td>.<Tm> <Dd>, <Dm>, #<fbits>
      char buffer[128];
      const char *dt = "INVALID";
      if      (ins->op == 1 && ins->U == 0) dt = "S32.F32";
      else if (ins->op == 1 && ins->U == 1) dt = "U32.F32";
      else if (ins->op == 0 && ins->U == 0) dt = "F32.S32";
      else if (ins->op == 0 && ins->U == 1) dt = "F32.U32";
  
      snprintf(buffer, sizeof(buffer), "VCVT.%s %s, %s, #%s",
          dt,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(64 - ins->imm32).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between floating-point and fixed-point, AdvancedSIMD)
  // Encoding: A1
  std::string decode_vcvt_between_floating_point_and_fixed_point_advancedsimd_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.<Td>.<Tm> <Qd>, <Qm>, #<fbits>
      // VCVT<c>.<Td>.<Tm> <Dd>, <Dm>, #<fbits>
      return decode_vcvt_between_floating_point_and_fixed_point_advancedsimd_t1_to_string(ins);
  }
  
  // Instruction: VCVT (between floating-point and fixed-point, Floating-point)
  // Encoding: T1
  std::string decode_vcvt_between_floating_point_and_fixed_point_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.<Td>.F64 <Dd>, <Dd>, #<fbits> op = 1, sf = 1
      // VCVT<c>.<Td>.F32 <Sd>, <Sd>, #<fbits> op = 1, sf = 0
  
      // VCVT<c>.F64.<Td> <Dd>, <Dd>, #<fbits> op = 0, sf = 1
      // VCVT<c>.F32.<Td> <Sd>, <Sd>, #<fbits> op = 0, sf = 0
      char buffer[64];
      // Td:
      // S16 encoded as U = 0, sx = 0
      // S32 encoded as U = 0, sx = 1
      // U16 encoded as U = 1, sx = 0
      // U32 encoded as U = 1, sx = 1.
      const char *Td;
      if (ins->U == 0) {
          Td = get_bit(ins->opcode, 7) ? "S32" : "S16";
      } else {
          Td = get_bit(ins->opcode, 7) ? "U32" : "U16";
      }
  
      if (ins->op == 1) {
          snprintf(buffer, sizeof(buffer), "VCVT%s.%s.%s %s, %s, #%s",
              c_str(ins).c_str(),
              Td,
              get_bit(ins->opcode, 8) ? "F64" : "F32",
              get_bit(ins->opcode, 8) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
              get_bit(ins->opcode, 8) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
              integer_to_string(ins->frac_bits).c_str()
          );
      } else {
          snprintf(buffer, sizeof(buffer), "VCVT%s.%s.%s %s, %s, #%s",
              c_str(ins).c_str(),
              get_bit(ins->opcode, 8) ? "F64" : "F32",
              Td,
              get_bit(ins->opcode, 8) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
              get_bit(ins->opcode, 8) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
              integer_to_string(ins->frac_bits).c_str()
          );
      }
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between floating-point and fixed-point, Floating-point)
  // Encoding: A1
  std::string decode_vcvt_between_floating_point_and_fixed_point_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vcvt_between_floating_point_and_fixed_point_floating_point_t1_to_string(ins);
  }
  
  // Instruction: VCVT (between double-precision and single-precision)
  // Encoding: T1
  std::string decode_vcvt_between_double_precision_and_single_precision_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.F64.F32 <Dd>, <Sm>
      // VCVT<c>.F32.F64 <Sd>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCVT.%s %s, %s",
          (!ins->double_to_single) ? "F64.F32" : "F32.F64",
          (!ins->double_to_single) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (!ins->double_to_single) ? simple_reg_str(ins->m).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between double-precision and single-precision)
  // Encoding: A1
  std::string decode_vcvt_between_double_precision_and_single_precision_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.F64.F32 <Dd>, <Sm>
      // VCVT<c>.F32.F64 <Sd>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCVT%s.%s %s, %s",
          c_str(ins).c_str(),
          (ins->double_to_single) ? "F32.F64" : "F64.F32",
          (ins->double_to_single) ? simple_reg_str(ins->d).c_str() : double_reg_str(ins->d).c_str(),
          (ins->double_to_single) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between half-precision and single-precision, AdvancedSIMD)
  // Encoding: T1
  std::string decode_vcvt_between_half_precision_and_single_precision_advancedsimd_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.F32.F16 <Qd>, <Dm>
      // VCVT<c>.F16.F32 <Dd>, <Qm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCVT.%s %s, %s",
          (ins->op) ? "F32.F16" : "F16.F32",
          (ins->op) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->op) ? double_reg_str(ins->m).c_str() : quad_reg_str(ins->m >> 1).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCVT (between half-precision and single-precision, AdvancedSIMD)
  // Encoding: A1
  std::string decode_vcvt_between_half_precision_and_single_precision_advancedsimd_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<c>.F32.F16 <Qd>, <Dm>
      // VCVT<c>.F16.F32 <Dd>, <Qm>
      return decode_vcvt_between_half_precision_and_single_precision_advancedsimd_t1_to_string(ins);
  }
  
  // Instruction: VCVTB, VCVTT
  // Encoding: T1
  std::string decode_vcvtb_vcvtt_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<y><c>.F32.F16 <Sd>, <Sm> Encoded as op = 0
      // VCVT<y><c>.F16.F32 <Sd>, <Sm> Encoded as op = 1
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCVT%s.%s %s, %s",
          (ins->T) ? "T" : "B",
          (ins->op) ? "F16.F32" : "F32.F16",
          simple_reg_str(ins->d).c_str(),
          simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VCVTB, VCVTT
  // Encoding: A1
  std::string decode_vcvtb_vcvtt_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VCVT<y><c>.F32.F16 <Sd>, <Sm> Encoded as op = 0
      // VCVT<y><c>.F16.F32 <Sd>, <Sm> Encoded as op = 1
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VCVT%s%s.%s %s, %s",
          (ins->T) ? "T" : "B",
          c_str(ins).c_str(),
          (ins->op) ? "F16.F32" : "F32.F16",
          simple_reg_str(ins->d).c_str(),
          simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VDIV
  // Encoding: T1
  std::string decode_vdiv_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDIV<c>.F64 <Dd>, <Dn>, <Dm>
      // VDIV<c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VDIV.%s %s, %s, %s",
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VDIV
  // Encoding: A1
  std::string decode_vdiv_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDIV<c>.F64 <Dd>, <Dn>, <Dm>
      // VDIV<c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VDIV%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VDUP (scalar)
  // Encoding: T1
  std::string decode_vdup_scalar_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDUP<c>.<size> <Qd>, <Dm[x]>
      // VDUP<c>.<size> <Dd>, <Dm[x]>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VDUP.%d %s, %s[%d]",
          ins->esize,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? double_reg_str(ins->m).c_str() : double_reg_str(ins->m).c_str(),
          ins->index
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VDUP (scalar)
  // Encoding: A1
  std::string decode_vdup_scalar_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDUP<c>.<size> <Qd>, <Dm[x]>
      // VDUP<c>.<size> <Dd>, <Dm[x]>
      return decode_vdup_scalar_t1_to_string(ins);
  }
  
  // Instruction: VDUP (ARM core register)
  // Encoding: T1
  std::string decode_vdup_arm_core_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDUP<c>.<size> <Qd>, <Rt>
      // VDUP<c>.<size> <Dd>, <Rt>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VDUP.%d %s, %s",
          ins->esize,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          regular_reg_str(ins->t).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VDUP (ARM core register)
  // Encoding: A1
  std::string decode_vdup_arm_core_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VDUP<c>.<size> <Qd>, <Rt>
      // VDUP<c>.<size> <Dd>, <Rt>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VDUP%s.%d %s, %s",
          c_str(ins).c_str(),
          ins->esize,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          regular_reg_str(ins->t).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VEOR
  // Encoding: T1
  std::string decode_veor_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VEOR<c> <Qd>, <Qn>, <Qm>
      // VEOR<c> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VEOR %s, %s, %s",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VEOR
  // Encoding: A1
  std::string decode_veor_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VEOR<c> <Qd>, <Qn>, <Qm>
      // VEOR<c> <Dd>, <Dn>, <Dm>
      return decode_veor_t1_to_string(ins);
  }
  
  // Instruction: VEXT
  // Encoding: T1
  std::string decode_vext_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
      // VEXT<c>.8 <Dd>, <Dn>, <Dm>, #<imm>
      char buffer[128];
      unsigned size;
      unsigned imm;
      if (!ins->imm32) {
          size = ins->Q ? 64 : 32;
          imm = ins->imm32;
      } else if (ins->imm32 % 8 == 0) {
          size = 64;
          imm = ins->imm32 / 8;
      } else if (ins->imm32 % 4 == 0) {
          size = 32;
          imm = ins->imm32 / 4;
      } else if (ins->imm32 % 2 == 0) {
          size = 16;
          imm = ins->imm32 / 2;
      } else {
          size = 8;
          imm = ins->imm32;
      }
  
      snprintf(buffer, sizeof(buffer), "VEXT.%u %s, %s, %s, #%s",
          size,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(imm).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VEXT
  // Encoding: A1
  std::string decode_vext_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
      // VEXT<c>.8 <Dd>, <Dn>, <Dm>, #<imm>
      return decode_vext_t1_to_string(ins);
  }
  
  // Instruction: VFMA, VFMS
  // Encoding: T1
  std::string decode_vfma_vfms_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VFM<y><c>.F32 <Qd>, <Qn>, <Qm>
      // VFM<y><c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VFM%s.F32 %s, %s, %s",
          (ins->op) ? "S" : "A",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VFMA, VFMS
  // Encoding: A1
  std::string decode_vfma_vfms_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VFM<y><c>.F32 <Qd>, <Qn>, <Qm>
      // VFM<y><c>.F32 <Dd>, <Dn>, <Dm>
      return decode_vfma_vfms_t1_to_string(ins);
  }
  
  // Instruction: VFMA, VFMS
  // Encoding: T2
  std::string decode_vfma_vfms_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VFM<y><c>.F64 <Dd>, <Dn>, <Dm>
      // VFM<y><c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VFM%s.%s %s, %s, %s",
          (ins->op) ? "S" : "A",
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VFMA, VFMS
  // Encoding: A2
  std::string decode_vfma_vfms_a2_to_string(const Disassembler::ARMInstruction *ins) {
      // VFM<y><c>.F64 <Dd>, <Dn>, <Dm>
      // VFM<y><c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VFM%s%s.%s %s, %s, %s",
          (ins->op) ? "S" : "A",
          c_str(ins).c_str(),
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VFNMA, VFNMS
  // Encoding: T1
  std::string decode_vfnma_vfnms_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VFNM<y><c>.F64 <Dd>, <Dn>, <Dm>
      // VFNM<y><c>.F32 <Sd>, <Sn>, <Sm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VFNM%s.%s %s, %s, %s",
          (ins->op) ? "A" : "S",
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VFNMA, VFNMS
  // Encoding: A1
  std::string decode_vfnma_vfnms_a1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VFNM%s%s.%s %s, %s, %s",
          (ins->op) ? "A" : "S",
          c_str(ins).c_str(),
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VHADD, VHSUB
  // Encoding: T1
  std::string decode_vhadd_vhsub_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VH<op><c>.<dt> <Qd>, <Qn>, <Qm>
      // VH<op><c>.<dt> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VH%s.%s %s, %s, %s",
          (ins->op) ? "SUB" : "ADD",
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VHADD, VHSUB
  // Encoding: A1
  std::string decode_vhadd_vhsub_a1_to_string(const Disassembler::ARMInstruction *ins) {
      // VH<op><c> <Qd>, <Qn>, <Qm>
      // VH<op><c> <Dd>, <Dn>, <Dm>
      return decode_vhadd_vhsub_t1_to_string(ins);
  }
  
  std::string c_size_list_Rn_align(const char *opname, const Disassembler::ARMInstruction *ins) {
      // <opcode><c>.<size> <list>, [<Rn>{@<align>}]{!}
      // <opcode><c>.<size> <list>, [<Rn>{@<align>}], <Rm>  When Rm != 15 && Rm != 13
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, [%s%s]",
          opname,
          size_str(ins).c_str(),
          list_str(ins).c_str(),
          regular_reg_str(ins->n).c_str(),
          align_str(ins).c_str()
      );
  
  
      if (ins->m != 15 && ins->m != 13) {
          strcat(buffer, (", " + regular_reg_str(ins->m)).c_str());
      } else if (ins->wback) {
          strcat(buffer, "!");
      }
  
      return std::string(buffer);
  }
  
  std::string c_size_list_Rn(const char *opname, const Disassembler::ARMInstruction *ins) {
      // VLD3{<c>}{<q>}.<size> <list>, [<Rn>]            Rm = '1111'
      // VLD3{<c>}{<q>}.<size> <list>, [<Rn>]!           Rm = '1101'
      // VLD3{<c>}{<q>}.<size> <list>, [<Rn>], <Rm>      Rm = other values
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, [%s]",
          opname,
          size_str(ins).c_str(),
          list_str(ins).c_str(),
          regular_reg_str(ins->n).c_str()
      );
  
      if (ins->m == 0x0f) {
          return std::string(buffer);
      } else  if (ins->m == 0x0d) {
          strcat(buffer, "!");
          return std::string(buffer);
      }
  
      strcat(buffer, (", " + regular_reg_str(ins->m)).c_str());
      return std::string(buffer);
  }
  
  std::string c_dt_QDd_QDn_QDm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // <opname><c>.<dt> <Qd>, <Qn>, <Qm>
      // <opname><c>.<dt> <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, %s",
          opname,
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  std::string c_QDd_QDn_QDm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // <opname><c>.F32 <Qd>, <Qn>, <Qm>
      // <opname><c>.F32 <Dd>, <Dn>, <Dm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, %s",
          opname,
          "F32",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  std::string c_dt_Qd_Dn_Dmx(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, %s[%d]",
          opname,
          dt_str(ins).c_str(),
          quad_reg_str(ins->d >> 1).c_str(),
          double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str(),
          ins->index
      );
  
  
      return std::string(buffer);
  }
  
  std::string c_dt_QDd_imm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // VBIC<c>.<dt> <Qd>, #<imm>
      // VBIC<c>.<dt> <Dd>, #<imm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s%s.%s %s, #%s",
          opname,
          c_str(ins).c_str(),
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          integer_to_string(ins->imm64, true).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  
  std::string c_dt_QDd_QDn_Dmx(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, %s[%d]",
          opname,
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str(),
          ins->index
      );
  
  
      return std::string(buffer);
  }
  
  std::string c_QDd_QDm(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s %s, %s",
          opname,
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  std::string c_QDd_QDn_QDm_REPLACE(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, %s",
          opname,
          dt_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_type_size_QDd_QDm_QDn(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s%s %s, %s, %s",
          opname,
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_type_size_QDd_QDm_shift_amount(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s%s %s, %s, #%s",
          opname,
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_type_size_QDd_QDm_imm(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s%s.%s%s %s, %s, #%s",
          opname,
          c_str(ins).c_str(),
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->imm64).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_size_QDd_QDm_shift_amount(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s, #%s",
          opname,
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_f64f32_DSd_DSm(const char *opname, const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s%s.%s %s, %s",
          opname,
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  std::string c_size_QDd_QDm(const char *opname, const Disassembler::ARMInstruction *ins) {
      // VTRN
      // VUZP
      // VZIP
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s %s, %s",
          opname,
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VLD1 (multiple single elements)
  // Encoding: T1
  std::string decode_vld1_multiple_single_elements_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD1 (multiple single elements)
  // Encoding: A1
  std::string decode_vld1_multiple_single_elements_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD1 (single element to one lane)
  // Encoding: T1
  std::string decode_vld1_single_element_to_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD1 (single element to one lane)
  // Encoding: A1
  std::string decode_vld1_single_element_to_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD1 (single element to all lanes)
  // Encoding: T1
  std::string decode_vld1_single_element_to_all_lanes_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD1 (single element to all lanes)
  // Encoding: A1
  std::string decode_vld1_single_element_to_all_lanes_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD1", ins);
  }
  
  // Instruction: VLD2 (multiple 2-element structures)
  // Encoding: T1
  std::string decode_vld2_multiple_2_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD2 (multiple 2-element structures)
  // Encoding: A1
  std::string decode_vld2_multiple_2_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD2 (single 2-element structure to one lane)
  // Encoding: T1
  std::string decode_vld2_single_2_element_structure_to_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD2 (single 2-element structure to one lane)
  // Encoding: A1
  std::string decode_vld2_single_2_element_structure_to_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD2 (single 2-element structure to all lanes)
  // Encoding: T1
  std::string decode_vld2_single_2_element_structure_to_all_lanes_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD2 (single 2-element structure to all lanes)
  // Encoding: A1
  std::string decode_vld2_single_2_element_structure_to_all_lanes_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD2", ins);
  }
  
  // Instruction: VLD3 (multiple 3-element structures)
  // Encoding: T1
  std::string decode_vld3_multiple_3_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD3", ins);
  }
  
  // Instruction: VLD3 (multiple 3-element structures)
  // Encoding: A1
  std::string decode_vld3_multiple_3_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD3", ins);
  }
  
  // Instruction: VLD3 (single 3-element structure to one lane)
  // Encoding: T1
  std::string decode_vld3_single_3_element_structure_to_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VLD3", ins);
  }
  
  // Instruction: VLD3 (single 3-element structure to one lane)
  // Encoding: A1
  std::string decode_vld3_single_3_element_structure_to_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VLD3", ins);
  }
  
  // Instruction: VLD3 (single 3-element structure to all lanes)
  // Encoding: T1
  std::string decode_vld3_single_3_element_structure_to_all_lanes_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VLD3", ins);
  }
  
  // Instruction: VLD3 (single 3-element structure to all lanes)
  // Encoding: A1
  std::string decode_vld3_single_3_element_structure_to_all_lanes_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VLD3", ins);
  }
  
  // Instruction: VLD4 (multiple 4-element structures)
  // Encoding: T1
  std::string decode_vld4_multiple_4_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VLD4 (multiple 4-element structures)
  // Encoding: A1
  std::string decode_vld4_multiple_4_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VLD4 (single 4-element structure to one lane)
  // Encoding: T1
  std::string decode_vld4_single_4_element_structure_to_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VLD4 (single 4-element structure to one lane)
  // Encoding: A1
  std::string decode_vld4_single_4_element_structure_to_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VLD4 (single 4-element structure to all lanes)
  // Encoding: T1
  std::string decode_vld4_single_4_element_structure_to_all_lanes_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VLD4 (single 4-element structure to all lanes)
  // Encoding: A1
  std::string decode_vld4_single_4_element_structure_to_all_lanes_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VLD4", ins);
  }
  
  // Instruction: VMAX, VMIN (integer)
  // Encoding: T1
  std::string decode_vmax_vmin_integer_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm(ins->op ? "VMIN" : "VMAX", ins);
  }
  
  // Instruction: VMAX, VMIN (integer)
  // Encoding: A1
  std::string decode_vmax_vmin_integer_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm(ins->op ? "VMIN" : "VMAX", ins);
  }
  
  // Instruction: VMAX, VMIN (floating-point)
  // Encoding: T1
  std::string decode_vmax_vmin_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm(ins->op ? "VMIN" : "VMAX", ins);
  }
  
  // Instruction: VMAX, VMIN (floating-point)
  // Encoding: A1
  std::string decode_vmax_vmin_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm(ins->op ? "VMIN" : "VMAX", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (integer)
  // Encoding: T1
  std::string decode_vmla_vmlal_vmls_vmlsl_integer_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (integer)
  // Encoding: A1
  std::string decode_vmla_vmlal_vmls_vmlsl_integer_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (integer)
  // Encoding: T2
  std::string decode_vmla_vmlal_vmls_vmlsl_integer_t2_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "V%s%s.%s %s, %s, %s",
          ins->op ? "MLS" : "MLA",
          (ins->Q) ? "W" : "L",
          dt_str(ins).c_str(),
          quad_reg_str(ins->d >> 1).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str()
      );
  
  
      return std::string(buffer);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (integer)
  // Encoding: A2
  std::string decode_vmla_vmlal_vmls_vmlsl_integer_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmla_vmlal_vmls_vmlsl_integer_t2_to_string(ins);
  }
  
  // Instruction: VMLA, VMLS (floating-point)
  // Encoding: T1
  std::string decode_vmla_vmls_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLS (floating-point)
  // Encoding: A1
  std::string decode_vmla_vmls_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLS (floating-point)
  // Encoding: T2
  std::string decode_vmla_vmls_floating_point_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // V<op><c>.F64 <Dd>, <Dn>, <Dm> sz == 1
      // V<op><c>.F32 <Sd>, <Sn>, <Sm> sz == 0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "V%s%s.%s %s, %s, %s",
          ins->op ? "MLS" : "MLA",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMLA, VMLS (floating-point)
  // Encoding: A2
  std::string decode_vmla_vmls_floating_point_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmla_vmls_floating_point_t2_to_string(ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (by scalar)
  // Encoding: T1
  std::string decode_vmla_vmlal_vmls_vmlsl_by_scalar_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (by scalar)
  // Encoding: A1
  std::string decode_vmla_vmlal_vmls_vmlsl_by_scalar_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx(ins->op ? "VMLS" : "VMLA", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (by scalar)
  // Encoding: T2
  std::string decode_vmla_vmlal_vmls_vmlsl_by_scalar_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_Qd_Dn_Dmx(ins->op ? "VMLSL" : "VMLAL", ins);
  }
  
  // Instruction: VMLA, VMLAL, VMLS, VMLSL (by scalar)
  // Encoding: A2
  std::string decode_vmla_vmlal_vmls_vmlsl_by_scalar_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_Qd_Dn_Dmx(ins->op ? "VMLSL" : "VMLAL", ins);
  }
  
  // Instruction: VMOV (immediate)
  // Encoding: T1
  std::string decode_vmov_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VMOV", ins);
  }
  
  // Instruction: VMOV (immediate)
  // Encoding: A1
  std::string decode_vmov_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VMOV", ins);
  }
  
  // Instruction: VMOV (immediate)
  // Encoding: T2
  std::string decode_vmov_immediate_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VMOV<c>.F64 <Dd>, #<imm>
      // VMOV<c>.F32 <Sd>, #<imm>
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VMOV%s.%s %s, #%.6e",
          c_str(ins).c_str(),
          get_bit(ins->opcode, 8) ? "F64" : "F32",
          get_bit(ins->opcode, 8) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          get_bit(ins->opcode, 8) ? *(double *) (&ins->imm64) : *(float *) (&ins->imm32)
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMOV (immediate)
  // Encoding: A2
  std::string decode_vmov_immediate_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmov_immediate_t2_to_string(ins);
  }
  
  // Instruction: VMOV (register)
  // Encoding: T1
  std::string decode_vmov_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VMOV", ins);
  }
  
  // Instruction: VMOV (register)
  // Encoding: A1
  std::string decode_vmov_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VMOV", ins);
  }
  
  // Instruction: VMOV (register)
  // Encoding: T2
  std::string decode_vmov_register_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VMOV", ins);
  }
  
  // Instruction: VMOV (register)
  // Encoding: A2
  std::string decode_vmov_register_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VMOV", ins);
  }
  
  // Instruction: VMOV (between ARM core register and single-precision register)
  // Encoding: T1
  std::string decode_vmov_between_arm_core_register_and_single_precision_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VMOV{<c>}{<q>} <Sn>, <Rt>  Encoded as op = 0
      // VMOV{<c>}{<q>} <Rt>, <Sn>  Encoded as op = 1
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VMOV%s %s, %s",
          c_str(ins).c_str(),
          (ins->op) ? regular_reg_str(ins->t).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->op) ? simple_reg_str(ins->n).c_str() : regular_reg_str(ins->t).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMOV (between ARM core register and single-precision register)
  // Encoding: A1
  std::string decode_vmov_between_arm_core_register_and_single_precision_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmov_between_arm_core_register_and_single_precision_register_t1_to_string(ins);
  }
  
  // Instruction: VMOV (between two ARM core registers and two single-precision registers)
  // Encoding: T1
  std::string decode_vmov_between_two_arm_core_registers_and_two_single_precision_registers_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VMOV<c> <Sm>, <Sm1>, <Rt>, <Rt2> op == 0
      // VMOV<c> <Rt>, <Rt2>, <Sm>, <Sm1> op == 1
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VMOV%s %s, %s, %s, %s",
          c_str(ins).c_str(),
          (ins->op) ? regular_reg_str(ins->t).c_str() : simple_reg_str(ins->m).c_str(),
          (ins->op) ? regular_reg_str(ins->t2).c_str() : simple_reg_str(ins->m + 1).c_str(),
          (ins->op) ? simple_reg_str(ins->m).c_str() : regular_reg_str(ins->t).c_str(),
          (ins->op) ? simple_reg_str(ins->m + 1).c_str() : regular_reg_str(ins->t2).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMOV (between two ARM core registers and two single-precision registers)
  // Encoding: A1
  std::string decode_vmov_between_two_arm_core_registers_and_two_single_precision_registers_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmov_between_two_arm_core_registers_and_two_single_precision_registers_t1_to_string(ins);
  }
  
  // Instruction: VMOV (between two ARM core registers and a doubleword extension register)
  // Encoding: T1
  std::string decode_vmov_between_two_arm_core_registers_and_a_doubleword_extension_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VMOV<c> <Dm>, <Rt>, <Rt2> op == 0
      // VMOV<c> <Rt>, <Rt2>, <Dm> op == 1
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VMOV%s %s, %s, %s",
          c_str(ins).c_str(),
          (ins->op) ? regular_reg_str(ins->t).c_str() : double_reg_str(ins->m).c_str(),
          (ins->op) ? regular_reg_str(ins->t2).c_str() : regular_reg_str(ins->t).c_str(),
          (ins->op) ? double_reg_str(ins->m).c_str() : regular_reg_str(ins->t2).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMOV (between two ARM core registers and a doubleword extension register)
  // Encoding: A1
  std::string decode_vmov_between_two_arm_core_registers_and_a_doubleword_extension_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmov_between_two_arm_core_registers_and_a_doubleword_extension_register_t1_to_string(ins);
  }
  
  // Instruction: VMUL, VMULL (integer and polynomial)
  // Encoding: T1
  std::string decode_vmul_vmull_integer_and_polynomial_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VMUL", ins);
  }
  
  // Instruction: VMUL, VMULL (integer and polynomial)
  // Encoding: A1
  std::string decode_vmul_vmull_integer_and_polynomial_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmul_vmull_integer_and_polynomial_t1_to_string(ins);
  }
  
  // Instruction: VMUL (floating-point)
  // Encoding: T1
  std::string decode_vmul_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VMUL", ins);
  }
  
  // Instruction: VMUL (floating-point)
  // Encoding: A1
  std::string decode_vmul_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VMUL", ins);
  }
  
  // Instruction: VMUL (floating-point)
  // Encoding: T2
  std::string decode_vmul_floating_point_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VMUL<c>.F64 <Dd>, <Dn>, <Dm> sz == 1
      // VMUL<c>.F32 <Sd>, <Sn>, <Sm> sz == 0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VMUL%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VMUL (floating-point)
  // Encoding: A2
  std::string decode_vmul_floating_point_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vmul_floating_point_t2_to_string(ins);
  }
  
  // Instruction: VMUL, VMULL (by scalar)
  // Encoding: T1
  std::string decode_vmul_vmull_by_scalar_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VMUL", ins);
  }
  
  // Instruction: VMUL, VMULL (by scalar)
  // Encoding: A1
  std::string decode_vmul_vmull_by_scalar_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VMUL", ins);
  }
  
  // Instruction: VMVN (immediate)
  // Encoding: T1
  std::string decode_vmvn_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VMVN", ins);
  }
  
  // Instruction: VMVN (immediate)
  // Encoding: A1
  std::string decode_vmvn_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VMVN", ins);
  }
  
  // Instruction: VMVN (register)
  // Encoding: T1
  std::string decode_vmvn_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VMVN", ins);
  }
  
  // Instruction: VMVN (register)
  // Encoding: A1
  std::string decode_vmvn_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VMVN", ins);
  }
  
  // Instruction: VNEG
  // Encoding: T1
  std::string decode_vneg_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VNEG", ins);
  }
  
  // Instruction: VNEG
  // Encoding: A1
  std::string decode_vneg_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VNEG", ins);
  }
  
  // Instruction: VNEG
  // Encoding: T2
  std::string decode_vneg_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VNEG", ins);
  }
  
  // Instruction: VNEG
  // Encoding: A2
  std::string decode_vneg_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VNEG", ins);
  }
  
  // Instruction: VNMLA, VNMLS, VNMUL
  // Encoding: T1
  std::string decode_vnmla_vnmls_vnmul_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VN<op>{<c>}.F64 <Dd>, <Dn>, <Dm> sz == 1
      // VN<op>{<c>}.F32 <Sd>, <Sn>, <Sm> sz == 0
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VN%s%s.%s %s, %s, %s",
          (ins->op) ? "MLA" : "MLS",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VNMLA, VNMLS, VNMUL
  // Encoding: A1
  std::string decode_vnmla_vnmls_vnmul_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vnmla_vnmls_vnmul_t1_to_string(ins);
  }
  
  // Instruction: VNMLA, VNMLS, VNMUL
  // Encoding: T2
  std::string decode_vnmla_vnmls_vnmul_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VNMUL<c>.F64 <Dd>, <Dn>, <Dm> sz == 1
      // VNMUL<c>.F32 <Sd>, <Sn>, <Sm> sz == 0
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VNMUL%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          (get_bit(ins->opcode, 8)) ? "F64" : "F32",
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (get_bit(ins->opcode, 8)) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VNMLA, VNMLS, VNMUL
  // Encoding: A2
  std::string decode_vnmla_vnmls_vnmul_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vnmla_vnmls_vnmul_t2_to_string(ins);
  }
  
  // Instruction: VORN (register)
  // Encoding: T1
  std::string decode_vorn_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s %s, %s, %s",
          "VORN",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VORN (register)
  // Encoding: A1
  std::string decode_vorn_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vorn_register_t1_to_string(ins);
  }
  
  // Instruction: VORR (immediate)
  // Encoding: T1
  std::string decode_vorr_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VORR", ins);
  }
  
  // Instruction: VORR (immediate)
  // Encoding: A1
  std::string decode_vorr_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_i_imm3_imm4("VORR", ins);
  }
  
  // Instruction: VORR (register)
  // Encoding: T1
  std::string decode_vorr_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s %s, %s, %s",
          "VORR",
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VORR (register)
  // Encoding: A1
  std::string decode_vorr_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vorr_register_t1_to_string(ins);
  }
  
  // Instruction: VPADAL
  // Encoding: T1
  std::string decode_vpadal_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VPADAL", ins);
  }
  
  // Instruction: VPADAL
  // Encoding: A1
  std::string decode_vpadal_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VPADAL", ins);
  }
  
  // Instruction: VPADDL
  // Encoding: T1
  std::string decode_vpaddl_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VPADDL", ins);
  }
  
  // Instruction: VPADDL
  // Encoding: A1
  std::string decode_vpaddl_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VPADDL", ins);
  }
  
  // Instruction: VQABS
  // Encoding: T1
  std::string decode_vqabs_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VQABS", ins);
  }
  
  // Instruction: VQABS
  // Encoding: A1
  std::string decode_vqabs_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VQABS", ins);
  }
  
  // Instruction: VQADD
  // Encoding: T1
  std::string decode_vqadd_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQADD", ins);
  }
  
  // Instruction: VQADD
  // Encoding: A1
  std::string decode_vqadd_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQADD", ins);
  }
  
  // Instruction: VQDMULH
  // Encoding: T1
  std::string decode_vqdmulh_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQDMULH", ins);
  }
  
  // Instruction: VQDMULH
  // Encoding: A1
  std::string decode_vqdmulh_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQDMULH", ins);
  }
  
  // Instruction: VQDMULH
  // Encoding: T2
  std::string decode_vqdmulh_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VQDMULH", ins);
  }
  
  // Instruction: VQDMULH
  // Encoding: A2
  std::string decode_vqdmulh_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VQDMULH", ins);
  }
  
  // Instruction: VQNEG
  // Encoding: T1
  std::string decode_vqneg_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VQNEG", ins);
  }
  
  // Instruction: VQNEG
  // Encoding: A1
  std::string decode_vqneg_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VQNEG", ins);
  }
  
  // Instruction: VQRDMULH
  // Encoding: T1
  std::string decode_vqrdmulh_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQRDMULH", ins);
  }
  
  // Instruction: VQRDMULH
  // Encoding: A1
  std::string decode_vqrdmulh_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VQRDMULH", ins);
  }
  
  // Instruction: VQRDMULH
  // Encoding: T2
  std::string decode_vqrdmulh_t2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VQRDMULH", ins);
  }
  
  // Instruction: VQRDMULH
  // Encoding: A2
  std::string decode_vqrdmulh_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_Dmx("VQRDMULH", ins);
  }
  
  // Instruction: VQRSHL
  // Encoding: T1
  std::string decode_vqrshl_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VQRSHL", ins);
  }
  
  // Instruction: VQRSHL
  // Encoding: A1
  std::string decode_vqrshl_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VQRSHL", ins);
  }
  
  // Instruction: VQSHL (register)
  // Encoding: T1
  std::string decode_vqshl_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VQSHL", ins);
  }
  
  // Instruction: VQSHL (register)
  // Encoding: A1
  std::string decode_vqshl_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VQSHL", ins);
  }
  
  // Instruction: VQSHL, VQSHLU (immediate)
  // Encoding: T1
  std::string decode_vqshl_vqshlu_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s%s.%s%s %s, %s, #%s",
          "VQSHL",
          (ins->src_unsigned && ins->U) ? "" : (ins->U ? "U" : ""),
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VQSHL, VQSHLU (immediate)
  // Encoding: A1
  std::string decode_vqshl_vqshlu_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vqshl_vqshlu_immediate_t1_to_string(ins);
  }
  
  // Instruction: VQSUB
  // Encoding: T1
  std::string decode_vqsub_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VQSUB<c>.<type><size> <Qd>, <Qn>, <Qm> Q == 1
      // VQSUB<c>.<type><size> <Dd>, <Dn>, <Dm> Q == 0
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VQSUB.%s%s %s, %s, %s",
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VQSUB
  // Encoding: A1
  std::string decode_vqsub_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vqsub_t1_to_string(ins);
  }
  
  // Instruction: VRECPE
  // Encoding: T1
  std::string decode_vrecpe_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VRECPE", ins);
  }
  
  // Instruction: VRECPE
  // Encoding: A1
  std::string decode_vrecpe_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VRECPE", ins);
  }
  
  // Instruction: VRECPS
  // Encoding: T1
  std::string decode_vrecps_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VRECPS", ins);
  }
  
  // Instruction: VRECPS
  // Encoding: A1
  std::string decode_vrecps_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VRECPS", ins);
  }
  
  // Instruction: VREV16, VREV32, VREV64
  // Encoding: T1
  std::string decode_vrev16_vrev32_vrev64_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VREV<n><c>.<size> <Qd>, <Qm> Q == 1
      // VREV<n><c>.<size> <Dd>, <Dm> Q == 0
      const char *n = "16";
      if (ins->op == 1)
          n = "32";
      else if (ins->op == 0)
          n = "64";
  
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VREV%s.%s %s, %s",
          n,
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VREV16, VREV32, VREV64
  // Encoding: A1
  std::string decode_vrev16_vrev32_vrev64_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vrev16_vrev32_vrev64_t1_to_string(ins);
  }
  
  // Instruction: VRHADD
  // Encoding: T1
  std::string decode_vrhadd_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm_REPLACE("VRHADD", ins);
  }
  
  // Instruction: VRHADD
  // Encoding: A1
  std::string decode_vrhadd_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm_REPLACE("VRHADD", ins);
  }
  
  // Instruction: VRSHL
  // Encoding: T1
  std::string decode_vrshl_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VRSHL", ins);
  }
  
  // Instruction: VRSHL
  // Encoding: A1
  std::string decode_vrshl_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VRSHL", ins);
  }
  
  // Instruction: VRSHR
  // Encoding: T1
  std::string decode_vrshr_t1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "%s.%s%s %s, %s, #%s",
          "VRSHR",
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VRSHR
  // Encoding: A1
  std::string decode_vrshr_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vrshr_t1_to_string(ins);
  }
  
  // Instruction: VRSQRTE
  // Encoding: T1
  std::string decode_vrsqrte_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VRSQRTE", ins);
  }
  
  // Instruction: VRSQRTE
  // Encoding: A1
  std::string decode_vrsqrte_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDm("VRSQRTE", ins);
  }
  
  // Instruction: VRSQRTS
  // Encoding: T1
  std::string decode_vrsqrts_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VRSQRTS", ins);
  }
  
  // Instruction: VRSQRTS
  // Encoding: A1
  std::string decode_vrsqrts_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VRSQRTS", ins);
  }
  
  // Instruction: VRSRA
  // Encoding: T1
  std::string decode_vrsra_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_shift_amount("VRSRA", ins);
  }
  
  // Instruction: VRSRA
  // Encoding: A1
  std::string decode_vrsra_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_shift_amount("VRSRA", ins);
  }
  
  // Instruction: VSHL (immediate)
  // Encoding: T1
  std::string decode_vshl_immediate_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VSHL<c>.I<size> <Qd>, <Qm>, #<imm> Q == 1
      // VSHL<c>.I<size> <Dd>, <Dm>, #<imm> Q == 0
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VSHL.I%s %s, %s, #%s",
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VSHL (immediate)
  // Encoding: A1
  std::string decode_vshl_immediate_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vshl_immediate_t1_to_string(ins);
  }
  
  // Instruction: VSHL (register)
  // Encoding: T1
  std::string decode_vshl_register_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VSHL", ins);
  }
  
  // Instruction: VSHL (register)
  // Encoding: A1
  std::string decode_vshl_register_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_QDn("VSHL", ins);
  }
  
  // Instruction: VSHR
  // Encoding: T1
  std::string decode_vshr_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_shift_amount("VSHR", ins);
  }
  
  // Instruction: VSHR
  // Encoding: A1
  std::string decode_vshr_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_type_size_QDd_QDm_shift_amount("VSHR", ins);
  }
  
  // Instruction: VSLI
  // Encoding: T1
  std::string decode_vsli_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm_shift_amount("VSLI", ins);
  }
  
  // Instruction: VSLI
  // Encoding: A1
  std::string decode_vsli_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm_shift_amount("VSLI", ins);
  }
  
  // Instruction: VSQRT
  // Encoding: T1
  std::string decode_vsqrt_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VSQRT", ins);
  }
  
  // Instruction: VSQRT
  // Encoding: A1
  std::string decode_vsqrt_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_f64f32_DSd_DSm("VSQRT", ins);
  }
  
  // Instruction: VSRA
  // Encoding: T1
  std::string decode_vsra_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VSRA<c>.<type><size> <Qd>, <Qm>, #<imm>
      // VSRA<c>.<type><size> <Dd>, <Dm>, #<imm>
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VSRA.%s%s %s, %s, #%s",
          type_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str(),
          integer_to_string(ins->shift_amount).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VSRA
  // Encoding: A1
  std::string decode_vsra_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vsra_t1_to_string(ins);
  }
  
  // Instruction: VSRI
  // Encoding: T1
  std::string decode_vsri_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm_shift_amount("VSRI", ins);
  }
  
  // Instruction: VSRI
  // Encoding: A1
  std::string decode_vsri_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm_shift_amount("VSRI", ins);
  }
  
  // Instruction: VST1 (multiple single elements)
  // Encoding: T1
  std::string decode_vst1_multiple_single_elements_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST1", ins);
  }
  
  // Instruction: VST1 (multiple single elements)
  // Encoding: A1
  std::string decode_vst1_multiple_single_elements_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST1", ins);
  }
  
  // Instruction: VST1 (single element from one lane)
  // Encoding: T1
  std::string decode_vst1_single_element_from_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST1", ins);
  }
  
  // Instruction: VST1 (single element from one lane)
  // Encoding: A1
  std::string decode_vst1_single_element_from_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST1", ins);
  }
  
  // Instruction: VST2 (multiple 2-element structures)
  // Encoding: T1
  std::string decode_vst2_multiple_2_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST2", ins);
  }
  
  // Instruction: VST2 (multiple 2-element structures)
  // Encoding: A1
  std::string decode_vst2_multiple_2_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST2", ins);
  }
  
  // Instruction: VST2 (single 2-element structure from one lane)
  // Encoding: T1
  std::string decode_vst2_single_2_element_structure_from_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST2", ins);
  }
  
  // Instruction: VST2 (single 2-element structure from one lane)
  // Encoding: A1
  std::string decode_vst2_single_2_element_structure_from_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST2", ins);
  }
  
  // Instruction: VST3 (multiple 3-element structures)
  // Encoding: T1
  std::string decode_vst3_multiple_3_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST3", ins);
  }
  
  // Instruction: VST3 (multiple 3-element structures)
  // Encoding: A1
  std::string decode_vst3_multiple_3_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST3", ins);
  }
  
  // Instruction: VST3 (single 3-element structure from one lane)
  // Encoding: T1
  std::string decode_vst3_single_3_element_structure_from_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VST3", ins);
  }
  
  // Instruction: VST3 (single 3-element structure from one lane)
  // Encoding: A1
  std::string decode_vst3_single_3_element_structure_from_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn("VST3", ins);
  }
  
  // Instruction: VST4 (multiple 4-element structures)
  // Encoding: T1
  std::string decode_vst4_multiple_4_element_structures_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST4", ins);
  }
  
  // Instruction: VST4 (multiple 4-element structures)
  // Encoding: A1
  std::string decode_vst4_multiple_4_element_structures_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST4", ins);
  }
  
  // Instruction: VST4 (single 4-element structure from one lane)
  // Encoding: T1
  std::string decode_vst4_single_4_element_structure_from_one_lane_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST4", ins);
  }
  
  // Instruction: VST4 (single 4-element structure from one lane)
  // Encoding: A1
  std::string decode_vst4_single_4_element_structure_from_one_lane_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_list_Rn_align("VST4", ins);
  }
  
  // Instruction: VSUB (integer)
  // Encoding: T1
  std::string decode_vsub_integer_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VSUB", ins);
  }
  
  // Instruction: VSUB (integer)
  // Encoding: A1
  std::string decode_vsub_integer_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_dt_QDd_QDn_QDm("VSUB", ins);
  }
  
  // Instruction: VSUB (floating-point)
  // Encoding: T1
  std::string decode_vsub_floating_point_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VSUB", ins);
  }
  
  // Instruction: VSUB (floating-point)
  // Encoding: A1
  std::string decode_vsub_floating_point_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDn_QDm("VSUB", ins);
  }
  
  // Instruction: VSUB (floating-point)
  // Encoding: T2
  std::string decode_vsub_floating_point_t2_to_string(const Disassembler::ARMInstruction *ins) {
      // VSUB<c>.F64 <Dd>, <Dn>, <Dm> Q == 1
      // VSUB<c>.F32 <Sd>, <Sn>, <Sm> Q == 0
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VSUB%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          (ins->dp_operation) ? "F64" : "F32",
          (ins->dp_operation) ? double_reg_str(ins->d).c_str() : simple_reg_str(ins->d).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->n).c_str() : simple_reg_str(ins->n).c_str(),
          (ins->dp_operation) ? double_reg_str(ins->m).c_str() : simple_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VSUB (floating-point)
  // Encoding: A2
  std::string decode_vsub_floating_point_a2_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vsub_floating_point_t2_to_string(ins);
  }
  
  // Instruction: VSUBL, VSUBW
  // Encoding: T1
  std::string decode_vsubl_vsubw_t1_to_string(const Disassembler::ARMInstruction *ins) {
      char buffer[128];
      snprintf(buffer, sizeof(buffer), "VSUB%s.%s %s, %s, %s",
          (ins->op) ? "W" : "L",
          dt_str(ins).c_str(),
          quad_reg_str(ins->d >> 1).c_str(),
          (ins->op) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VSUBL, VSUBW
  // Encoding: A1
  std::string decode_vsubl_vsubw_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vsubl_vsubw_t1_to_string(ins);
  }
  
  // Instruction: VSWP
  // Encoding: T1
  std::string decode_vswp_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VSWP", ins);
  }
  
  // Instruction: VSWP
  // Encoding: A1
  std::string decode_vswp_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_QDd_QDm("VSWP", ins);
  }
  
  // Instruction: VTRN
  // Encoding: T1
  std::string decode_vtrn_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VTRN", ins);
  }
  
  // Instruction: VTRN
  // Encoding: A1
  std::string decode_vtrn_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VTRN", ins);
  }
  
  // Instruction: VTST
  // Encoding: T1
  std::string decode_vtst_t1_to_string(const Disassembler::ARMInstruction *ins) {
      // VTST<c>.<size> <Qd>, <Qn>, <Qm> Q == 1
      // VTST<c>.<size> <Dd>, <Dn>, <Dm> Q == 0
      char buffer[64];
      snprintf(buffer, sizeof(buffer), "VTST%s.%s %s, %s, %s",
          c_str(ins).c_str(),
          size_str(ins).c_str(),
          (ins->Q) ? quad_reg_str(ins->d >> 1).c_str() : double_reg_str(ins->d).c_str(),
          (ins->Q) ? quad_reg_str(ins->n >> 1).c_str() : double_reg_str(ins->n).c_str(),
          (ins->Q) ? quad_reg_str(ins->m >> 1).c_str() : double_reg_str(ins->m).c_str()
      );
  
      return std::string(buffer);
  }
  
  // Instruction: VTST
  // Encoding: A1
  std::string decode_vtst_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return decode_vtst_t1_to_string(ins);
  }
  
  // Instruction: VUZP
  // Encoding: T1
  std::string decode_vuzp_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VUZP", ins);
  }
  
  // Instruction: VUZP
  // Encoding: A1
  std::string decode_vuzp_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VUZP", ins);
  }
  
  // Instruction: VZIP
  // Encoding: T1
  std::string decode_vzip_t1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VZIP", ins);
  }
  
  // Instruction: VZIP
  // Encoding: A1
  std::string decode_vzip_a1_to_string(const Disassembler::ARMInstruction *ins) {
      return c_size_QDd_QDm("VZIP", ins);
  }
  
  // Instruction: SUBS PC, LR and related instructions, ARM
  // Encoding: A1
  std::string decode_subs_pc_lr_and_related_instructions_arm_a1_to_string(const Disassembler::ARMInstruction *ins) {
      //                           0      1      2      3      4      5      6      7       8     9     10     11     12     13     14     15
      const char *opc1_str[] = {"AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC", "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"};
      char buffer[64];
  
      switch(ins->opcode_) {
          case 8:
          case 9:
          case 10:
          case 11:
              snprintf(buffer, sizeof(buffer), "%s%s %s, #%s",
                  opc1_str[ins->opcode_],
                  c_str(ins).c_str(),
                  regular_reg_str(ins->n).c_str(),
                  integer_to_string(ins->imm32, ins->imm32 >= 10).c_str()
              );
  
              break;
  
          case 13:
          case 15:
              snprintf(buffer, sizeof(buffer), "%sS%s PC, #%s",
                  opc1_str[ins->opcode_],
                  c_str(ins).c_str(),
                  integer_to_string(ins->imm32, ins->imm32 >= 10).c_str()
              );
  
              break;
  
          default:
              snprintf(buffer, sizeof(buffer), "%sS%s PC, %s, #%s",
                  opc1_str[ins->opcode_],
                  c_str(ins).c_str(),
                  regular_reg_str(ins->n).c_str(),
                  integer_to_string(ins->imm32, ins->imm32 >= 10).c_str()
              );
  
              break;
      }
  
      return std::string(buffer);
  }
  
  // Instruction: SUBS PC, LR and related instructions, ARM
  // Encoding: A2
  std::string decode_subs_pc_lr_and_related_instructions_arm_a2_to_string(const Disassembler::ARMInstruction *ins) {
      //                           0      1      2      3      4      5      6      7       8     9     10     11     12     13     14     15
      const char *opc1_str[] = {"AND", "EOR", "SUB", "RSB", "ADD", "ADC", "SBC", "RSC", "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"};
      char buffer[64];
  
      if (ins->opcode_ == 8 || ins->opcode_ == 9 || ins->opcode_ == 10 || ins->opcode_ == 11) {
          snprintf(buffer, sizeof(buffer), "%s%s %s, %s%s%s",
              opc1_str[ins->opcode_],
              c_str(ins).c_str(),
              regular_reg_str(ins->n).c_str(),
              regular_reg_str(ins->m).c_str(),
              ins->shift_n ? ", " : "",
              ins->shift_n ? shift_str(ins->shift_t, ins->shift_n).c_str() : ""
          );
  
      } else if (ins->opcode_ <= 12 || ins->opcode_ == 14) {
          // <opc1>S<c> PC, <Rn>, <Rm>{, <shift>}
          snprintf(buffer, sizeof(buffer), "%sS%s PC, %s, %s%s%s",
              opc1_str[ins->opcode_],
              c_str(ins).c_str(),
              regular_reg_str(ins->n).c_str(),
              regular_reg_str(ins->m).c_str(),
              ins->shift_n ? ", " : "",
              ins->shift_n ? shift_str(ins->shift_t, ins->shift_n).c_str() : ""
          );
  
      } else if (ins->opcode_ == 13) {
          // TODO: This is most likely a bad hack. The spec is unclear or I'm dumb.
          // <opc2>S<c> PC, <Rm>{, <shift>}
          const char *op[] = {"MOV,", "LSR", "ASR", "ROR", "RRX"};
  
          if (ins->shift_t == 0) {
              snprintf(buffer, sizeof(buffer), "%sS%s PC, %s",
                  "MOV",
                  c_str(ins).c_str(),
                  regular_reg_str(ins->m).c_str());
          } else if (ins->shift_t == 4) {
              snprintf(buffer, sizeof(buffer), "%sS%s PC, %s",
                  "RRX",
                  c_str(ins).c_str(),
                  regular_reg_str(ins->m).c_str());
          } else {
              // printf("%s %u\n", op[ins->shift_t], ins->shift_t);
              snprintf(buffer, sizeof(buffer), "%sS%s PC, %s, #%s",
                  op[ins->shift_t],
                  c_str(ins).c_str(),
                  regular_reg_str(ins->m).c_str(),
                  integer_to_string(ins->shift_n, ins->shift_n >= 10).c_str()
                  );
          }
      } else {
          // <opc3>S<c> PC, <Rn>, #<const>
          snprintf(buffer, sizeof(buffer), "%sS%s PC, %s, %s",
              "MVN",
              c_str(ins).c_str(),
              regular_reg_str(ins->m).c_str(),
              shift_str(ins->shift_t, ins->shift_n).c_str()
              );
      }
  
      return std::string(buffer);
  }
  
  std::string decode_cps_thumb_t1_to_string(const ARMInstruction *ins) {
      // DEBUG: CPS<effect> <iflags>
      std::string tmp = "CPS" + effect_str(ins) + " ";
  
      if (iflags_str(ins) != "") {
          tmp += iflags_str(ins);
      }
  
      return tmp;
  }
  
  std::string decode_cps_thumb_t2_to_string(const ARMInstruction *ins) {
      std::string tmp = "CPS" + effect_str(ins) + ".W ";
  
      if (iflags_str(ins) != "") {
          tmp += iflags_str(ins);
  
          if (ins->changemode) {
              tmp += ", #" + std::to_string(ins->mode);
          }
  
      } else {
          if (ins->changemode) {
              tmp += "#" + std::to_string(ins->mode);
          }
      }
  
      return tmp;
  }
  
  std::string decode_cps_arm_a1_to_string(const ARMInstruction *ins) {
      std::string tmp = "CPS" + effect_str(ins) + " ";
  
      if (iflags_str(ins) != "") {
          tmp += iflags_str(ins);
  
          if (ins->changemode) {
              tmp += ", #" + std::to_string(ins->mode);
          }
  
      } else {
          if (ins->changemode) {
              tmp += "#" + std::to_string(ins->mode);
          }
      }
  
      return tmp;
  }
  