diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -87,6 +87,14 @@ VEXEncoding ForcedVEXEncoding = VEXEncoding_Default; + enum DispEncoding { + DispEncoding_Default, + DispEncoding_Disp8, + DispEncoding_Disp32, + }; + + DispEncoding ForcedDispEncoding = DispEncoding_Default; + private: SMLoc consumeToken() { MCAsmParser &Parser = getParser(); @@ -2592,6 +2600,7 @@ // Reset the forced VEX encoding. ForcedVEXEncoding = VEXEncoding_Default; + ForcedDispEncoding = DispEncoding_Default; // Parse pseudo prefixes. while (1) { @@ -2610,6 +2619,10 @@ ForcedVEXEncoding = VEXEncoding_VEX3; else if (Prefix == "evex") ForcedVEXEncoding = VEXEncoding_EVEX; + else if (Prefix == "disp8") + ForcedDispEncoding = DispEncoding_Disp8; + else if (Prefix == "disp32") + ForcedDispEncoding = DispEncoding_Disp32; else return Error(NameLoc, "unknown prefix"); @@ -3118,6 +3131,26 @@ switch (Inst.getOpcode()) { default: return false; + case X86::JMP_1: + // {disp32} forces a larger displacement as if the instruction was relaxed. + // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}. + // This matches GNU assembler. + if (ForcedDispEncoding == DispEncoding_Disp32) { + Inst.setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4); + return true; + } + + return false; + case X86::JCC_1: + // {disp32} forces a larger displacement as if the instruction was relaxed. + // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}. + // This matches GNU assembler. + if (ForcedDispEncoding == DispEncoding_Disp32) { + Inst.setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4); + return true; + } + + return false; case X86::VMOVZPQILo2PQIrr: case X86::VMOVAPDrr: case X86::VMOVAPDYrr: diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s --- a/llvm/test/MC/X86/x86-16.s +++ b/llvm/test/MC/X86/x86-16.s @@ -1045,3 +1045,14 @@ // CHECK: xresldtrk // CHECK: encoding: [0xf2,0x0f,0x01,0xe9] xresldtrk + +// CHECK: jmp foo +// CHECK: encoding: [0xe9,A,A] +// CHECK: fixup A - offset: 1, value: foo-2, kind: FK_PCRel_2 +{disp32} jmp foo +foo: + +// CHECK: je foo +// CHECK: encoding: [0x0f,0x84,A,A] +// CHECK: fixup A - offset: 2, value: foo-2, kind: FK_PCRel_2 +{disp32} je foo diff --git a/llvm/test/MC/X86/x86-32.s b/llvm/test/MC/X86/x86-32.s --- a/llvm/test/MC/X86/x86-32.s +++ b/llvm/test/MC/X86/x86-32.s @@ -1109,3 +1109,14 @@ // CHECK: ptwritel %eax // CHECK: encoding: [0xf3,0x0f,0xae,0xe0] ptwritel %eax + +// CHECK: jmp foo +// CHECK: encoding: [0xe9,A,A,A,A] +// CHECK: fixup A - offset: 1, value: foo-4, kind: FK_PCRel_4 +{disp32} jmp foo +foo: + +// CHECK: je foo +// CHECK: encoding: [0x0f,0x84,A,A,A,A] +// CHECK: fixup A - offset: 2, value: foo-4, kind: FK_PCRel_4 +{disp32} je foo