Add Intel encodings for the icmp instruction.

This instruction returns a `b1` value which is represented as the output
of a setCC instruction which is the low 8 bits of a GPR register. Use a
cmp+setCC macro recipe to encode this. That is not ideal, but we can't
represent CPU flags yet.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-19 10:47:51 -07:00
parent 5a81831c69
commit 82fbc78f2f
5 changed files with 297 additions and 22 deletions

View File

@@ -254,6 +254,78 @@ ebb0:
; asm: tzcntl %ecx, %esi ; asm: tzcntl %ecx, %esi
[-,%rsi] v205 = ctz v1 ; bin: f3 0f bc f1 [-,%rsi] v205 = ctz v1 ; bin: f3 0f bc f1
; Integer comparisons.
; asm: cmpl %esi, %ecx
; asm: sete %bl
[-,%rbx] v300 = icmp eq v1, v2 ; bin: 39 f1 0f 94 c3
; asm: cmpl %ecx, %esi
; asm: sete %dl
[-,%rdx] v301 = icmp eq v2, v1 ; bin: 39 ce 0f 94 c2
; asm: cmpl %esi, %ecx
; asm: setne %bl
[-,%rbx] v302 = icmp ne v1, v2 ; bin: 39 f1 0f 95 c3
; asm: cmpl %ecx, %esi
; asm: setne %dl
[-,%rdx] v303 = icmp ne v2, v1 ; bin: 39 ce 0f 95 c2
; asm: cmpl %esi, %ecx
; asm: setl %bl
[-,%rbx] v304 = icmp slt v1, v2 ; bin: 39 f1 0f 9c c3
; asm: cmpl %ecx, %esi
; asm: setl %dl
[-,%rdx] v305 = icmp slt v2, v1 ; bin: 39 ce 0f 9c c2
; asm: cmpl %esi, %ecx
; asm: setge %bl
[-,%rbx] v306 = icmp sge v1, v2 ; bin: 39 f1 0f 9d c3
; asm: cmpl %ecx, %esi
; asm: setge %dl
[-,%rdx] v307 = icmp sge v2, v1 ; bin: 39 ce 0f 9d c2
; asm: cmpl %esi, %ecx
; asm: setg %bl
[-,%rbx] v308 = icmp sgt v1, v2 ; bin: 39 f1 0f 9f c3
; asm: cmpl %ecx, %esi
; asm: setg %dl
[-,%rdx] v309 = icmp sgt v2, v1 ; bin: 39 ce 0f 9f c2
; asm: cmpl %esi, %ecx
; asm: setle %bl
[-,%rbx] v310 = icmp sle v1, v2 ; bin: 39 f1 0f 9e c3
; asm: cmpl %ecx, %esi
; asm: setle %dl
[-,%rdx] v311 = icmp sle v2, v1 ; bin: 39 ce 0f 9e c2
; asm: cmpl %esi, %ecx
; asm: setb %bl
[-,%rbx] v312 = icmp ult v1, v2 ; bin: 39 f1 0f 92 c3
; asm: cmpl %ecx, %esi
; asm: setb %dl
[-,%rdx] v313 = icmp ult v2, v1 ; bin: 39 ce 0f 92 c2
; asm: cmpl %esi, %ecx
; asm: setae %bl
[-,%rbx] v314 = icmp uge v1, v2 ; bin: 39 f1 0f 93 c3
; asm: cmpl %ecx, %esi
; asm: setae %dl
[-,%rdx] v315 = icmp uge v2, v1 ; bin: 39 ce 0f 93 c2
; asm: cmpl %esi, %ecx
; asm: seta %bl
[-,%rbx] v316 = icmp ugt v1, v2 ; bin: 39 f1 0f 97 c3
; asm: cmpl %ecx, %esi
; asm: seta %dl
[-,%rdx] v317 = icmp ugt v2, v1 ; bin: 39 ce 0f 97 c2
; asm: cmpl %esi, %ecx
; asm: setbe %bl
[-,%rbx] v318 = icmp ule v1, v2 ; bin: 39 f1 0f 96 c3
; asm: cmpl %ecx, %esi
; asm: setbe %dl
[-,%rdx] v319 = icmp ule v2, v1 ; bin: 39 ce 0f 96 c2
; asm: call foo ; asm: call foo
call fn0() ; bin: e8 PCRel4(fn0) 00000000 call fn0() ; bin: e8 PCRel4(fn0) 00000000

View File

