1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
//===-- X86InstructionInfo.def - X86 Instruction Information ----*- C++ -*-===//
//
// This file describes all of the instructions that the X86 backend uses. It
// relys on an external 'I' macro being defined that takes the arguments
// specified below, and is used to make all of the information relevant to an
// instruction be in one place.
//
// Note that X86 Instructions always have the destination register listed as
// operand 0, unless it does not produce a value (in which case the TSFlags will
// include X86II::Void).
//
//===----------------------------------------------------------------------===//
// NOTE: No include guards desired
#ifndef I
#errror "Must define I macro before including X86/X86InstructionInfo.def!"
#endif
// Macro to handle the implicit register uses lists...
#ifndef IMPREGSLIST
#define IMPREGSLIST(NAME, ...)
#endif
// Implicit register usage info: O_ is for one register, T_ is for two registers
// NoIR means the instruction does not use implicit registers, in this form.
#define NoIR 0
IMPREGSLIST(O_AL , X86::AL , 0)
IMPREGSLIST(O_AH , X86::AH , 0)
IMPREGSLIST(O_CL , X86::CL , 0)
IMPREGSLIST(O_AX , X86::AX , 0)
IMPREGSLIST(O_DX , X86::DX , 0)
IMPREGSLIST(O_EAX, X86::EAX, 0)
IMPREGSLIST(O_EDX, X86::EDX, 0)
IMPREGSLIST(O_EBP, X86::EBP, 0)
IMPREGSLIST(T_AXDX , X86::AX , X86::DX , 0)
IMPREGSLIST(T_EAXEDX, X86::EAX, X86::EDX, 0)
IMPREGSLIST(C_CLOBBER, X86::EAX, X86::ECX, X86::EDX,
X86::FP0, X86::FP1, X86::FP2, X86::FP3,
X86::FP4, X86::FP5, X86::FP6, 0) // Callee clobber regs
// Floating point registers...
IMPREGSLIST(O_ST0, X86::ST0, 0)
//IMPREGSLIST(O_TOP, X86::TOP, 0)
#undef IMPREGSLIST
// Arguments to be passed into the I macro
// #1: Enum name - This ends up being the opcode symbol in the X86 namespace
// #2: Opcode name, as used by the gnu assembler
// #3: The base opcode for the instruction
// #4: Instruction Flags - This should be a field or'd together that contains
// constants from the TargetInstrInfo.h file.
// #5: Target Specific Flags - Another bitfield containing X86 specific flags
// that we are interested in for each instruction. These should be flags
// defined in X86InstrInfo.h in the X86II namespace.
// #6: Name of the implicit register uses list
// #7: Name of the implicit register definitions list
//
// The first instruction must always be the PHI instruction:
I(PHI , "phi", 0, 0, X86II::Pseudo , NoIR, NoIR)
// The second instruction must always be the noop instruction:
I(NOOP , "nop", 0x90, 0, X86II::RawFrm | X86II::Void, NoIR, NoIR) // nop
// This "instruction" is really an annotation which indicates that a specified
// amount of stack space is needed for an outgoing function call. This
// instruction is found before any of the stores to the argument slots, which
// use direct ESP references. If the frame pointer is eliminated, this
// instruction turns into a noop, but if the frame pointer is retained, this
// turns into a 'sub ESP, <amount>'.
//
I(ADJCALLSTACKDOWN, "adjcallstackdown", 0, 0, X86II::Pseudo, NoIR, NoIR)
// This instruction is used to mark readjustment of the stack after a function
// call. If the frame pointer is retained, this becomes a 'add ESP, <amount>'
// instruction after the call.
I(ADJCALLSTACKUP , "adjcallstackup" , 0, 0, X86II::Pseudo, NoIR, NoIR)
// Flow control instructions
I(RET , "ret", 0xC3, M_RET_FLAG | M_TERMINATOR_FLAG, X86II::RawFrm | X86II::Void, NoIR, NoIR) // ret
I(JMP , "jmp", 0xE9, M_BRANCH_FLAG | M_TERMINATOR_FLAG, X86II::RawFrm | X86II::Void, NoIR, NoIR) // jmp foo
I(JNE , "jne", 0x85, M_BRANCH_FLAG | M_TERMINATOR_FLAG, X86II::RawFrm | X86II::TB | X86II::Void, NoIR, NoIR) // jne foo
I(JE , "je", 0x84, M_BRANCH_FLAG | M_TERMINATOR_FLAG, X86II::RawFrm | X86II::TB | X86II::Void, NoIR, NoIR) // je foo
I(CALLpcrel32 , "call", 0xE8, M_CALL_FLAG, X86II::Void | X86II::RawFrm, NoIR, C_CLOBBER) // call pc+42
I(CALLr32 , "call", 0xFF, M_CALL_FLAG, X86II::Void | X86II::MRMS2r | X86II::Arg32,
NoIR, C_CLOBBER) // call [r32]
I(CALLm32 , "call", 0xFF, M_CALL_FLAG, X86II::Void | X86II::MRMS2m | X86II::Arg32,
NoIR, C_CLOBBER) // call [m32]
// Misc instructions
I(LEAVE , "leave", 0xC9, 0, X86II::RawFrm , O_EBP, O_EBP) // leave
I(BSWAPr32 , "bswap", 0xC8, M_2_ADDR_FLAG, X86II::AddRegFrm | X86II::Arg32 | X86II::TB , NoIR, NoIR) // R32 = bswap R32
I(XCHGrr8 , "xchg" , 0x86, 0, X86II::MRMDestReg | X86II::Arg8 , NoIR, NoIR) // xchg(R8, R8)
I(XCHGrr16 , "xchg" , 0x87, 0, X86II::MRMDestReg | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // xchg(R16, R16)
I(XCHGrr32 , "xchg" , 0x87, 0, X86II::MRMDestReg | X86II::Arg32 , NoIR, NoIR) // xchg(R32, R32)
I(LEAr16 , "lea" , 0x8D, 0, X86II::MRMSrcMem | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // R16 = lea [mem]
I(LEAr32 , "lea" , 0x8D, 0, X86II::MRMSrcMem | X86II::Arg32 , NoIR, NoIR) // R32 = lea [mem]
// Move instructions
I(MOVrr8 , "mov", 0x88, 0, X86II::MRMDestReg, NoIR, NoIR) // R8 = R8
I(MOVrr16 , "mov", 0x89, 0, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 = R16
I(MOVrr32 , "mov", 0x89, 0, X86II::MRMDestReg, NoIR, NoIR) // R32 = R32
I(MOVir8 , "mov", 0xB0, 0, X86II::AddRegFrm | X86II::Arg8, NoIR, NoIR) // R8 = imm8
I(MOVir16 , "mov", 0xB8, 0, X86II::AddRegFrm | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // R16 = imm16
I(MOVir32 , "mov", 0xB8, 0, X86II::AddRegFrm | X86II::Arg32, NoIR, NoIR) // R32 = imm32
I(MOVim8 , "mov", 0xC6, 0, X86II::MRMS0m | X86II::Arg8, NoIR, NoIR) // [mem] = imm8
I(MOVim16 , "mov", 0xC7, 0, X86II::MRMS0m | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // [mem] = imm16
I(MOVim32 , "mov", 0xC7, 0, X86II::MRMS0m | X86II::Arg32, NoIR, NoIR) // [mem] = imm32
I(MOVmr8 , "mov", 0x8A, 0, X86II::MRMSrcMem | X86II::Arg8, NoIR, NoIR) // R8 = [mem]
I(MOVmr16 , "mov", 0x8B, 0, X86II::MRMSrcMem | X86II::OpSize |
X86II::Arg16, NoIR, NoIR) // R16 = [mem]
I(MOVmr32 , "mov", 0x8B, 0, X86II::MRMSrcMem | X86II::Arg32, NoIR, NoIR)// R32 = [mem]
I(MOVrm8 , "mov", 0x88, 0, X86II::MRMDestMem | X86II::Void |
X86II::Arg8, NoIR, NoIR) // [mem] = R8
I(MOVrm16 , "mov", 0x89, 0, X86II::MRMDestMem | X86II::Void |
X86II::OpSize | X86II::Arg16, NoIR, NoIR) // [mem] = R16
I(MOVrm32 , "mov", 0x89, 0, X86II::MRMDestMem | X86II::Void |
X86II::Arg32, NoIR, NoIR) // [mem] = R32
// Arithmetic instructions
I(ADDrr8 , "add", 0x00, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 += R8
I(ADDrr16 , "add", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 += R16
I(ADDrr32 , "add", 0x01, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 += R32
I(ADDri32 , "add", 0x81, M_2_ADDR_FLAG, X86II::MRMS0r | X86II::Arg32, NoIR, NoIR) // R32 += imm32
I(ADCrr32 , "adc", 0x11, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::Arg32, NoIR, NoIR) // R32 += R32 + Carry
I(SUBrr8 , "sub", 0x28, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 -= R8
I(SUBrr16 , "sub", 0x29, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 -= R16
I(SUBrr32 , "sub", 0x29, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 -= R32
I(SUBri32 , "sub", 0x81, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg32, NoIR, NoIR) // R32 -= imm32
I(SBBrr32 , "sbb", 0x19, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::Arg32, NoIR, NoIR) // R32 -= R32 + Carry
I(MULr8 , "mul", 0xF6, 0, X86II::MRMS4r | X86II::Void, O_AL, O_AX) // AX = AL*R8
I(MULr16 , "mul", 0xF7, 0, X86II::MRMS4r | X86II::Void | // DX:AX= AX*R16
X86II::OpSize, O_AX, T_AXDX)
I(MULr32 , "mul", 0xF7, 0, X86II::MRMS4r | X86II::Void, O_EAX, T_EAXEDX) // ED:EA= EA*R32
// unsigned division/remainder
I(DIVr8 , "div", 0xF6, 0, X86II::MRMS6r | X86II::Void, O_AX, O_AX) // AX/r8= AL&AH
I(DIVr16 , "div", 0xF7, 0, X86II::MRMS6r | X86II::Void | // ED:EA/r16=AX&DX
X86II::OpSize, T_AXDX, T_AXDX)
I(DIVr32 , "div", 0xF7, 0, X86II::MRMS6r | X86II::Void, T_EAXEDX,
T_EAXEDX) // ED:EA/r32=EA&ED
// signed division/remainder
I(IDIVr8 , "idiv", 0xF6, 0, X86II::MRMS7r | X86II::Void, O_AX, O_AX) // AX/r8= AL&AH
I(IDIVr16 , "idiv", 0xF7, 0, X86II::MRMS7r | X86II::Void | // DA/r16=AX&DX
X86II::OpSize, T_AXDX, T_AXDX)
I(IDIVr32 , "idiv", 0xF7, 0, X86II::MRMS7r | X86II::Void, T_EAXEDX,
T_EAXEDX) // DA/r32=EAX&DX
// Logical operators
I(ANDrr8 , "and", 0x20, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 &= R8
I(ANDrr16 , "and", 0x21, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 &= R16
I(ANDrr32 , "and", 0x21, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 &= R32
I(ANDri32 , "and", 0x81, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg32, NoIR, NoIR) // R32 &= imm32
I(ORrr8 , "or", 0x08, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 |= R8
I(ORrr16 , "or", 0x09, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 |= R16
I(ORrr32 , "or", 0x09, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 |= R32
I(XORrr8 , "xor", 0x30, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 ^= R8
I(XORrr16 , "xor", 0x31, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // R16 ^= R16
I(XORrr32 , "xor", 0x31, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R32 ^= R32
// Shift instructions
I(SHLrr8 , "shl", 0xD2, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R8 <<= cl
I(SHLrr16 , "shl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::OpSize, O_CL, NoIR) // R16 <<= cl
I(SHLrr32 , "shl", 0xD3, M_2_ADDR_FLAG, X86II::MRMS4r, O_CL, NoIR) // R32 <<= cl
I(SHLir8 , "shl", 0xC0, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8, NoIR, NoIR) // R8 <<= imm8
I(SHLir16 , "shl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 <<= imm8
I(SHLir32 , "shl", 0xC1, M_2_ADDR_FLAG, X86II::MRMS4r | X86II::Arg8, NoIR, NoIR) // R32 <<= imm8
I(SHRrr8 , "shr", 0xD2, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R8 >>>= cl
I(SHRrr16 , "shr", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::OpSize, O_CL, NoIR) // R16 >>>= cl
I(SHRrr32 , "shr", 0xD3, M_2_ADDR_FLAG, X86II::MRMS5r, O_CL, NoIR) // R32 >>>= cl
I(SHRir8 , "shr", 0xC0, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8, NoIR, NoIR) // R8 >>>= imm8
I(SHRir16 , "shr", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 >>>= imm8
I(SHRir32 , "shr", 0xC1, M_2_ADDR_FLAG, X86II::MRMS5r | X86II::Arg8, NoIR, NoIR) // R32 >>>= imm8
I(SARrr8 , "sar", 0xD2, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R8 >>= cl
I(SARrr16 , "sar", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::OpSize, O_CL, NoIR) // R16 >>= cl
I(SARrr32 , "sar", 0xD3, M_2_ADDR_FLAG, X86II::MRMS7r, O_CL, NoIR) // R32 >>= cl
I(SARir8 , "sar", 0xC0, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // R8 >>= imm8
I(SARir16 , "sar", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8 | X86II::OpSize, NoIR, NoIR) // R16 >>= imm8
I(SARir32 , "sar", 0xC1, M_2_ADDR_FLAG, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // R32 >>= imm8
I(SHLDir32 , "shld", 0xA4, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::TB | X86II::Arg8, NoIR, NoIR) // R32 >>= R32,R32 imm8
I(SHLDrr32 , "shld", 0xA5, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::TB, O_CL, NoIR) // R32 >>= R32,R32 cl
I(SHRDir32 , "shrd", 0xAC, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::TB | X86II::Arg8, NoIR, NoIR) // R32 >>= R32,R32 imm8
I(SHRDrr32 , "shrd", 0xAD, M_2_ADDR_FLAG, X86II::MRMDestReg | X86II::TB, O_CL, NoIR) // R32 >>= R32,R32 cl
// Condition code ops, incl. set if equal/not equal/...
I(SAHF , "sahf", 0x9E, 0, X86II::RawFrm, O_AH, NoIR) // flags = AH
I(SETBr , "setb", 0x92, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = < unsign
I(SETAEr , "setae", 0x93, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = >= unsign
I(SETEr , "sete", 0x94, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = ==
I(SETNEr , "setne", 0x95, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = !=
I(SETBEr , "setbe", 0x96, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = <= unsign
I(SETAr , "seta", 0x97, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = > unsign
I(SETLr , "setl", 0x9C, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = < signed
I(SETGEr , "setge", 0x9D, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = >= signed
I(SETLEr , "setle", 0x9E, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = <= signed
I(SETGr , "setg", 0x9F, 0, X86II::TB | X86II::MRMS0r, NoIR, NoIR) // R8 = > signed
// Conditional moves. These are modelled as X = cmovXX Y, Z. Eventually
// register allocated to cmovXX XY, Z
I(CMOVErr16 , "cmove", 0x44, M_2_ADDR_FLAG, X86II::TB | X86II::OpSize | X86II::MRMSrcReg, NoIR, NoIR) // if ==, R16 = R16
// Integer comparisons
I(CMPrr8 , "cmpb", 0x38, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R8,R8
I(CMPrr16 , "cmpw", 0x39, 0, X86II::Void | X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // compare R16,R16
I(CMPrr32 , "cmpl", 0x39, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R32,R32
I(CMPri8 , "cmp", 0x80, 0, X86II::Void | X86II::MRMS7r | X86II::Arg8 , NoIR, NoIR) // compare R8, imm8
// Sign extenders (first 3 are good for DIV/IDIV; the others are more general)
I(CBW , "cbw", 0x98, 0, X86II::Void | X86II::RawFrm | X86II::OpSize, O_AL, O_AH) // AX = signext(AL)
I(CWD , "cwd", 0x99, 0, X86II::Void | X86II::RawFrm, O_AX, O_DX) // DX:AX = signext(AX)
I(CDQ , "cdq", 0x99, 0, X86II::Void | X86II::RawFrm, O_EAX, O_EDX) // EDX:EAX = signext(EAX)
I(MOVSXr16r8 , "movsx", 0xBE, 0, X86II::MRMSrcReg | X86II::TB | // R16 = signext(R8)
X86II::OpSize, NoIR, NoIR)
I(MOVSXr32r8 , "movsx", 0xBE, 0, X86II::MRMSrcReg | X86II::TB, NoIR, NoIR) // R32 = signext(R8)
I(MOVSXr32r16 , "movsx", 0xBF, 0, X86II::MRMSrcReg | X86II::TB, NoIR, NoIR) // R32 = signext(R16)
I(MOVZXr16r8 , "movzx", 0xB6, 0, X86II::MRMSrcReg | X86II::TB | // R16 = zeroext(R8)
X86II::OpSize, NoIR, NoIR)
I(MOVZXr32r8 , "movzx", 0xB6, 0, X86II::MRMSrcReg | X86II::TB, NoIR, NoIR) // R32 = zeroext(R8)
I(MOVZXr32r16 , "movzx", 0xB7, 0, X86II::MRMSrcReg | X86II::TB, NoIR, NoIR) // R32 = zeroext(R16)
//===----------------------------------------------------------------------===//
// Floating point support
//===----------------------------------------------------------------------===//
// FIXME: These need to indicate mod/ref sets for FP regs... & FP 'TOP'
// Floating point pseudo instructions...
I(FpMOV , "FMOV" , 0, M_PSEUDO_FLAG, X86II::ArgF80 | X86II::Pseudo | X86II::SpecialFP, NoIR, NoIR) // f1 = fmov f2
I(FpADD , "FADD" , 0, M_PSEUDO_FLAG, X86II::ArgF80 | X86II::Pseudo | X86II::TwoArgFP , NoIR, NoIR) // f1 = fadd f2, f3
I(FpSUB , "FSUB" , 0, M_PSEUDO_FLAG, X86II::ArgF80 | X86II::Pseudo | X86II::TwoArgFP , NoIR, NoIR) // f1 = fsub f2, f3
I(FpMUL , "FMUL" , 0, M_PSEUDO_FLAG, X86II::ArgF80 | X86II::Pseudo | X86II::TwoArgFP , NoIR, NoIR) // f1 = fmul f2, f3
I(FpDIV , "FDIV" , 0, M_PSEUDO_FLAG, X86II::ArgF80 | X86II::Pseudo | X86II::TwoArgFP , NoIR, NoIR) // f1 = fdiv f2, f3
I(FpUCOM , "FUCOM", 0, M_PSEUDO_FLAG, X86II::Void | X86II::ArgF80 | X86II::Pseudo | X86II::TwoArgFP , NoIR, NoIR) // FPSW = fucom f1, f2
I(FpGETRESULT , "FGETRESULT",0, M_PSEUDO_FLAG, X86II::Pseudo | X86II::SpecialFP, NoIR, NoIR) // FPR = ST(0)
I(FpSETRESULT , "FSETRESULT",0, M_PSEUDO_FLAG | M_TERMINATOR_FLAG, X86II::Void | X86II::Pseudo | X86II::SpecialFP, NoIR, NoIR) // ST(0) = FPR
// Floating point loads & stores... PREFIX ARGTYPE ENCODING FP INST TYPE REF MOD
I(FLDr32 , "fld32", 0xD9, 0, X86II::ArgF32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load float
I(FLDr64 , "fld64", 0xDD, 0, X86II::ArgF64 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load double
I(FLDr80 , "fld80", 0xDB, 0, X86II::ArgF80 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load extended
I(FLDrr , "fld" , 0xC0, 0, X86II::D9 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // push(ST(i))
I(FILDr16 , "fild16", 0xDF, 0, X86II::Arg16 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed short
I(FILDr32 , "fild32", 0xDB, 0, X86II::Arg32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed int
I(FILDr64 , "fild64", 0xDF, 0, X86II::Arg64 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load signed long
I(FSTr32 , "fst32", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store float
I(FSTr64 , "fst64", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store double
I(FSTPr32 , "fst32p", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS3m , NoIR, NoIR) // store float, pop
I(FSTPr64 , "fst64p", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS3m , NoIR, NoIR) // store double, pop
I(FSTPr80 , "fst80p", 0xDB, 0, X86II::Void | X86II::ArgF80 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store extended, pop
I(FSTrr , "fst" , 0xD0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0)
I(FSTPrr , "fstp" , 0xD8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0), pop
I(FISTr16 , "fist16", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed short
I(FISTr32 , "fist32", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed int
I(FISTPr16 , "fist16p", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS3m , NoIR, NoIR) // store short, pop
I(FISTPr32 , "fist32p", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS3m , NoIR, NoIR) // store int, pop
I(FISTPr64 , "fist64p", 0xDF, 0, X86II::Void | X86II::Arg64 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store long, pop
I(FXCH , "fxch" , 0xC8, 0, X86II::D9 | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // fxch ST(i), ST(0)
// Floating point constant loads...
I(FLD0 , "fld0" , 0xEE, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +0.0
I(FLD1 , "fld1" , 0xE8, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +1.0
// Binary arithmetic operations...
I(FADDST0r , "fadd_0", 0xC0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) + ST(i)
I(FADDrST0 , "fadd_i", 0xC0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0)
I(FADDPrST0 , "faddp_i", 0xC0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0), pop
I(FSUBRST0r , "fsubr_0" , 0xE8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) - ST(0)
I(FSUBrST0 , "fsub_i" , 0xE8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0)
I(FSUBPrST0 , "fsubp_i" , 0xE8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0), pop
I(FSUBST0r , "fsub_0" , 0xE0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) - ST(i)
I(FSUBRrST0 , "fsubr_i" , 0xE0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i)
I(FSUBRPrST0 , "fsubrp_i", 0xE0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i), pop
I(FMULST0r , "fmul_0", 0xC8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) * ST(i)
I(FMULrST0 , "fmul_i", 0xC8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0)
I(FMULPrST0 , "fmulp_i", 0xC8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0), pop
I(FDIVRST0r , "fdivr_0" , 0xF8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) / ST(0)
I(FDIVrST0 , "fdiv_i" , 0xF8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0)
I(FDIVPrST0 , "fdivp_i" , 0xF8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0), pop
I(FDIVST0r , "fdiv_0" , 0xF0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) / ST(i)
I(FDIVRrST0 , "fdivr_i" , 0xF0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i)
I(FDIVRPrST0 , "fdivrp_i", 0xF0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i), pop
// Floating point compares
I(FUCOMr , "fucom" , 0xE0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // FPSW = compare ST(0) with ST(i)
I(FUCOMPr , "fucomp" , 0xE8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // compare, pop
I(FUCOMPPr , "fucompp" , 0xE9, 0, X86II::DA | X86II::Void | X86II::RawFrm , NoIR, NoIR) // compare ST(0) with ST(1), pop, pop
// Floating point flag ops
I(FNSTSWr8 , "fnstsw" , 0xE0, 0, X86II::DF | X86II::Void | X86II::RawFrm , NoIR, O_AX) // AX = fp flags
I(FNSTCWm16 , "fnstcw" , 0xD9, 0, X86II::Void | X86II::Arg16 | X86II::MRMS7m , NoIR, NoIR) // [mem16] = X87 Control Word
I(FLDCWm16 , "fldcw" , 0xD9, 0, X86II::Void | X86II::Arg16 | X86II::MRMS5m , NoIR, NoIR) // X87 Control Word = [mem16]
// At this point, I is dead, so undefine the macro
#undef I
#undef NoIR
|