1 //===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- tablegen -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file describes the integer arithmetic instructions in the M68k
11 /// architecture. Here is the current status of the file:
15 /// ADD [~] ADDA [~] ADDI [~] ADDQ [ ] ADDX [~]
16 /// CLR [ ] CMP [~] CMPA [~] CMPI [~] CMPM [ ]
17 /// CMP2 [ ] DIVS/DIVU [~] DIVSL/DIVUL [ ] EXT [~] EXTB [ ]
18 /// MULS/MULU [~] NEG [~] NEGX [~] SUB [~] SUBA [~]
19 /// SUBI [~] SUBQ [ ] SUBX [~]
23 /// [ ] - was not touched at all
24 /// [!] - requires extarnal stuff implemented
25 /// [~] - functional implementation
26 /// [X] - complete implementation
28 //===----------------------------------------------------------------------===//
30 //===----------------------------------------------------------------------===//
32 //===----------------------------------------------------------------------===//
33 class MxOpModeEncoding<bits<3> encoding> {
34 bits<3> Value = encoding;
38 def MxOpMode8_d_EA : MxOpModeEncoding<0b000>;
39 def MxOpMode16_d_EA : MxOpModeEncoding<0b001>;
40 def MxOpMode32_d_EA : MxOpModeEncoding<0b010>;
43 def MxOpMode8_EA_d : MxOpModeEncoding<0b100>;
44 def MxOpMode16_EA_d : MxOpModeEncoding<0b101>;
45 def MxOpMode32_EA_d : MxOpModeEncoding<0b110>;
48 def MxOpMode16_a_EA : MxOpModeEncoding<0b011>;
49 def MxOpMode32_a_EA : MxOpModeEncoding<0b111>;
52 //===----------------------------------------------------------------------===//
54 //===----------------------------------------------------------------------===//
57 let Constraints = "$src = $dst" in {
59 /// Encoding for Normal forms
60 /// ----------------------------------------------------
61 /// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
62 /// ----------------------------------------------------
63 /// | | | EFFECTIVE ADDRESS
64 /// x x x x | REG | OP MODE | MODE | REG
65 /// ----------------------------------------------------
67 // $reg, $ccr <- $reg op $reg
68 class MxBiArOp_R_RR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE,
70 : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd),
71 MN#"."#DST_TYPE.Prefix#"\t$opd, $dst",
72 [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> {
74 CMD, (operand "$dst", 3),
75 !cast<MxOpModeEncoding>("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value,
77 !eq(SRC_TYPE.RLet, "r") : (descend 0b00, (operand "$opd", 4)),
78 !eq(SRC_TYPE.RLet, "d") : (descend 0b000, (operand "$opd", 3))
83 /// This Op is similar to the one above except it uses reversed opmode, some
84 /// commands(e.g. eor) do not support dEA or rEA modes and require EAd for
85 /// register only operations.
86 /// NOTE when using dd commands it is irrelevant which opmode to use(as it seems)
87 /// but some opcodes support address register and some do not which creates this
89 class MxBiArOp_R_RR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
90 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
91 MN#"."#TYPE.Prefix#"\t$opd, $dst",
92 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> {
94 CMD, (operand "$opd", 3),
95 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
96 /*Destination can only be a data register*/
98 /*REGISTER*/(operand "$dst", 3));
102 class MxBiArOp_R_RM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT,
103 bits<4> CMD, MxEncMemOp SRC_ENC>
104 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd),
105 MN#"."#TYPE.Prefix#"\t$opd, $dst",
106 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> {
108 (descend CMD, (operand "$dst", 3),
109 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
115 /// Encoding for Immediate forms
116 /// ---------------------------------------------------
117 /// F E D C B A 9 8 | 7 6 | 5 4 3 | 2 1 0
118 /// ---------------------------------------------------
119 /// | | EFFECTIVE ADDRESS
120 /// x x x x x x x x | SIZE | MODE | REG
121 /// ---------------------------------------------------
122 /// 16-BIT WORD DATA | 8-BIT BYTE DATA
123 /// ---------------------------------------------------
125 /// ---------------------------------------------------
126 /// NOTE It is used to store an immediate to memory, imm-to-reg are handled with
129 // $reg <- $reg op $imm
130 class MxBiArOp_R_RI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
131 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
132 MN#"."#TYPE.Prefix#"\t$opd, $dst",
133 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
135 (descend CMD, (operand "$dst", 3),
136 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value,
137 MxEncAddrMode_i<"opd", TYPE.Size>.EA),
138 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
142 // Again, there are two ways to write an immediate to Dn register either dEA
143 // opmode or using *I encoding, and again some instructions also support address
144 // registers some do not.
145 class MxBiArOp_R_RI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
146 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
147 MN#"i."#TYPE.Prefix#"\t$opd, $dst",
148 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> {
150 (descend 0b0000, CMD,
151 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
152 // The destination cannot be address register, so it's always
153 // the MODE for data register direct mode.
155 /*REGISTER*/(operand "$dst", 3)),
156 // Source (i.e. immediate value) encoding
157 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement
162 let mayLoad = 1, mayStore = 1 in {
164 // FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for
165 // MxAdd to survive the match and subsequent mismatch.
166 class MxBiArOp_MR<string MN, MxType TYPE,
167 MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
168 : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd),
169 MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
171 (descend CMD, (operand "$opd", 3),
172 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value,
178 class MxBiArOp_MI<string MN, MxType TYPE,
179 MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC>
180 : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd),
181 MN#"."#TYPE.Prefix#"\t$opd, $dst", []> {
183 (descend 0b0000, CMD,
184 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
186 // Source (i.e. immediate value) encoding
187 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement,
188 // Destination encoding
192 } // mayLoad, mayStore
195 multiclass MxBiArOp_DF<string MN, SDNode NODE, bit isComm,
196 bits<4> CMD, bits<4> CMDI> {
198 foreach SZ = [8, 16, 32] in {
200 def NAME#SZ#"dk" : MxBiArOp_R_RM<MN, NODE,
201 !cast<MxType>("MxType"#SZ#"d"),
202 !cast<MxType>("MxType"#SZ).KOp,
203 !cast<MxType>("MxType"#SZ).KPat,
204 CMD, MxEncAddrMode_k<"opd">>;
206 def NAME#SZ#"dq" : MxBiArOp_R_RM<MN, NODE,
207 !cast<MxType>("MxType"#SZ#"d"),
208 !cast<MxType>("MxType"#SZ).QOp,
209 !cast<MxType>("MxType"#SZ).QPat,
210 CMD, MxEncAddrMode_q<"opd">>;
212 def NAME#SZ#"dp" : MxBiArOp_R_RM<MN, NODE,
213 !cast<MxType>("MxType"#SZ#"d"),
214 !cast<MxType>("MxType"#SZ).POp,
215 !cast<MxType>("MxType"#SZ).PPat,
216 CMD, MxEncAddrMode_p<"opd">>;
218 def NAME#SZ#"df" : MxBiArOp_R_RM<MN, NODE,
219 !cast<MxType>("MxType"#SZ#"d"),
220 !cast<MxType>("MxType"#SZ).FOp,
221 !cast<MxType>("MxType"#SZ).FPat,
222 CMD, MxEncAddrMode_f<"opd">>;
224 def NAME#SZ#"dj" : MxBiArOp_R_RM<MN, NODE,
225 !cast<MxType>("MxType"#SZ#"d"),
226 !cast<MxType>("MxType"#SZ).JOp,
227 !cast<MxType>("MxType"#SZ).JPat,
228 CMD, MxEncAddrMode_j<"opd">>;
230 def NAME#SZ#"di" : MxBiArOp_R_RI_xEA<MN, NODE,
231 !cast<MxType>("MxType"#SZ#"d"),
234 def NAME#SZ#"pd" : MxBiArOp_MR<MN,
235 !cast<MxType>("MxType"#SZ#"d"),
236 !cast<MxType>("MxType"#SZ).POp,
237 CMD, MxEncAddrMode_p<"dst">>;
239 def NAME#SZ#"fd" : MxBiArOp_MR<MN,
240 !cast<MxType>("MxType"#SZ#"d"),
241 !cast<MxType>("MxType"#SZ).FOp,
242 CMD, MxEncAddrMode_f<"dst">>;
244 def NAME#SZ#"jd" : MxBiArOp_MR<MN,
245 !cast<MxType>("MxType"#SZ#"d"),
246 !cast<MxType>("MxType"#SZ).JOp,
247 CMD, MxEncAddrMode_j<"dst">>;
249 def NAME#SZ#"pi" : MxBiArOp_MI<MN,
250 !cast<MxType>("MxType"#SZ),
251 !cast<MxType>("MxType"#SZ).POp,
252 CMDI, MxEncAddrMode_p<"dst">>;
254 def NAME#SZ#"fi" : MxBiArOp_MI<MN,
255 !cast<MxType>("MxType"#SZ),
256 !cast<MxType>("MxType"#SZ).FOp,
257 CMDI, MxEncAddrMode_f<"dst">>;
259 def NAME#SZ#"ji" : MxBiArOp_MI<MN,
260 !cast<MxType>("MxType"#SZ),
261 !cast<MxType>("MxType"#SZ).JOp,
262 CMDI, MxEncAddrMode_j<"dst">>;
264 let isCommutable = isComm in
265 def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA<MN, NODE,
266 !cast<MxType>("MxType"#SZ#"d"),
267 !cast<MxType>("MxType"#SZ#"d"),
271 foreach SZ = [16, 32] in
272 def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA<MN, NODE,
273 !cast<MxType>("MxType"#SZ#"d"),
274 !cast<MxType>("MxType"#SZ#"r"),
280 // These special snowflakes allowed to match address registers but since *A
281 // operations do not produce CCR we should not match them against Mx nodes that
283 let Pattern = [(null_frag)] in
284 multiclass MxBiArOp_AF<string MN, SDNode NODE, bits<4> CMD> {
286 def NAME#"32ak" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat,
287 CMD, MxEncAddrMode_k<"opd">>;
288 def NAME#"32aq" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat,
289 CMD, MxEncAddrMode_q<"opd">>;
290 def NAME#"32af" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat,
291 CMD, MxEncAddrMode_f<"opd">>;
292 def NAME#"32ap" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat,
293 CMD, MxEncAddrMode_p<"opd">>;
294 def NAME#"32aj" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat,
295 CMD, MxEncAddrMode_j<"opd">>;
296 def NAME#"32ab" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.BOp, MxType32.BPat,
297 CMD, MxEncAddrMode_abs<"opd", true>>;
298 def NAME#"32ai" : MxBiArOp_R_RI_xEA<MN, NODE, MxType32a, CMD>;
300 def NAME#"32ar" : MxBiArOp_R_RR_xEA<MN, NODE, MxType32a, MxType32r, CMD>;
304 // NOTE These naturally produce CCR
306 //===----------------------------------------------------------------------===//
308 //===----------------------------------------------------------------------===//
310 defm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>;
311 defm ADD : MxBiArOp_AF<"adda", MxAdd, 0xD>;
312 defm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>;
313 defm SUB : MxBiArOp_AF<"suba", MxSub, 0x9>;
315 // This pattern is used to enable the instruction selector to select ADD32ab
316 // for global values that are allocated in thread-local storage, i.e.:
317 // t8: i32 = ISD::ADD GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
319 // t8: i32,i8 = ADD32ab GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar>
320 def : Pat<(add MxARD32:$src, tglobaltlsaddr:$opd), (ADD32ab MxARD32:$src, MxAL32:$opd)>;
322 let Uses = [CCR], Defs = [CCR] in {
323 let Constraints = "$src = $dst" in {
325 /// Encoding for Extended forms
326 /// ------------------------------------------------------
327 /// F E D C | B A 9 | 8 | 7 6 | 5 4 | 3 | 2 1 0
328 /// ------------------------------------------------------
329 /// x x x x | REG Rx | 1 | SIZE | 0 0 | M | REG Ry
330 /// ------------------------------------------------------
333 /// M - address mode switch
335 // $reg, ccr <- $reg op $reg op ccr
336 class MxBiArOp_R_RRX<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
337 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
338 MN#"."#TYPE.Prefix#"\t$opd, $dst",
339 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> {
340 let Inst = (descend CMD,
341 // Destination register
345 !cond(!eq(TYPE.Size, 8): 0b00,
346 !eq(TYPE.Size, 16): 0b01,
347 !eq(TYPE.Size, 32): 0b10),
356 multiclass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> {
358 let isCommutable = isComm in {
359 foreach SZ = [8, 16, 32] in
360 def NAME#SZ#"dd" : MxBiArOp_R_RRX<MN, NODE, !cast<MxType>("MxType"#SZ#"d"), CMD>;
365 // NOTE These consume and produce CCR
366 defm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>;
367 defm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>;
370 //===----------------------------------------------------------------------===//
372 //===----------------------------------------------------------------------===//
374 defm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>;
375 defm OR : MxBiArOp_DF<"or", MxOr, 1, 0x8, 0x0>;
377 multiclass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> {
378 foreach SZ = [8, 16, 32] in {
379 let isCommutable = 1 in
380 def NAME#SZ#"dd" : MxBiArOp_R_RR_EAd<MN, NODE,
381 !cast<MxType>("MxType"#SZ#"d"),
384 def NAME#SZ#"di" : MxBiArOp_R_RI<MN, NODE,
385 !cast<MxType>("MxType"#SZ#"d"),
390 defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>;
393 //===----------------------------------------------------------------------===//
395 //===----------------------------------------------------------------------===//
397 let Defs = [CCR] in {
398 class MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE>
399 : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs),
400 "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs",
401 [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> {
402 let Inst = (descend 0b1011,
406 !cast<MxOpModeEncoding>("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value,
407 // MODE without last bit
409 // REGISTER prefixed by D/A bit
414 class MxCmp_RI<MxType TYPE>
415 : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg),
416 "cmpi."#TYPE.Prefix#"\t$imm, $reg",
417 [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> {
420 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
421 // The destination cannot be address register, so it's always
422 // the MODE for data register direct mode.
424 /*REGISTER*/(operand "$reg", 3)),
425 // Source (i.e. immediate value) encoding
426 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement
432 class MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
434 : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem),
435 "cmpi."#TYPE.Prefix#"\t$imm, $mem",
436 [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> {
439 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
441 // Source (i.e. immediate value) encoding
442 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
443 // Destination (i.e. memory operand) encoding
448 // FIXME: What about abs.W?
449 class MxCmp_BI<MxType TYPE>
450 : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs),
451 "cmpi."#TYPE.Prefix#"\t$imm, $abs",
452 [(set CCR, (MxCmp TYPE.IPat:$imm,
453 (load (i32 (MxWrapper tglobaladdr:$abs)))))]> {
454 defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>;
457 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
459 // Source (i.e. immediate value) encoding
460 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement,
461 // Destination (i.e. memory operand) encoding
462 AbsEncoding.Supplement
466 class MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
468 : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem),
469 "cmp."#TYPE.Prefix#"\t$mem, $reg",
470 [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> {
476 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_d_EA").Value,
483 } // let Defs = [CCR]
485 multiclass MMxCmp_RM<MxType TYPE> {
486 def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncAddrMode_k<"mem">>;
487 def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncAddrMode_q<"mem">>;
488 def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncAddrMode_p<"mem">>;
489 def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncAddrMode_f<"mem">>;
490 def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncAddrMode_j<"mem">>;
493 multiclass MMxCmp_MI<MxType TYPE> {
494 def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat,
495 MxEncAddrMode_k<"mem">>;
496 def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat,
497 MxEncAddrMode_q<"mem">>;
498 def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat,
499 MxEncAddrMode_p<"mem">>;
500 def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat,
501 MxEncAddrMode_f<"mem">>;
502 def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat,
503 MxEncAddrMode_j<"mem">>;
506 foreach S = [8, 16, 32] in {
507 def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>;
508 def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>;
511 def CMP8dd : MxCmp_RR<MxType8d>;
512 foreach S = [16, 32] in {
513 def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"),
514 !cast<MxType>("MxType"#S#"d")>;
518 defm CMP8d : MMxCmp_RM<MxType8d>;
519 defm CMP16d : MMxCmp_RM<MxType16d>;
520 defm CMP32d : MMxCmp_RM<MxType32d>;
523 defm CMP8 : MMxCmp_MI<MxType8d>;
524 defm CMP16 : MMxCmp_MI<MxType16d>;
525 defm CMP32 : MMxCmp_MI<MxType32d>;
528 //===----------------------------------------------------------------------===//
530 //===----------------------------------------------------------------------===//
532 /// ---------------------------------------------------
533 /// F E D C B A 9 | 8 7 6 | 5 4 3 | 2 1 0
534 /// ---------------------------------------------------
535 /// 0 1 0 0 1 0 0 | OPMODE | 0 0 0 | REG
536 /// ---------------------------------------------------
538 let Constraints = "$src = $dst" in
539 class MxExt<MxType TO, MxType FROM>
540 : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src),
541 "ext."#TO.Prefix#"\t$src", []> {
542 let Inst = (descend 0b0100100,
546 !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010,
548 !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011,
550 !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111
558 def EXT16 : MxExt<MxType16d, MxType8d>;
559 def EXT32 : MxExt<MxType32d, MxType16d>;
561 def : Pat<(sext_inreg i16:$src, i8), (EXT16 $src)>;
562 def : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>;
563 def : Pat<(sext_inreg i32:$src, i8),
564 (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>;
567 //===----------------------------------------------------------------------===//
569 //===----------------------------------------------------------------------===//
572 /// ----------------------------------------------------
573 /// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
574 /// ----------------------------------------------------
575 /// | | | EFFECTIVE ADDRESS
576 /// x x x x | REG | OP MODE | MODE | REG
577 /// ----------------------------------------------------
578 let Defs = [CCR] in {
579 let Constraints = "$src = $dst" in {
580 // $dreg <- $dreg op $dreg
581 class MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false,
582 MxOperand DST, MxOperand OPD>
583 : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
584 let Inst = (descend CMD,
587 !if(SIGNED, 0b111, 0b011),
588 /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)
592 // $dreg <- $dreg op $dreg
593 class MxDiMuOp_DD_Long<string MN, bits<10> CMD, bit SIGNED = false>
594 : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", []> {
597 /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)),
601 !if(SIGNED, 0b1, 0b0),
602 /*SIZE*/0b0, 0b0000000,
608 // $reg <- $reg op $imm
609 class MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false,
610 MxOperand DST, MxOperand OPD>
611 : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> {
612 // FIXME: Support immediates with different widths.
613 defvar ImmEnc = MxEncAddrMode_i<"opd", 16>;
618 !if(SIGNED, 0b111, 0b011), ImmEnc.EA),
625 multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> {
626 let isCommutable = isComm in {
627 def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>;
628 def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>;
631 def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>;
632 def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>;
635 defm DIV : MxDiMuOp<"div", 0x8>;
637 def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", 0x131, /*SIGNED*/true>;
638 def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", 0x131, /*SIGNED*/false>;
640 // This is used to cast immediates to 16-bits for operations which don't
641 // support smaller immediate sizes.
642 def as_i16imm : SDNodeXForm<imm, [{
643 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16);
647 def : Pat<(sdiv i8:$dst, i8:$opd),
649 (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)),
652 def : Pat<(udiv i8:$dst, i8:$opd),
654 (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)),
657 def : Pat<(srem i8:$dst, i8:$opd),
659 (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8),
662 def : Pat<(urem i8:$dst, i8:$opd),
664 (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8),
668 def : Pat<(sdiv i16:$dst, i16:$opd),
670 (SDIVd32d16 (MOVSXd32d16 $dst), $opd),
673 def : Pat<(udiv i16:$dst, i16:$opd),
675 (UDIVd32d16 (MOVZXd32d16 $dst), $opd),
678 def : Pat<(srem i16:$dst, i16:$opd),
680 (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8),
683 def : Pat<(urem i16:$dst, i16:$opd),
685 (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8),
690 def : Pat<(sdiv i32:$dst, i32:$opd), (SDIVd32d32 $dst, $opd)>;
692 def : Pat<(udiv i32:$dst, i32:$opd), (UDIVd32d32 $dst, $opd)>;
696 def : Pat<(sdiv i8:$dst, MximmSExt8:$opd),
698 (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)),
701 def : Pat<(udiv i8:$dst, MximmSExt8:$opd),
703 (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)),
706 def : Pat<(srem i8:$dst, MximmSExt8:$opd),
708 (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 8), 8),
711 def : Pat<(urem i8:$dst, MximmSExt8:$opd),
713 (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 8), 8),
717 def : Pat<(sdiv i16:$dst, MximmSExt16:$opd),
719 (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd),
722 def : Pat<(udiv i16:$dst, MximmSExt16:$opd),
724 (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd),
727 def : Pat<(srem i16:$dst, MximmSExt16:$opd),
729 (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8),
732 def : Pat<(urem i16:$dst, MximmSExt16:$opd),
734 (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8),
738 defm MUL : MxDiMuOp<"mul", 0xC, 1>;
740 def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", 0x130, /*SIGNED*/true>;
741 def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", 0x130, /*SIGNED*/false>;
744 def : Pat<(mul i16:$dst, i16:$opd),
746 (SMULd32d16 (MOVXd32d16 $dst), $opd),
749 def : Pat<(mulhs i16:$dst, i16:$opd),
751 (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
754 def : Pat<(mulhu i16:$dst, i16:$opd),
756 (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
759 def : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>;
763 def : Pat<(mul i16:$dst, MximmSExt16:$opd),
765 (SMULd32i16 (MOVXd32d16 $dst), imm:$opd),
768 def : Pat<(mulhs i16:$dst, MximmSExt16:$opd),
770 (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
773 def : Pat<(mulhu i16:$dst, MximmSExt16:$opd),
775 (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
779 //===----------------------------------------------------------------------===//
781 //===----------------------------------------------------------------------===//
783 /// ------------+------------+------+---------+---------
784 /// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0
785 /// ------------+------------+------+-------------------
786 /// | | | EFFECTIVE ADDRESS
787 /// 0 1 0 0 | x x x x | SIZE | MODE | REG
788 /// ------------+------------+------+---------+---------
789 let Defs = [CCR] in {
790 let Constraints = "$src = $dst" in {
792 class MxNeg_D<MxType TYPE>
793 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
794 "neg."#TYPE.Prefix#"\t$dst",
795 [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> {
796 let Inst = (descend 0b01000100,
797 /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
798 //MODE without last bit
800 //REGISTER prefixed by D/A bit
805 let Uses = [CCR] in {
806 class MxNegX_D<MxType TYPE>
807 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
808 "negx."#TYPE.Prefix#"\t$dst",
809 [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> {
810 let Inst = (descend 0b01000000,
811 /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value,
812 //MODE without last bit
814 //REGISTER prefixed by D/A bit
821 } // let Defs = [CCR]
823 foreach S = [8, 16, 32] in {
824 def NEG#S#d : MxNeg_D<!cast<MxType>("MxType"#S#"d")>;
825 def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>;
828 def : Pat<(MxSub 0, i8 :$src), (NEG8d MxDRD8 :$src)>;
829 def : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>;
830 def : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>;
831 // SExt of i1 values.
832 // Although we specify `ZeroOrOneBooleanContent` for boolean content,
833 // we're still adding an AND here as we don't know the origin of the i1 value.
834 def : Pat<(sext_inreg i8:$src, i1), (NEG8d (AND8di MxDRD8:$src, 1))>;
835 def : Pat<(sext_inreg i16:$src, i1), (NEG16d (AND16di MxDRD16:$src, 1))>;
836 def : Pat<(sext_inreg i32:$src, i1), (NEG32d (AND32di MxDRD32:$src, 1))>;
838 //===----------------------------------------------------------------------===//
840 //===----------------------------------------------------------------------===//
842 /// Basically the reason for this stuff is that add and addc share the same
843 /// operand types constraints for whatever reasons and I had to define a common
844 /// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc
846 /// NOTE On the other hand I see no reason why I cannot just drop explicit CCR
847 /// result. Anyway works for now, hopefully I will better understand how this stuff
848 /// is designed later
849 foreach N = ["add", "addc"] in {
852 def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
853 (ADD8dd MxDRD8 :$src, MxDRD8 :$opd)>;
854 def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
855 (ADD16dr MxXRD16:$src, MxDRD16:$opd)>;
856 def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
857 (ADD32dr MxXRD32:$src, MxDRD32:$opd)>;
860 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
861 (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>;
862 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
863 (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>;
864 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
865 (ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>;
868 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
869 (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>;
870 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
871 (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>;
872 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
873 (ADD32dp MxDRD32:$src, MxType32.POp:$opd)>;
875 // add (i,An,Xn), reg
876 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
877 (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>;
878 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
879 (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>;
880 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
881 (ADD32df MxDRD32:$src, MxType32.FOp:$opd)>;
884 def : Pat<(!cast<SDNode>(N) i8: $src, MximmSExt8:$opd),
885 (ADD8di MxDRD8 :$src, imm:$opd)>;
886 def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
887 (ADD16di MxDRD16:$src, imm:$opd)>;
889 // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot
890 // be used with data registers, here by adding complexity to a simple ADD32ri insts
891 // we make sure it will be selected over LEAp
892 let AddedComplexity = 15 in {
893 def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
894 (ADD32di MxDRD32:$src, imm:$opd)>;
895 } // AddedComplexity = 15
898 def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
900 (ADD8ji MxType8.JOp:$dst, imm:$opd)>;
901 def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
903 (ADD16ji MxType16.JOp:$dst, imm:$opd)>;
904 def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
906 (ADD32ji MxType32.JOp:$dst, imm:$opd)>;
908 } // foreach add, addc
910 def : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd MxDRD8 :$src, MxDRD8 :$opd)>;
911 def : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>;
912 def : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>;
916 foreach N = ["sub", "subc"] in {
919 def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
920 (SUB8dd MxDRD8 :$src, MxDRD8 :$opd)>;
921 def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
922 (SUB16dd MxDRD16:$src, MxDRD16:$opd)>;
923 def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
924 (SUB32dd MxDRD32:$src, MxDRD32:$opd)>;
928 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
929 (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>;
930 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
931 (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>;
932 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
933 (SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>;
936 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
937 (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>;
938 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
939 (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>;
940 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
941 (SUB32dp MxDRD32:$src, MxType32.POp:$opd)>;
943 // sub (i,An,Xn), reg
944 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
945 (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>;
946 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
947 (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>;
948 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
949 (SUB32df MxDRD32:$src, MxType32.FOp:$opd)>;
952 def : Pat<(!cast<SDNode>(N) i8 :$src, MximmSExt8 :$opd),
953 (SUB8di MxDRD8 :$src, imm:$opd)>;
954 def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
955 (SUB16di MxDRD16:$src, imm:$opd)>;
956 def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
957 (SUB32di MxDRD32:$src, imm:$opd)>;
960 def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
962 (SUB8ji MxType8.JOp:$dst, imm:$opd)>;
963 def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
965 (SUB16ji MxType16.JOp:$dst, imm:$opd)>;
966 def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
968 (SUB32ji MxType32.JOp:$dst, imm:$opd)>;
970 } // foreach sub, subx
972 def : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd MxDRD8 :$src, MxDRD8 :$opd)>;
973 def : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>;
974 def : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>;
976 multiclass BitwisePat<string INST, SDNode OP> {
978 def : Pat<(OP i8 :$src, i8 :$opd),
979 (!cast<MxInst>(INST#"8dd") MxDRD8 :$src, MxDRD8 :$opd)>;
980 def : Pat<(OP i16:$src, i16:$opd),
981 (!cast<MxInst>(INST#"16dd") MxDRD16:$src, MxDRD16:$opd)>;
982 def : Pat<(OP i32:$src, i32:$opd),
983 (!cast<MxInst>(INST#"32dd") MxDRD32:$src, MxDRD32:$opd)>;
985 def : Pat<(OP i8: $src, MximmSExt8 :$opd),
986 (!cast<MxInst>(INST#"8di") MxDRD8 :$src, imm:$opd)>;
987 def : Pat<(OP i16:$src, MximmSExt16:$opd),
988 (!cast<MxInst>(INST#"16di") MxDRD16:$src, imm:$opd)>;
989 def : Pat<(OP i32:$src, MximmSExt32:$opd),
990 (!cast<MxInst>(INST#"32di") MxDRD32:$src, imm:$opd)>;
993 defm : BitwisePat<"AND", and>;
994 defm : BitwisePat<"OR", or>;
995 defm : BitwisePat<"XOR", xor>;
997 //===----------------------------------------------------------------------===//
998 // Floating point arithmetic instruction
999 //===----------------------------------------------------------------------===//
1002 class MxFArithBase_FF<dag outs, dag ins, string asm, string rounding,
1004 : MxInst<outs, ins, asm, patterns> {
1005 let Uses = !if(!eq(rounding, ""), [FPC], []);
1007 let Predicates = !if(!eq(rounding, ""), [AtLeastM68881], [AtLeastM68040]);
1010 class MxFPOpModeSelector<string rounding, bits<7> single, bits<7> double,
1012 bits<7> Mode = !cond(!eq(rounding, "s"): single,
1013 !eq(rounding, "d"): double,
1014 !eq(rounding, ""): extended);
1017 //===----------------------------------------------------------------------===//
1018 // Unary floating point instruction
1019 //===----------------------------------------------------------------------===//
1021 class MxFUnary_FF<MxOpBundle Opnd, string rounding,
1022 string mnemonic, bits<7> opmode>
1023 : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src),
1024 "f"#rounding#mnemonic#".x\t$src, $dst", rounding, [(null_frag)]> {
1027 /*COPROCESSOR ID*/0b001,
1029 /*MODE+REGISTER*/0b000000),
1030 (descend 0b0, /* R/M */ 0b0, 0b0,
1031 /*SOURCE SPECIFIER*/
1032 (operand "$src", 3),
1034 (operand "$dst", 3),
1040 multiclass MxFUnaryOp<string mnemonic, bits<7> single, bits<7> double,
1042 foreach rounding = ["", "s", "d"] in {
1043 defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
1045 def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
1046 : MxFUnary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
1048 let isCodeGenOnly = 1 in
1049 foreach size = [32, 64] in
1050 def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
1051 : MxFUnary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
1052 rounding, mnemonic, opmode>;
1056 defm FABS : MxFUnaryOp<"abs", 0b1011000, 0b1011100, 0b0011000>;
1057 defm FNEG : MxFUnaryOp<"neg", 0b1011010, 0b1011110, 0b0011010>;
1059 //===----------------------------------------------------------------------===//
1060 // Binary floating point instruction
1061 //===----------------------------------------------------------------------===//
1063 let Constraints = "$src = $dst" in
1064 class MxFBinary_FF<MxOpBundle Opnd, string rounding,
1065 string mnemonic, bits<7> opmode>
1066 : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src, Opnd.Op:$opd),
1067 "f"#rounding#mnemonic#".x\t$opd, $dst", rounding, [(null_frag)]> {
1070 /*COPROCESSOR ID*/0b001,
1072 /*MODE+REGISTER*/0b000000),
1073 (descend 0b0, /* R/M */ 0b0, 0b0,
1074 /*SOURCE SPECIFIER*/
1075 (operand "$opd", 3),
1077 (operand "$dst", 3),
1083 multiclass MxFBinaryOp<string mnemonic, bits<7> single, bits<7> double,
1085 foreach rounding = ["", "s", "d"] in {
1086 defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode;
1088 def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp"
1089 : MxFBinary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>;
1091 let isCodeGenOnly = 1 in
1092 foreach size = [32, 64] in
1093 def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp"
1094 : MxFBinary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"),
1095 rounding, mnemonic, opmode>;
1099 defm FADD : MxFBinaryOp<"add", 0b1100010, 0b1100110, 0b0100010>;
1100 defm FSUB : MxFBinaryOp<"sub", 0b1101000, 0b1101100, 0b0101000>;
1101 defm FMUL : MxFBinaryOp<"mul", 0b1100011, 0b1100111, 0b0100011>;
1102 defm FDIV : MxFBinaryOp<"div", 0b1100000, 0b1100100, 0b0100000>;