xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86InstrExtension.td (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker//===-- X86InstrExtension.td - Sign and Zero Extensions ----*- tablegen -*-===//
2*9880d681SAndroid Build Coastguard Worker//
3*9880d681SAndroid Build Coastguard Worker//                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker//
5*9880d681SAndroid Build Coastguard Worker// This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker// License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker//
8*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker//
10*9880d681SAndroid Build Coastguard Worker// This file describes the sign and zero extension operations.
11*9880d681SAndroid Build Coastguard Worker//
12*9880d681SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Workerlet hasSideEffects = 0 in {
15*9880d681SAndroid Build Coastguard Worker  let Defs = [AX], Uses = [AL] in
16*9880d681SAndroid Build Coastguard Worker  def CBW : I<0x98, RawFrm, (outs), (ins),
17*9880d681SAndroid Build Coastguard Worker              "{cbtw|cbw}", [], IIC_CBW>, OpSize16;  // AX = signext(AL)
18*9880d681SAndroid Build Coastguard Worker  let Defs = [EAX], Uses = [AX] in
19*9880d681SAndroid Build Coastguard Worker  def CWDE : I<0x98, RawFrm, (outs), (ins),
20*9880d681SAndroid Build Coastguard Worker              "{cwtl|cwde}", [], IIC_CBW>, OpSize32; // EAX = signext(AX)
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker  let Defs = [AX,DX], Uses = [AX] in
23*9880d681SAndroid Build Coastguard Worker  def CWD : I<0x99, RawFrm, (outs), (ins),
24*9880d681SAndroid Build Coastguard Worker              "{cwtd|cwd}", [], IIC_CBW>, OpSize16; // DX:AX = signext(AX)
25*9880d681SAndroid Build Coastguard Worker  let Defs = [EAX,EDX], Uses = [EAX] in
26*9880d681SAndroid Build Coastguard Worker  def CDQ : I<0x99, RawFrm, (outs), (ins),
27*9880d681SAndroid Build Coastguard Worker              "{cltd|cdq}", [], IIC_CBW>, OpSize32; // EDX:EAX = signext(EAX)
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker  let Defs = [RAX], Uses = [EAX] in
31*9880d681SAndroid Build Coastguard Worker  def CDQE : RI<0x98, RawFrm, (outs), (ins),
32*9880d681SAndroid Build Coastguard Worker               "{cltq|cdqe}", [], IIC_CBW>;     // RAX = signext(EAX)
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker  let Defs = [RAX,RDX], Uses = [RAX] in
35*9880d681SAndroid Build Coastguard Worker  def CQO  : RI<0x99, RawFrm, (outs), (ins),
36*9880d681SAndroid Build Coastguard Worker                "{cqto|cqo}", [], IIC_CBW>; // RDX:RAX = signext(RAX)
37*9880d681SAndroid Build Coastguard Worker}
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker// Sign/Zero extenders
42*9880d681SAndroid Build Coastguard Workerlet hasSideEffects = 0 in {
43*9880d681SAndroid Build Coastguard Workerdef MOVSX16rr8 : I<0xBE, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src),
44*9880d681SAndroid Build Coastguard Worker                   "movs{bw|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVSX_R16_R8>,
45*9880d681SAndroid Build Coastguard Worker                   TB, OpSize16, Sched<[WriteALU]>;
46*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
47*9880d681SAndroid Build Coastguard Workerdef MOVSX16rm8 : I<0xBE, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src),
48*9880d681SAndroid Build Coastguard Worker                   "movs{bw|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVSX_R16_M8>,
49*9880d681SAndroid Build Coastguard Worker                   TB, OpSize16, Sched<[WriteALULd]>;
50*9880d681SAndroid Build Coastguard Worker} // hasSideEffects = 0
51*9880d681SAndroid Build Coastguard Workerdef MOVSX32rr8 : I<0xBE, MRMSrcReg, (outs GR32:$dst), (ins GR8:$src),
52*9880d681SAndroid Build Coastguard Worker                   "movs{bl|x}\t{$src, $dst|$dst, $src}",
53*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (sext GR8:$src))], IIC_MOVSX>, TB,
54*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALU]>;
55*9880d681SAndroid Build Coastguard Workerdef MOVSX32rm8 : I<0xBE, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src),
56*9880d681SAndroid Build Coastguard Worker                   "movs{bl|x}\t{$src, $dst|$dst, $src}",
57*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (sextloadi32i8 addr:$src))], IIC_MOVSX>, TB,
58*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALULd]>;
59*9880d681SAndroid Build Coastguard Workerdef MOVSX32rr16: I<0xBF, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src),
60*9880d681SAndroid Build Coastguard Worker                   "movs{wl|x}\t{$src, $dst|$dst, $src}",
61*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (sext GR16:$src))], IIC_MOVSX>, TB,
62*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALU]>;
63*9880d681SAndroid Build Coastguard Workerdef MOVSX32rm16: I<0xBF, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src),
64*9880d681SAndroid Build Coastguard Worker                   "movs{wl|x}\t{$src, $dst|$dst, $src}",
65*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (sextloadi32i16 addr:$src))], IIC_MOVSX>,
66*9880d681SAndroid Build Coastguard Worker                   OpSize32, TB, Sched<[WriteALULd]>;
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Workerlet hasSideEffects = 0 in {
69*9880d681SAndroid Build Coastguard Workerdef MOVZX16rr8 : I<0xB6, MRMSrcReg, (outs GR16:$dst), (ins GR8:$src),
70*9880d681SAndroid Build Coastguard Worker                   "movz{bw|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX_R16_R8>,
71*9880d681SAndroid Build Coastguard Worker                   TB, OpSize16, Sched<[WriteALU]>;
72*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
73*9880d681SAndroid Build Coastguard Workerdef MOVZX16rm8 : I<0xB6, MRMSrcMem, (outs GR16:$dst), (ins i8mem:$src),
74*9880d681SAndroid Build Coastguard Worker                   "movz{bw|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX_R16_M8>,
75*9880d681SAndroid Build Coastguard Worker                   TB, OpSize16, Sched<[WriteALULd]>;
76*9880d681SAndroid Build Coastguard Worker} // hasSideEffects = 0
77*9880d681SAndroid Build Coastguard Workerdef MOVZX32rr8 : I<0xB6, MRMSrcReg, (outs GR32:$dst), (ins GR8 :$src),
78*9880d681SAndroid Build Coastguard Worker                   "movz{bl|x}\t{$src, $dst|$dst, $src}",
79*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (zext GR8:$src))], IIC_MOVZX>, TB,
80*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALU]>;
81*9880d681SAndroid Build Coastguard Workerdef MOVZX32rm8 : I<0xB6, MRMSrcMem, (outs GR32:$dst), (ins i8mem :$src),
82*9880d681SAndroid Build Coastguard Worker                   "movz{bl|x}\t{$src, $dst|$dst, $src}",
83*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (zextloadi32i8 addr:$src))], IIC_MOVZX>, TB,
84*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALULd]>;
85*9880d681SAndroid Build Coastguard Workerdef MOVZX32rr16: I<0xB7, MRMSrcReg, (outs GR32:$dst), (ins GR16:$src),
86*9880d681SAndroid Build Coastguard Worker                   "movz{wl|x}\t{$src, $dst|$dst, $src}",
87*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (zext GR16:$src))], IIC_MOVZX>, TB,
88*9880d681SAndroid Build Coastguard Worker                   OpSize32, Sched<[WriteALU]>;
89*9880d681SAndroid Build Coastguard Workerdef MOVZX32rm16: I<0xB7, MRMSrcMem, (outs GR32:$dst), (ins i16mem:$src),
90*9880d681SAndroid Build Coastguard Worker                   "movz{wl|x}\t{$src, $dst|$dst, $src}",
91*9880d681SAndroid Build Coastguard Worker                   [(set GR32:$dst, (zextloadi32i16 addr:$src))], IIC_MOVZX>,
92*9880d681SAndroid Build Coastguard Worker                   TB, OpSize32, Sched<[WriteALULd]>;
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker// These are the same as the regular MOVZX32rr8 and MOVZX32rm8
95*9880d681SAndroid Build Coastguard Worker// except that they use GR32_NOREX for the output operand register class
96*9880d681SAndroid Build Coastguard Worker// instead of GR32. This allows them to operate on h registers on x86-64.
97*9880d681SAndroid Build Coastguard Workerlet hasSideEffects = 0, isCodeGenOnly = 1 in {
98*9880d681SAndroid Build Coastguard Workerdef MOVZX32_NOREXrr8 : I<0xB6, MRMSrcReg,
99*9880d681SAndroid Build Coastguard Worker                         (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src),
100*9880d681SAndroid Build Coastguard Worker                         "movz{bl|x}\t{$src, $dst|$dst, $src}  # NOREX",
101*9880d681SAndroid Build Coastguard Worker                         [], IIC_MOVZX>, TB, OpSize32, Sched<[WriteALU]>;
102*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
103*9880d681SAndroid Build Coastguard Workerdef MOVZX32_NOREXrm8 : I<0xB6, MRMSrcMem,
104*9880d681SAndroid Build Coastguard Worker                         (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src),
105*9880d681SAndroid Build Coastguard Worker                         "movz{bl|x}\t{$src, $dst|$dst, $src}  # NOREX",
106*9880d681SAndroid Build Coastguard Worker                         [], IIC_MOVZX>, TB, OpSize32, Sched<[WriteALULd]>;
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Workerdef MOVSX32_NOREXrr8 : I<0xBE, MRMSrcReg,
109*9880d681SAndroid Build Coastguard Worker                         (outs GR32_NOREX:$dst), (ins GR8_NOREX:$src),
110*9880d681SAndroid Build Coastguard Worker                         "movs{bl|x}\t{$src, $dst|$dst, $src}  # NOREX",
111*9880d681SAndroid Build Coastguard Worker                         [], IIC_MOVSX>, TB, OpSize32, Sched<[WriteALU]>;
112*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
113*9880d681SAndroid Build Coastguard Workerdef MOVSX32_NOREXrm8 : I<0xBE, MRMSrcMem,
114*9880d681SAndroid Build Coastguard Worker                         (outs GR32_NOREX:$dst), (ins i8mem_NOREX:$src),
115*9880d681SAndroid Build Coastguard Worker                         "movs{bl|x}\t{$src, $dst|$dst, $src}  # NOREX",
116*9880d681SAndroid Build Coastguard Worker                         [], IIC_MOVSX>, TB, OpSize32, Sched<[WriteALULd]>;
117*9880d681SAndroid Build Coastguard Worker}
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker// MOVSX64rr8 always has a REX prefix and it has an 8-bit register
120*9880d681SAndroid Build Coastguard Worker// operand, which makes it a rare instruction with an 8-bit register
121*9880d681SAndroid Build Coastguard Worker// operand that can never access an h register. If support for h registers
122*9880d681SAndroid Build Coastguard Worker// were generalized, this would require a special register class.
123*9880d681SAndroid Build Coastguard Workerdef MOVSX64rr8 : RI<0xBE, MRMSrcReg, (outs GR64:$dst), (ins GR8 :$src),
124*9880d681SAndroid Build Coastguard Worker                    "movs{bq|x}\t{$src, $dst|$dst, $src}",
125*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sext GR8:$src))], IIC_MOVSX>, TB,
126*9880d681SAndroid Build Coastguard Worker                    Sched<[WriteALU]>;
127*9880d681SAndroid Build Coastguard Workerdef MOVSX64rm8 : RI<0xBE, MRMSrcMem, (outs GR64:$dst), (ins i8mem :$src),
128*9880d681SAndroid Build Coastguard Worker                    "movs{bq|x}\t{$src, $dst|$dst, $src}",
129*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sextloadi64i8 addr:$src))], IIC_MOVSX>,
130*9880d681SAndroid Build Coastguard Worker                    TB, Sched<[WriteALULd]>;
131*9880d681SAndroid Build Coastguard Workerdef MOVSX64rr16: RI<0xBF, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src),
132*9880d681SAndroid Build Coastguard Worker                    "movs{wq|x}\t{$src, $dst|$dst, $src}",
133*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sext GR16:$src))], IIC_MOVSX>, TB,
134*9880d681SAndroid Build Coastguard Worker                    Sched<[WriteALU]>;
135*9880d681SAndroid Build Coastguard Workerdef MOVSX64rm16: RI<0xBF, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src),
136*9880d681SAndroid Build Coastguard Worker                    "movs{wq|x}\t{$src, $dst|$dst, $src}",
137*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sextloadi64i16 addr:$src))], IIC_MOVSX>,
138*9880d681SAndroid Build Coastguard Worker                    TB, Sched<[WriteALULd]>;
139*9880d681SAndroid Build Coastguard Workerdef MOVSX64rr32: RI<0x63, MRMSrcReg, (outs GR64:$dst), (ins GR32:$src),
140*9880d681SAndroid Build Coastguard Worker                    "movs{lq|xd}\t{$src, $dst|$dst, $src}",
141*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sext GR32:$src))], IIC_MOVSX>,
142*9880d681SAndroid Build Coastguard Worker                    Sched<[WriteALU]>, Requires<[In64BitMode]>;
143*9880d681SAndroid Build Coastguard Workerdef MOVSX64rm32: RI<0x63, MRMSrcMem, (outs GR64:$dst), (ins i32mem:$src),
144*9880d681SAndroid Build Coastguard Worker                    "movs{lq|xd}\t{$src, $dst|$dst, $src}",
145*9880d681SAndroid Build Coastguard Worker                    [(set GR64:$dst, (sextloadi64i32 addr:$src))], IIC_MOVSX>,
146*9880d681SAndroid Build Coastguard Worker                    Sched<[WriteALULd]>, Requires<[In64BitMode]>;
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker// movzbq and movzwq encodings for the disassembler
149*9880d681SAndroid Build Coastguard Workerlet hasSideEffects = 0 in {
150*9880d681SAndroid Build Coastguard Workerdef MOVZX64rr8 : RI<0xB6, MRMSrcReg, (outs GR64:$dst), (ins GR8:$src),
151*9880d681SAndroid Build Coastguard Worker                     "movz{bq|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX>,
152*9880d681SAndroid Build Coastguard Worker                     TB, Sched<[WriteALU]>;
153*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
154*9880d681SAndroid Build Coastguard Workerdef MOVZX64rm8 : RI<0xB6, MRMSrcMem, (outs GR64:$dst), (ins i8mem:$src),
155*9880d681SAndroid Build Coastguard Worker                     "movz{bq|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX>,
156*9880d681SAndroid Build Coastguard Worker                     TB, Sched<[WriteALULd]>;
157*9880d681SAndroid Build Coastguard Workerdef MOVZX64rr16 : RI<0xB7, MRMSrcReg, (outs GR64:$dst), (ins GR16:$src),
158*9880d681SAndroid Build Coastguard Worker                     "movz{wq|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX>,
159*9880d681SAndroid Build Coastguard Worker                     TB, Sched<[WriteALU]>;
160*9880d681SAndroid Build Coastguard Workerlet mayLoad = 1 in
161*9880d681SAndroid Build Coastguard Workerdef MOVZX64rm16 : RI<0xB7, MRMSrcMem, (outs GR64:$dst), (ins i16mem:$src),
162*9880d681SAndroid Build Coastguard Worker                     "movz{wq|x}\t{$src, $dst|$dst, $src}", [], IIC_MOVZX>,
163*9880d681SAndroid Build Coastguard Worker                     TB, Sched<[WriteALULd]>;
164*9880d681SAndroid Build Coastguard Worker}
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker// 64-bit zero-extension patterns use SUBREG_TO_REG and an operation writing a
167*9880d681SAndroid Build Coastguard Worker// 32-bit register.
168*9880d681SAndroid Build Coastguard Workerdef : Pat<(i64 (zext GR8:$src)),
169*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOVZX32rr8 GR8:$src), sub_32bit)>;
170*9880d681SAndroid Build Coastguard Workerdef : Pat<(zextloadi64i8 addr:$src),
171*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>;
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Workerdef : Pat<(i64 (zext GR16:$src)),
174*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16:$src), sub_32bit)>;
175*9880d681SAndroid Build Coastguard Workerdef : Pat<(zextloadi64i16 addr:$src),
176*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOVZX32rm16 addr:$src), sub_32bit)>;
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker// The preferred way to do 32-bit-to-64-bit zero extension on x86-64 is to use a
179*9880d681SAndroid Build Coastguard Worker// SUBREG_TO_REG to utilize implicit zero-extension, however this isn't possible
180*9880d681SAndroid Build Coastguard Worker// when the 32-bit value is defined by a truncate or is copied from something
181*9880d681SAndroid Build Coastguard Worker// where the high bits aren't necessarily all zero. In such cases, we fall back
182*9880d681SAndroid Build Coastguard Worker// to these explicit zext instructions.
183*9880d681SAndroid Build Coastguard Workerdef : Pat<(i64 (zext GR32:$src)),
184*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOV32rr GR32:$src), sub_32bit)>;
185*9880d681SAndroid Build Coastguard Workerdef : Pat<(i64 (zextloadi64i32 addr:$src)),
186*9880d681SAndroid Build Coastguard Worker          (SUBREG_TO_REG (i64 0), (MOV32rm addr:$src), sub_32bit)>;
187