diff options
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 57ae6c5..c7b9a95 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1157,6 +1157,7 @@ static const arch_entry cpu_arch[] = VECARCH (sm4, SM4, ANY_SM4, reset), SUBARCH (pbndkb, PBNDKB, PBNDKB, false), VECARCH (avx10.1, AVX10_1, ANY_AVX512F, set), + SUBARCH (user_msr, USER_MSR, USER_MSR, false), }; #undef SUBARCH @@ -2474,7 +2475,8 @@ smallest_imm_type (offsetT num) t.bitfield.imm8 = 1; t.bitfield.imm8s = 1; t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_unsigned_byte (num)) @@ -2487,12 +2489,14 @@ smallest_imm_type (offsetT num) else if (fits_in_signed_word (num) || fits_in_unsigned_word (num)) { t.bitfield.imm16 = 1; - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_signed_long (num)) { - t.bitfield.imm32 = 1; + if (flag_code != CODE_64BIT || fits_in_unsigned_long (num)) + t.bitfield.imm32 = 1; t.bitfield.imm32s = 1; } else if (fits_in_unsigned_long (num)) @@ -3833,6 +3837,7 @@ build_vex_prefix (const insn_template *t) case SPACE_0F: case SPACE_0F38: case SPACE_0F3A: + case SPACE_VEXMAP7: i.vex.bytes[0] = 0xc4; break; case SPACE_XOP08: @@ -5203,7 +5208,23 @@ md_assemble (char *line) swap_2_operands (0, 1); if (i.imm_operands) - optimize_imm (); + { + /* For USER_MSR instructions, imm32 stands for the name of an model specific + register (MSR). That's an unsigned quantity, whereas all other insns with + 32-bit immediate and 64-bit operand size use sign-extended + immediates (imm32s). Therefore these insns are special-cased, bypassing + the normal handling of immediates here. */ + if (is_cpu(current_templates->start, CpuUSER_MSR)) + { + for (j = 0; j < i.operands; j++) + { + if (operand_type_check(i.types[j], imm)) + i.types[j] = smallest_imm_type (i.op[j].imms->X_add_number); + } + } + else + optimize_imm (); + } if (i.disp_operands && !optimize_disp (t)) return; @@ -7536,6 +7557,17 @@ match_template (char mnem_suffix) break; } + /* This pattern aims to put the unusually placed imm operand to a usual + place. The constraints are currently only adapted to uwrmsr, and may + need further tweaking when new similar instructions become available. */ + if (i.imm_operands && i.imm_operands < i.operands + && operand_type_check (operand_types[i.operands - 1], imm)) + { + i.tm.operand_types[0] = operand_types[i.operands - 1]; + i.tm.operand_types[i.operands - 1] = operand_types[0]; + swap_2_operands(0, i.operands - 1); + } + return t; } |