@@ -192,22 +192,94 @@ ebb0:
; asm: tzcntq %rcx, %r10 ; asm: tzcntq %rcx, %r10
[-,%r10] v208 = ctz v1 ; bin: f3 4c 0f bc d1 [-,%r10] v208 = ctz v1 ; bin: f3 4c 0f bc d1
; asm: testq %rcx, %ecx ; Integer comparisons.
; asm: cmpq %rsi, %rcx
; asm: sete %bl
[-,%rbx] v300 = icmp eq v1, v2 ; bin: 48 39 f1 0f 94 c3
; asm: cmpq %r10, %rsi
; asm: sete %dl
[-,%rdx] v301 = icmp eq v2, v3 ; bin: 4c 39 d6 0f 94 c2
; asm: cmpq %rsi, %rcx
; asm: setne %bl
[-,%rbx] v302 = icmp ne v1, v2 ; bin: 48 39 f1 0f 95 c3
; asm: cmpq %r10, %rsi
; asm: setne %dl
[-,%rdx] v303 = icmp ne v2, v3 ; bin: 4c 39 d6 0f 95 c2
; asm: cmpq %rsi, %rcx
; asm: setl %bl
[-,%rbx] v304 = icmp slt v1, v2 ; bin: 48 39 f1 0f 9c c3
; asm: cmpq %r10, %rsi
; asm: setl %dl
[-,%rdx] v305 = icmp slt v2, v3 ; bin: 4c 39 d6 0f 9c c2
; asm: cmpq %rsi, %rcx
; asm: setge %bl
[-,%rbx] v306 = icmp sge v1, v2 ; bin: 48 39 f1 0f 9d c3
; asm: cmpq %r10, %rsi
; asm: setge %dl
[-,%rdx] v307 = icmp sge v2, v3 ; bin: 4c 39 d6 0f 9d c2
; asm: cmpq %rsi, %rcx
; asm: setg %bl
[-,%rbx] v308 = icmp sgt v1, v2 ; bin: 48 39 f1 0f 9f c3
; asm: cmpq %r10, %rsi
; asm: setg %dl
[-,%rdx] v309 = icmp sgt v2, v3 ; bin: 4c 39 d6 0f 9f c2
; asm: cmpq %rsi, %rcx
; asm: setle %bl
[-,%rbx] v310 = icmp sle v1, v2 ; bin: 48 39 f1 0f 9e c3
; asm: cmpq %r10, %rsi
; asm: setle %dl
[-,%rdx] v311 = icmp sle v2, v3 ; bin: 4c 39 d6 0f 9e c2
; asm: cmpq %rsi, %rcx
; asm: setb %bl
[-,%rbx] v312 = icmp ult v1, v2 ; bin: 48 39 f1 0f 92 c3
; asm: cmpq %r10, %rsi
; asm: setb %dl
[-,%rdx] v313 = icmp ult v2, v3 ; bin: 4c 39 d6 0f 92 c2
; asm: cmpq %rsi, %rcx
; asm: setae %bl
[-,%rbx] v314 = icmp uge v1, v2 ; bin: 48 39 f1 0f 93 c3
; asm: cmpq %r10, %rsi
; asm: setae %dl
[-,%rdx] v315 = icmp uge v2, v3 ; bin: 4c 39 d6 0f 93 c2
; asm: cmpq %rsi, %rcx
; asm: seta %bl
[-,%rbx] v316 = icmp ugt v1, v2 ; bin: 48 39 f1 0f 97 c3
; asm: cmpq %r10, %rsi
; asm: seta %dl
[-,%rdx] v317 = icmp ugt v2, v3 ; bin: 4c 39 d6 0f 97 c2
; asm: cmpq %rsi, %rcx
; asm: setbe %bl
[-,%rbx] v318 = icmp ule v1, v2 ; bin: 48 39 f1 0f 96 c3
; asm: cmpq %r10, %rsi
; asm: setbe %dl
[-,%rdx] v319 = icmp ule v2, v3 ; bin: 4c 39 d6 0f 96 c2
; asm: testq %rcx, %rcx
; asm: je ebb1 ; asm: je ebb1
brz v1, ebb1 ; bin: 48 85 c9 74 1b brz v1, ebb1 ; bin: 48 85 c9 74 1b
; asm: testq %rsi, %esi ; asm: testq %rsi, %rsi
; asm: je ebb1 ; asm: je ebb1
brz v2, ebb1 ; bin: 48 85 f6 74 16 brz v2, ebb1 ; bin: 48 85 f6 74 16
; asm: testq %r10, %r10d ; asm: testq %r10, %r10
; asm: je ebb1 ; asm: je ebb1
brz v3, ebb1 ; bin: 4d 85 d2 74 11 brz v3, ebb1 ; bin: 4d 85 d2 74 11
; asm: testq %rcx, %ecx ; asm: testq %rcx, %rcx
; asm: jne ebb1 ; asm: jne ebb1
brnz v1, ebb1 ; bin: 48 85 c9 75 0c brnz v1, ebb1 ; bin: 48 85 c9 75 0c
; asm: test %rsi, %esi ; asm: testq %rsi, %rsi
; asm: jne ebb1 ; asm: jne ebb1
brnz v2, ebb1 ; bin: 48 85 f6 75 07 brnz v2, ebb1 ; bin: 48 85 f6 75 07
; asm: testq %r10, %r10d ; asm: testq %r10, %r10
; asm: jne ebb1 ; asm: jne ebb1
brnz v3, ebb1 ; bin: 4d 85 d2 75 02 brnz v3, ebb1 ; bin: 4d 85 d2 75 02
@@ -376,15 +448,15 @@ ebb0:
[-,%rax] v130 = iconst.i32 1 [-,%rax] v130 = iconst.i32 1
[-,%rdx] v131 = iconst.i32 2 [-,%rdx] v131 = iconst.i32 2
; asm: idivl %rcx ; asm: idivl %ecx
[-,%rax,%rdx] v132, v133 = x86_sdivmodx v130, v131, v1 ; bin: 40 f7 f9 [-,%rax,%rdx] v132, v133 = x86_sdivmodx v130, v131, v1 ; bin: 40 f7 f9
; asm: idivl %rsi ; asm: idivl %esi
[-,%rax,%rdx] v134, v135 = x86_sdivmodx v130, v131, v2 ; bin: 40 f7 fe [-,%rax,%rdx] v134, v135 = x86_sdivmodx v130, v131, v2 ; bin: 40 f7 fe
; asm: idivl %r10d ; asm: idivl %r10d
[-,%rax,%rdx] v136, v137 = x86_sdivmodx v130, v131, v3 ; bin: 41 f7 fa [-,%rax,%rdx] v136, v137 = x86_sdivmodx v130, v131, v3 ; bin: 41 f7 fa
; asm: divl %rcx ; asm: divl %ecx
[-,%rax,%rdx] v138, v139 = x86_udivmodx v130, v131, v1 ; bin: 40 f7 f1 [-,%rax,%rdx] v138, v139 = x86_udivmodx v130, v131, v1 ; bin: 40 f7 f1
; asm: divl %rsi ; asm: divl %esi
[-,%rax,%rdx] v140, v141 = x86_udivmodx v130, v131, v2 ; bin: 40 f7 f6 [-,%rax,%rdx] v140, v141 = x86_udivmodx v130, v131, v2 ; bin: 40 f7 f6
; asm: divl %r10d ; asm: divl %r10d
[-,%rax,%rdx] v142, v143 = x86_udivmodx v130, v131, v3 ; bin: 41 f7 f2 [-,%rax,%rdx] v142, v143 = x86_udivmodx v130, v131, v3 ; bin: 41 f7 f2
@@ -412,33 +484,105 @@ ebb0:
; asm: tzcntl %ecx, %r10d ; asm: tzcntl %ecx, %r10d
[-,%r10] v208 = ctz v1 ; bin: f3 44 0f bc d1 [-,%r10] v208 = ctz v1 ; bin: f3 44 0f bc d1
; Integer comparisons.
; asm: cmpl %esi, %ecx
; asm: sete %bl
[-,%rbx] v300 = icmp eq v1, v2 ; bin: 40 39 f1 0f 94 c3
; asm: cmpl %r10d, %esi
; asm: sete %dl
[-,%rdx] v301 = icmp eq v2, v3 ; bin: 44 39 d6 0f 94 c2
; asm: cmpl %esi, %ecx
; asm: setne %bl
[-,%rbx] v302 = icmp ne v1, v2 ; bin: 40 39 f1 0f 95 c3
; asm: cmpl %r10d, %esi
; asm: setne %dl
[-,%rdx] v303 = icmp ne v2, v3 ; bin: 44 39 d6 0f 95 c2
; asm: cmpl %esi, %ecx
; asm: setl %bl
[-,%rbx] v304 = icmp slt v1, v2 ; bin: 40 39 f1 0f 9c c3
; asm: cmpl %r10d, %esi
; asm: setl %dl
[-,%rdx] v305 = icmp slt v2, v3 ; bin: 44 39 d6 0f 9c c2
; asm: cmpl %esi, %ecx
; asm: setge %bl
[-,%rbx] v306 = icmp sge v1, v2 ; bin: 40 39 f1 0f 9d c3
; asm: cmpl %r10d, %esi
; asm: setge %dl
[-,%rdx] v307 = icmp sge v2, v3 ; bin: 44 39 d6 0f 9d c2
; asm: cmpl %esi, %ecx
; asm: setg %bl
[-,%rbx] v308 = icmp sgt v1, v2 ; bin: 40 39 f1 0f 9f c3
; asm: cmpl %r10d, %esi
; asm: setg %dl
[-,%rdx] v309 = icmp sgt v2, v3 ; bin: 44 39 d6 0f 9f c2
; asm: cmpl %esi, %ecx
; asm: setle %bl
[-,%rbx] v310 = icmp sle v1, v2 ; bin: 40 39 f1 0f 9e c3
; asm: cmpl %r10d, %esi
; asm: setle %dl
[-,%rdx] v311 = icmp sle v2, v3 ; bin: 44 39 d6 0f 9e c2
; asm: cmpl %esi, %ecx
; asm: setb %bl
[-,%rbx] v312 = icmp ult v1, v2 ; bin: 40 39 f1 0f 92 c3
; asm: cmpl %r10d, %esi
; asm: setb %dl
[-,%rdx] v313 = icmp ult v2, v3 ; bin: 44 39 d6 0f 92 c2
; asm: cmpl %esi, %ecx
; asm: setae %bl
[-,%rbx] v314 = icmp uge v1, v2 ; bin: 40 39 f1 0f 93 c3
; asm: cmpl %r10d, %esi
; asm: setae %dl
[-,%rdx] v315 = icmp uge v2, v3 ; bin: 44 39 d6 0f 93 c2
; asm: cmpl %esi, %ecx
; asm: seta %bl
[-,%rbx] v316 = icmp ugt v1, v2 ; bin: 40 39 f1 0f 97 c3
; asm: cmpl %r10d, %esi
; asm: seta %dl
[-,%rdx] v317 = icmp ugt v2, v3 ; bin: 44 39 d6 0f 97 c2
; asm: cmpl %esi, %ecx
; asm: setbe %bl
[-,%rbx] v318 = icmp ule v1, v2 ; bin: 40 39 f1 0f 96 c3
; asm: cmpl %r10d, %esi
; asm: setbe %dl
[-,%rdx] v319 = icmp ule v2, v3 ; bin: 44 39 d6 0f 96 c2
; asm: testl %ecx, %ecx ; asm: testl %ecx, %ecx
; asm: je ebb1 ; asm: je ebb1x
brz v1, ebb1 ; bin: 40 85 c9 74 1b brz v1, ebb1 ; bin: 40 85 c9 74 1b
; asm: testl %esi, %esi ; asm: testl %esi, %esi
; asm: je ebb1 ; asm: je ebb1x
brz v2, ebb1 ; bin: 40 85 f6 74 16 brz v2, ebb1 ; bin: 40 85 f6 74 16
; asm: testl %r10d, %r10d ; asm: testl %r10d, %r10d
; asm: je ebb1 ; asm: je ebb1x
brz v3, ebb1 ; bin: 45 85 d2 74 11 brz v3, ebb1 ; bin: 45 85 d2 74 11
; asm: testl %ecx, %ecx ; asm: testl %ecx, %ecx
; asm: jne ebb1 ; asm: jne ebb1x
brnz v1, ebb1 ; bin: 40 85 c9 75 0c brnz v1, ebb1 ; bin: 40 85 c9 75 0c
; asm: test %esi, %esi ; asm: testl %esi, %esi
; asm: jne ebb1 ; asm: jne ebb1x
brnz v2, ebb1 ; bin: 40 85 f6 75 07 brnz v2, ebb1 ; bin: 40 85 f6 75 07
; asm: testl %r10d, %r10d ; asm: testl %r10d, %r10d
; asm: jne ebb1 ; asm: jne ebb1x
brnz v3, ebb1 ; bin: 45 85 d2 75 02 brnz v3, ebb1 ; bin: 45 85 d2 75 02
; asm: jmp ebb2 ; asm: jmp ebb2x
jump ebb2 ; bin: eb 01 jump ebb2 ; bin: eb 01
; asm: ebb1: ; asm: ebb1x:
ebb1: ebb1:
return ; bin: c3 return ; bin: c3
; asm: ebb2: ; asm: ebb2x:
ebb2: ebb2:
jump ebb1 ; bin: eb fd jump ebb1 ; bin: eb fd
} }

