+/* Try the shortest encoding by shortening operand size. */
+
+static void
+optimize_encoding (void)
+{
+ unsigned int j;
+
+ if (optimize_for_space
+ && i.reg_operands == 1
+ && i.imm_operands == 1
+ && !i.types[1].bitfield.byte
+ && i.op[0].imms->X_op == O_constant
+ && fits_in_imm7 (i.op[0].imms->X_add_number)
+ && ((i.tm.base_opcode == 0xa8
+ && i.tm.extension_opcode == None)
+ || (i.tm.base_opcode == 0xf6
+ && i.tm.extension_opcode == 0x0)))
+ {
+ /* Optimize: -Os:
+ test $imm7, %r64/%r32/%r16 -> test $imm7, %r8
+ */
+ unsigned int base_regnum = i.op[1].regs->reg_num;
+ if (flag_code == CODE_64BIT || base_regnum < 4)
+ {
+ i.types[1].bitfield.byte = 1;
+ /* Ignore the suffix. */
+ i.suffix = 0;
+ if (base_regnum >= 4
+ && !(i.op[1].regs->reg_flags & RegRex))
+ {
+ /* Handle SP, BP, SI and DI registers. */
+ if (i.types[1].bitfield.word)
+ j = 16;
+ else if (i.types[1].bitfield.dword)
+ j = 32;
+ else
+ j = 48;
+ i.op[1].regs -= j;
+ }
+ }
+ }
+ else if (flag_code == CODE_64BIT
+ && ((i.types[1].bitfield.qword
+ && i.reg_operands == 1
+ && i.imm_operands == 1
+ && i.op[0].imms->X_op == O_constant
+ && ((i.tm.base_opcode == 0xb8
+ && i.tm.extension_opcode == None
+ && fits_in_unsigned_long (i.op[0].imms->X_add_number))
+ || (fits_in_imm31 (i.op[0].imms->X_add_number)
+ && (((i.tm.base_opcode == 0x24
+ || i.tm.base_opcode == 0xa8)
+ && i.tm.extension_opcode == None)
+ || (i.tm.base_opcode == 0x80
+ && i.tm.extension_opcode == 0x4)
+ || ((i.tm.base_opcode == 0xf6
+ || (i.tm.base_opcode | 1) == 0xc7)
+ && i.tm.extension_opcode == 0x0)))
+ || (fits_in_imm7 (i.op[0].imms->X_add_number)
+ && i.tm.base_opcode == 0x83
+ && i.tm.extension_opcode == 0x4)))
+ || (i.types[0].bitfield.qword
+ && ((i.reg_operands == 2
+ && i.op[0].regs == i.op[1].regs
+ && ((i.tm.base_opcode == 0x30
+ || i.tm.base_opcode == 0x28)
+ && i.tm.extension_opcode == None))
+ || (i.reg_operands == 1
+ && i.operands == 1
+ && i.tm.base_opcode == 0x30
+ && i.tm.extension_opcode == None)))))
+ {
+ /* Optimize: -O:
+ andq $imm31, %r64 -> andl $imm31, %r32
+ andq $imm7, %r64 -> andl $imm7, %r32
+ testq $imm31, %r64 -> testl $imm31, %r32
+ xorq %r64, %r64 -> xorl %r32, %r32
+ subq %r64, %r64 -> subl %r32, %r32
+ movq $imm31, %r64 -> movl $imm31, %r32
+ movq $imm32, %r64 -> movl $imm32, %r32
+ */
+ i.tm.opcode_modifier.norex64 = 1;
+ if (i.tm.base_opcode == 0xb8 || (i.tm.base_opcode | 1) == 0xc7)
+ {
+ /* Handle
+ movq $imm31, %r64 -> movl $imm31, %r32
+ movq $imm32, %r64 -> movl $imm32, %r32
+ */
+ i.tm.operand_types[0].bitfield.imm32 = 1;
+ i.tm.operand_types[0].bitfield.imm32s = 0;
+ i.tm.operand_types[0].bitfield.imm64 = 0;
+ i.types[0].bitfield.imm32 = 1;
+ i.types[0].bitfield.imm32s = 0;
+ i.types[0].bitfield.imm64 = 0;
+ i.types[1].bitfield.dword = 1;
+ i.types[1].bitfield.qword = 0;
+ if ((i.tm.base_opcode | 1) == 0xc7)
+ {
+ /* Handle
+ movq $imm31, %r64 -> movl $imm31, %r32
+ */
+ i.tm.base_opcode = 0xb8;
+ i.tm.extension_opcode = None;
+ i.tm.opcode_modifier.w = 0;
+ i.tm.opcode_modifier.shortform = 1;
+ i.tm.opcode_modifier.modrm = 0;
+ }
+ }
+ }
+ else if (optimize > 1
+ && !optimize_for_space
+ && i.reg_operands == 2
+ && i.op[0].regs == i.op[1].regs
+ && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
+ || (i.tm.base_opcode & ~(Opcode_D | 1)) == 0x20)
+ && (flag_code != CODE_64BIT || !i.types[0].bitfield.dword))
+ {
+ /* Optimize: -O2:
+ andb %rN, %rN -> testb %rN, %rN
+ andw %rN, %rN -> testw %rN, %rN
+ andq %rN, %rN -> testq %rN, %rN
+ orb %rN, %rN -> testb %rN, %rN
+ orw %rN, %rN -> testw %rN, %rN
+ orq %rN, %rN -> testq %rN, %rN
+
+ and outside of 64-bit mode
+
+ andl %rN, %rN -> testl %rN, %rN
+ orl %rN, %rN -> testl %rN, %rN
+ */
+ i.tm.base_opcode = 0x84 | (i.tm.base_opcode & 1);
+ }
+ else if (i.reg_operands == 3
+ && i.op[0].regs == i.op[1].regs
+ && !i.types[2].bitfield.xmmword
+ && (i.tm.opcode_modifier.vex
+ || ((!i.mask || i.mask->zeroing)
+ && !i.rounding
+ && is_evex_encoding (&i.tm)
+ && (i.vec_encoding != vex_encoding_evex
+ || cpu_arch_isa_flags.bitfield.cpuavx512vl
+ || i.tm.cpu_flags.bitfield.cpuavx512vl
+ || (i.tm.operand_types[2].bitfield.zmmword
+ && i.types[2].bitfield.ymmword))))
+ && ((i.tm.base_opcode == 0x55
+ || i.tm.base_opcode == 0x6655
+ || i.tm.base_opcode == 0x66df
+ || i.tm.base_opcode == 0x57
+ || i.tm.base_opcode == 0x6657
+ || i.tm.base_opcode == 0x66ef
+ || i.tm.base_opcode == 0x66f8
+ || i.tm.base_opcode == 0x66f9
+ || i.tm.base_opcode == 0x66fa
+ || i.tm.base_opcode == 0x66fb
+ || i.tm.base_opcode == 0x42
+ || i.tm.base_opcode == 0x6642
+ || i.tm.base_opcode == 0x47
+ || i.tm.base_opcode == 0x6647)
+ && i.tm.extension_opcode == None))
+ {
+ /* Optimize: -O1:
+ VOP, one of vandnps, vandnpd, vxorps, vxorpd, vpsubb, vpsubd,
+ vpsubq and vpsubw:
+ EVEX VOP %zmmM, %zmmM, %zmmN
+ -> VEX VOP %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ EVEX VOP %ymmM, %ymmM, %ymmN
+ -> VEX VOP %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ VEX VOP %ymmM, %ymmM, %ymmN
+ -> VEX VOP %xmmM, %xmmM, %xmmN
+ VOP, one of vpandn and vpxor:
+ VEX VOP %ymmM, %ymmM, %ymmN
+ -> VEX VOP %xmmM, %xmmM, %xmmN
+ VOP, one of vpandnd and vpandnq:
+ EVEX VOP %zmmM, %zmmM, %zmmN
+ -> VEX vpandn %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ EVEX VOP %ymmM, %ymmM, %ymmN
+ -> VEX vpandn %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ VOP, one of vpxord and vpxorq:
+ EVEX VOP %zmmM, %zmmM, %zmmN
+ -> VEX vpxor %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ EVEX VOP %ymmM, %ymmM, %ymmN
+ -> VEX vpxor %xmmM, %xmmM, %xmmN (M and N < 16)
+ -> EVEX VOP %xmmM, %xmmM, %xmmN (M || N >= 16) (-O2)
+ VOP, one of kxord and kxorq:
+ VEX VOP %kM, %kM, %kN
+ -> VEX kxorw %kM, %kM, %kN
+ VOP, one of kandnd and kandnq:
+ VEX VOP %kM, %kM, %kN
+ -> VEX kandnw %kM, %kM, %kN
+ */
+ if (is_evex_encoding (&i.tm))
+ {
+ if (i.vec_encoding != vex_encoding_evex)
+ {
+ i.tm.opcode_modifier.vex = VEX128;
+ i.tm.opcode_modifier.vexw = VEXW0;
+ i.tm.opcode_modifier.evex = 0;
+ }
+ else if (optimize > 1)
+ i.tm.opcode_modifier.evex = EVEX128;
+ else
+ return;
+ }
+ else if (i.tm.operand_types[0].bitfield.class == RegMask)
+ {
+ i.tm.base_opcode &= 0xff;
+ i.tm.opcode_modifier.vexw = VEXW0;
+ }
+ else
+ i.tm.opcode_modifier.vex = VEX128;
+
+ if (i.tm.opcode_modifier.vex)
+ for (j = 0; j < 3; j++)
+ {
+ i.types[j].bitfield.xmmword = 1;
+ i.types[j].bitfield.ymmword = 0;
+ }
+ }
+ else if (i.vec_encoding != vex_encoding_evex
+ && !i.types[0].bitfield.zmmword
+ && !i.types[1].bitfield.zmmword
+ && !i.mask
+ && !i.broadcast
+ && is_evex_encoding (&i.tm)
+ && ((i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0x666f
+ || (i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0xf36f
+ || (i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0xf26f
+ || (i.tm.base_opcode & ~4) == 0x66db
+ || (i.tm.base_opcode & ~4) == 0x66eb)
+ && i.tm.extension_opcode == None)
+ {
+ /* Optimize: -O1:
+ VOP, one of vmovdqa32, vmovdqa64, vmovdqu8, vmovdqu16,
+ vmovdqu32 and vmovdqu64:
+ EVEX VOP %xmmM, %xmmN
+ -> VEX vmovdqa|vmovdqu %xmmM, %xmmN (M and N < 16)
+ EVEX VOP %ymmM, %ymmN
+ -> VEX vmovdqa|vmovdqu %ymmM, %ymmN (M and N < 16)
+ EVEX VOP %xmmM, mem
+ -> VEX vmovdqa|vmovdqu %xmmM, mem (M < 16)
+ EVEX VOP %ymmM, mem
+ -> VEX vmovdqa|vmovdqu %ymmM, mem (M < 16)
+ EVEX VOP mem, %xmmN
+ -> VEX mvmovdqa|vmovdquem, %xmmN (N < 16)
+ EVEX VOP mem, %ymmN
+ -> VEX vmovdqa|vmovdqu mem, %ymmN (N < 16)
+ VOP, one of vpand, vpandn, vpor, vpxor:
+ EVEX VOP{d,q} %xmmL, %xmmM, %xmmN
+ -> VEX VOP %xmmL, %xmmM, %xmmN (L, M, and N < 16)
+ EVEX VOP{d,q} %ymmL, %ymmM, %ymmN
+ -> VEX VOP %ymmL, %ymmM, %ymmN (L, M, and N < 16)
+ EVEX VOP{d,q} mem, %xmmM, %xmmN
+ -> VEX VOP mem, %xmmM, %xmmN (M and N < 16)
+ EVEX VOP{d,q} mem, %ymmM, %ymmN
+ -> VEX VOP mem, %ymmM, %ymmN (M and N < 16)
+ */
+ for (j = 0; j < i.operands; j++)
+ if (operand_type_check (i.types[j], disp)
+ && i.op[j].disps->X_op == O_constant)
+ {
+ /* Since the VEX prefix has 2 or 3 bytes, the EVEX prefix
+ has 4 bytes, EVEX Disp8 has 1 byte and VEX Disp32 has 4
+ bytes, we choose EVEX Disp8 over VEX Disp32. */
+ int evex_disp8, vex_disp8;
+ unsigned int memshift = i.memshift;
+ offsetT n = i.op[j].disps->X_add_number;
+
+ evex_disp8 = fits_in_disp8 (n);
+ i.memshift = 0;
+ vex_disp8 = fits_in_disp8 (n);
+ if (evex_disp8 != vex_disp8)
+ {
+ i.memshift = memshift;
+ return;
+ }
+
+ i.types[j].bitfield.disp8 = vex_disp8;
+ break;
+ }
+ if ((i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0xf26f)
+ i.tm.base_opcode ^= 0xf36f ^ 0xf26f;
+ i.tm.opcode_modifier.vex
+ = i.types[0].bitfield.ymmword ? VEX256 : VEX128;
+ i.tm.opcode_modifier.vexw = VEXW0;
+ /* VPAND, VPOR, and VPXOR are commutative. */
+ if (i.reg_operands == 3 && i.tm.base_opcode != 0x66df)
+ i.tm.opcode_modifier.commutative = 1;
+ i.tm.opcode_modifier.evex = 0;
+ i.tm.opcode_modifier.masking = 0;
+ i.tm.opcode_modifier.broadcast = 0;
+ i.tm.opcode_modifier.disp8memshift = 0;
+ i.memshift = 0;
+ if (j < i.operands)
+ i.types[j].bitfield.disp8
+ = fits_in_disp8 (i.op[j].disps->X_add_number);
+ }
+}
+