Add a t8jccd_long encoding recipe for brz.b1 and brnz.b1 in 32-bit mode.

The register allocator can't handle branches with constrained register
operands, and the brz.b1/brnz.b1 instructions only have the t8jccd_abcd
in 32-bit mode where no REX prefixes are possible.

This adds a worst case encoding for those cases where a b1 value lives
in a non-ABCD register.
This commit is contained in:
Jakob Stoklund Olesen
2017-10-11 14:18:21 -07:00
parent ece09f2df2
commit ba52a38597
3 changed files with 53 additions and 0 deletions

View File

@@ -292,6 +292,12 @@ enc_i32_i64(base.brnz, r.tjccd, 0x85)
# Branch on a b1 value in a register only looks at the low 8 bits. See also
# bint encodings below.
#
# Start with the worst-case encoding for I32 only. The register allocator can't
# handle a branch with an ABCD-constrained operand.
I32.enc(base.brz.b1, *r.t8jccd_long(0x84))
I32.enc(base.brnz.b1, *r.t8jccd_long(0x85))
enc_both(base.brz.b1, r.t8jccb_abcd, 0x74)
enc_both(base.brz.b1, r.t8jccd_abcd, 0x84)
enc_both(base.brnz.b1, r.t8jccb_abcd, 0x75)

View File

@@ -848,6 +848,25 @@ t8jccd_abcd = TailRecipe(
disp4(destination, func, sink);
''')
# Worst case test-and-branch recipe for brz.b1 and brnz.b1 in 32-bit mode.
# The register allocator can't handle a branch instruction with constrained
# operands like the t8jccd_abcd above. This variant can accept the b1 opernd in
# any register, but is is larger because it uses a 32-bit test instruction with
# a 0xff immediate.
t8jccd_long = TailRecipe(
't8jccd_long', Branch, size=5 + 6, ins=GPR, outs=(),
branch_range=32,
emit='''
// test32 r, 0xff.
PUT_OP((bits & 0xff00) | 0xf7, rex1(in_reg0), sink);
modrm_r_bits(in_reg0, bits, sink);
sink.put4(0xff);
// Jcc instruction.
sink.put1(0x0f);
sink.put1(bits as u8);
disp4(destination, func, sink);
''')
# Comparison that produces a `b1` result in a GPR.
#
# This is a macro of a `cmp` instruction followed by a `setCC` instruction.