View File

@@ -11,7 +11,8 @@ from .immediates import intcc
from .instructions import iadd, iadd_cout, iadd_cin, iadd_carry, iadd_imm from .instructions import iadd, iadd_cout, iadd_cin, iadd_carry, iadd_imm
from .instructions import isub, isub_bin, isub_bout, isub_borrow from .instructions import isub, isub_bin, isub_bout, isub_borrow
from .instructions import band, bor, bxor, isplit, iconcat from .instructions import band, bor, bxor, isplit, iconcat
from .instructions import icmp, iconst, bint from .instructions import icmp, icmp_imm
from .instructions import iconst, bint
from cdsl.ast import Var from cdsl.ast import Var
from cdsl.xform import Rtl, XFormGroup from cdsl.xform import Rtl, XFormGroup
@@ -53,6 +54,7 @@ yl = Var('yl')
yh = Var('yh') yh = Var('yh')
al = Var('al') al = Var('al')
ah = Var('ah') ah = Var('ah')
cc = Var('cc')
narrow.legalize( narrow.legalize(
a << iadd(x, y), a << iadd(x, y),
@@ -135,10 +137,17 @@ expand.legalize(
b << bor(b1, b2) b << bor(b1, b2)
)) ))
# Expansions for immediates that are too large. # Expansions for immediate operands that are out of range.
expand.legalize( expand.legalize(
a << iadd_imm(x, y), a << iadd_imm(x, y),
Rtl( Rtl(
a1 << iconst(y), a1 << iconst(y),
a << iadd(x, a1) a << iadd(x, a1)
)) ))
expand.legalize(
a << icmp_imm(cc, x, y),
Rtl(
a1 << iconst(y),
a << icmp(cc, x, a1)
))

View File

@@ -174,3 +174,11 @@ I32.enc(base.brnz.i32, *r.tjccb(0x75))
I64.enc(base.brnz.i64, *r.tjccb.rex(0x75, w=1)) I64.enc(base.brnz.i64, *r.tjccb.rex(0x75, w=1))
I64.enc(base.brnz.i32, *r.tjccb.rex(0x75)) I64.enc(base.brnz.i32, *r.tjccb.rex(0x75))
I64.enc(base.brnz.i32, *r.tjccb(0x75)) I64.enc(base.brnz.i32, *r.tjccb(0x75))
#
# Comparisons
#
I32.enc(base.icmp.i32, *r.icscc(0x39))
I64.enc(base.icmp.i64, *r.icscc.rex(0x39, w=1))
I64.enc(base.icmp.i32, *r.icscc.rex(0x39))
I64.enc(base.icmp.i32, *r.icscc(0x39))

View File

@@ -6,6 +6,7 @@ from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt, IsEqual from cdsl.predicates import IsSignedInt, IsEqual
from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry from base.formats import Unary, UnaryImm, Binary, BinaryImm, MultiAry
from base.formats import Call, IndirectCall, Store, Load from base.formats import Call, IndirectCall, Store, Load
from base.formats import IntCompare
from base.formats import RegMove, Ternary, Jump, Branch from base.formats import RegMove, Ternary, Jump, Branch
from .registers import GPR, ABCD from .registers import GPR, ABCD
@@ -464,3 +465,44 @@ tjccb = TailRecipe(
sink.put1(bits as u8); sink.put1(bits as u8);
disp1(destination, func, sink); disp1(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.
# This is not a great solution because:
#
# - The cmp+setcc combination is not recognized by CPU's macro fusion.
# - The 64-bit encoding has issues with REX prefixes. The `cmp` and `setCC`
# instructions may need a REX independently.
# - Modeling CPU flags in the type system would be better.
#
# Since the `setCC` instructions only write an 8-bit register, we use that as
# our `b1` representation: A `b1` value is represented as a GPR where the low 8
# bits are known to be 0 or 1. The high bits are undefined.
#
# This bandaid macro doesn't support a REX prefix for the final `setCC`
# instruction, so it is limited to the `ABCD` register class for booleans.
icscc = TailRecipe(
'cscc', IntCompare, size=1 + 3, ins=(GPR, GPR), outs=ABCD,
emit='''
// Comparison instruction.
PUT_OP(bits, rex2(in_reg0, in_reg1), sink);
modrm_rr(in_reg0, in_reg1, sink);
// `setCC` instruction, no REX.
use ir::condcodes::IntCC::*;
let setcc = match cond {
Equal => 0x94,
NotEqual => 0x95,
SignedLessThan => 0x9c,
SignedGreaterThanOrEqual => 0x9d,
SignedGreaterThan => 0x9f,
SignedLessThanOrEqual => 0x9e,
UnsignedLessThan => 0x92,
UnsignedGreaterThanOrEqual => 0x93,
UnsignedGreaterThan => 0x97,
UnsignedLessThanOrEqual => 0x96,
};
sink.put1(0x0f);
sink.put1(setcc);
modrm_rr(out_reg0, 0, sink);
''')