aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/X86/X86InstrInfo.td
blob: 1bd93a76e2ab53e9a594578166fe4c2be4cd345e (plain)
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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
//===- X86InstrInfo.td - Describe the X86 Instruction Set -------*- C++ -*-===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file describes the X86 instruction set, defining the instructions, and
// properties of the instructions which are needed for code generation, machine
// code emission, and analysis.
//
//===----------------------------------------------------------------------===//

// *mem - Operand definitions for the funky X86 addressing mode operands.
//
def i8mem : Operand<i8> {
  let NumMIOperands = 4;
  let PrintMethod = "printMemoryOperand";
}

def i16mem : Operand<i16> {
  let NumMIOperands = 4;
  let PrintMethod = "printMemoryOperand";
}

def i32mem : Operand<i32> {
  let NumMIOperands = 4;
  let PrintMethod = "printMemoryOperand";
}


// Format specifies the encoding used by the instruction.  This is part of the
// ad-hoc solution used to emit machine instruction encodings by our machine
// code emitter.
class Format<bits<5> val> {
  bits<5> Value = val;
}

def Pseudo     : Format<0>; def RawFrm     : Format<1>;
def AddRegFrm  : Format<2>; def MRMDestReg : Format<3>;
def MRMDestMem : Format<4>; def MRMSrcReg  : Format<5>;
def MRMSrcMem  : Format<6>;
def MRM0r  : Format<16>; def MRM1r  : Format<17>; def MRM2r  : Format<18>;
def MRM3r  : Format<19>; def MRM4r  : Format<20>; def MRM5r  : Format<21>;
def MRM6r  : Format<22>; def MRM7r  : Format<23>;
def MRM0m  : Format<24>; def MRM1m  : Format<25>; def MRM2m  : Format<26>;
def MRM3m  : Format<27>; def MRM4m  : Format<28>; def MRM5m  : Format<29>;
def MRM6m  : Format<30>; def MRM7m  : Format<31>;

// ImmType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
// machine code emitter.
class ImmType<bits<2> val> {
  bits<2> Value = val;
}
def NoImm  : ImmType<0>;
def Imm8   : ImmType<1>;
def Imm16  : ImmType<2>;
def Imm32  : ImmType<3>;

// MemType - This specifies the immediate type used by an instruction. This is
// part of the ad-hoc solution used to emit machine instruction encodings by our
// machine code emitter.
class MemType<bits<3> val> {
  bits<3> Value = val;
}
def NoMem  : MemType<0>;
def Mem8   : MemType<1>;
def Mem16  : MemType<2>;
def Mem32  : MemType<3>;
def Mem64  : MemType<4>;
def Mem80  : MemType<5>;
def Mem128 : MemType<6>;

// FPFormat - This specifies what form this FP instruction has.  This is used by
// the Floating-Point stackifier pass.
class FPFormat<bits<3> val> {
  bits<3> Value = val;
}
def NotFP      : FPFormat<0>;
def ZeroArgFP  : FPFormat<1>;
def OneArgFP   : FPFormat<2>;
def OneArgFPRW : FPFormat<3>;
def TwoArgFP   : FPFormat<4>;
def CompareFP  : FPFormat<5>;
def CondMovFP  : FPFormat<6>;
def SpecialFP  : FPFormat<7>;


class X86Inst<string nam, bits<8> opcod, Format f, MemType m, ImmType i> : Instruction {
  let Namespace = "X86";

  let Name = nam;
  bits<8> Opcode = opcod;
  Format Form = f;
  bits<5> FormBits = Form.Value;
  MemType MemT = m;
  bits<3> MemTypeBits = MemT.Value;
  ImmType ImmT = i;
  bits<2> ImmTypeBits = ImmT.Value;

  //
  // Attributes specific to X86 instructions...
  //
  bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?

  // Flag whether implicit register usage is printed after the instruction.
  bit printImplicitUsesAfter  = 0;

  bits<4> Prefix = 0;       // Which prefix byte does this inst have?
  FPFormat FPForm;          // What flavor of FP instruction is this?
  bits<3> FPFormBits = 0;
}

class Imp<list<Register> uses, list<Register> defs> {
  list<Register> Uses = uses;
  list<Register> Defs = defs;
}

// II - InstructionInfo - this will eventually replace the I class.
class II<dag ops, string AsmStr> {
  dag OperandList = ops;
  string AsmString = AsmStr;
}


// Prefix byte classes which are used to indicate to the ad-hoc machine code
// emitter that various prefix bytes are required.
class OpSize { bit hasOpSizePrefix = 1; }
class TB     { bits<4> Prefix = 1; }
class REP    { bits<4> Prefix = 2; }
class D8     { bits<4> Prefix = 3; }
class D9     { bits<4> Prefix = 4; }
class DA     { bits<4> Prefix = 5; }
class DB     { bits<4> Prefix = 6; }
class DC     { bits<4> Prefix = 7; }
class DD     { bits<4> Prefix = 8; }
class DE     { bits<4> Prefix = 9; }
class DF     { bits<4> Prefix = 10; }


//===----------------------------------------------------------------------===//
// Instruction templates...

class I<bits<8> o, Format f, dag ops, string asm> : X86Inst<"", o, f, NoMem, NoImm>, II<ops, asm>;

class Ii<bits<8> o, Format f, ImmType i> : X86Inst<"", o, f, NoMem, i>;
class Ii8 <bits<8> o, Format f, dag ops, string asm> : Ii<o, f, Imm8 >, II<ops, asm>;
class Ii16<bits<8> o, Format f, dag ops, string asm> : Ii<o, f, Imm16>, II<ops, asm>;
class Ii32<bits<8> o, Format f, dag ops, string asm> : Ii<o, f, Imm32>, II<ops, asm>;

class Im8i8 <string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem8 , Imm8 >;
class Im16i16<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem16, Imm16>;
class Im32i32<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm32>;

class Im16i8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem16, Imm8>;
class Im32i8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm8>;

//===----------------------------------------------------------------------===//
// Instruction list...
//

def PHI : I<0, Pseudo, (ops), "PHINODE">;        // PHI node.
def NOOP : I<0x90, RawFrm, (ops), "nop">; // nop

def ADJCALLSTACKDOWN : I<0, Pseudo, (ops), "#ADJCALLSTACKDOWN">;
def ADJCALLSTACKUP   : I<0, Pseudo, (ops), "#ADJCALLSTACKUP">;
def IMPLICIT_USE     : I<0, Pseudo, (ops), "#IMPLICIT_USE">;
def IMPLICIT_DEF     : I<0, Pseudo, (ops), "#IMPLICIT_DEF">;
let isTerminator = 1 in
  let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
    def FP_REG_KILL  : I<0, Pseudo, (ops), "#FP_REG_KILL">;

//===----------------------------------------------------------------------===//
//  Control Flow Instructions...
//

// Return instruction...
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
  def RET : I<0xC3, RawFrm, (ops), "ret">;

// All branches are RawFrm, Void, Branch, and Terminators
let isBranch = 1, isTerminator = 1 in
  class IBr<bits<8> opcode, dag ops, string asm> : I<opcode, RawFrm, ops, asm>;

let isBarrier = 1 in
  def JMP : IBr<0xE9, (ops i32imm:$dst), "jmp $dst">;
def JB  : IBr<0x82, (ops i32imm:$dst), "jb $dst">, TB;
def JAE : IBr<0x83, (ops i32imm:$dst), "jae $dst">, TB;
def JE  : IBr<0x84, (ops i32imm:$dst), "je $dst">, TB;
def JNE : IBr<0x85, (ops i32imm:$dst), "jne $dst">, TB;
def JBE : IBr<0x86, (ops i32imm:$dst), "jbe $dst">, TB;
def JA  : IBr<0x87, (ops i32imm:$dst), "ja $dst">, TB;
def JS  : IBr<0x88, (ops i32imm:$dst), "js $dst">, TB;
def JNS : IBr<0x89, (ops i32imm:$dst), "jns $dst">, TB;
def JL  : IBr<0x8C, (ops i32imm:$dst), "jl $dst">, TB;
def JGE : IBr<0x8D, (ops i32imm:$dst), "jge $dst">, TB;
def JLE : IBr<0x8E, (ops i32imm:$dst), "jle $dst">, TB;
def JG  : IBr<0x8F, (ops i32imm:$dst), "jg $dst">, TB;


//===----------------------------------------------------------------------===//
//  Call Instructions...
//
let isCall = 1 in
  // All calls clobber the non-callee saved registers...
  let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6] in {
    def CALLpcrel32 : X86Inst<"call", 0xE8, RawFrm, NoMem, NoImm>;  // FIXME: 'call' doesn't allow 'OFFSET'
    def CALL32r     : I<0xFF, MRM2r, (ops R32:$dst), "call $dst">;
    def CALL32m     : I<0xFF, MRM2m, (ops i32mem:$dst), "call $dst">;
  }

       
//===----------------------------------------------------------------------===//
//  Miscellaneous Instructions...
//
def LEAVE    : I<0xC9, RawFrm,
                 (ops), "leave">, Imp<[EBP,ESP],[EBP,ESP]>;
def POP32r   : I<0x58, AddRegFrm,
                 (ops R32:$reg), "pop $reg">, Imp<[ESP],[ESP]>;

let isTwoAddress = 1 in                                    // R32 = bswap R32
  def BSWAP32r : I<0xC8, AddRegFrm,
                   (ops R32:$dst, R32:$src), "bswap $dst">, TB;

def XCHG8rr  : I<0x86, MRMDestReg,                    // xchg R8, R8
                 (ops R8:$src1, R8:$src2), "xchg $src1, $src2">;
def XCHG16rr : I<0x87, MRMDestReg,                    // xchg R16, R16
                 (ops R16:$src1, R16:$src2), "xchg $src1, $src2">, OpSize;
def XCHG32rr : I<0x87, MRMDestReg,                    // xchg R32, R32
                 (ops R32:$src1, R32:$src2), "xchg $src1, $src2">;

def XCHG8mr  : I<0x86, MRMDestMem, (ops i8mem:$src1, R8:$src2), "xchg $src1, $src2">;
def XCHG16mr : I<0x87, MRMDestMem, (ops i16mem:$src1, R16:$src2), "xchg $src1, $src2">, OpSize;
def XCHG32mr : I<0x87, MRMDestMem, (ops i32mem:$src1, R32:$src2), "xchg $src1, $src2">;
def XCHG8rm  : I<0x86, MRMSrcMem , (ops R8:$src1, i8mem:$src2), "xchg $src1, $src2">;
def XCHG16rm : I<0x87, MRMSrcMem , (ops R16:$src1, i16mem:$src2), "xchg $src1, $src2">, OpSize;
def XCHG32rm : I<0x87, MRMSrcMem , (ops R32:$src1, i32mem:$src2), "xchg $src1, $src2">;

def LEA16r   : I<0x8D, MRMSrcMem, (ops R16:$dst, i32mem:$src), "lea $dst, $src">, OpSize;
def LEA32r   : I<0x8D, MRMSrcMem, (ops R32:$dst, i32mem:$src), "lea $dst, $src">;


def REP_MOVSB : I<0xA4, RawFrm, (ops), "rep movsb">,
                Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP;
def REP_MOVSW : I<0xA5, RawFrm, (ops), "rep movsw">,
                Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP, OpSize;
def REP_MOVSD : I<0xA5, RawFrm, (ops), "rep movsd">,
                Imp<[ECX,EDI,ESI], [ECX,EDI,ESI]>, REP;

def REP_STOSB : I<0xAA, RawFrm, (ops), "rep stosb">,
                Imp<[AL,ECX,EDI], [ECX,EDI]>, REP;
def REP_STOSW : I<0xAB, RawFrm, (ops), "rep stosw">,
                Imp<[AX,ECX,EDI], [ECX,EDI]>, REP, OpSize;
def REP_STOSD : I<0xAB, RawFrm, (ops), "rep stosd">,
                Imp<[EAX,ECX,EDI], [ECX,EDI]>, REP;


//===----------------------------------------------------------------------===//
//  Input/Output Instructions...
//
def IN8rr  : I<0xEC, RawFrm, (ops),
               "in %AL, %DX">,  Imp<[DX], [AL]>;
def IN16rr : I<0xED, RawFrm, (ops),
               "in %AX, %DX">,  Imp<[DX], [AX]>, OpSize;
def IN32rr : I<0xED, RawFrm, (ops),
               "in %EAX, %DX">, Imp<[DX],[EAX]>;

def IN8ri  : Ii16<0xE4, RawFrm, (ops i16imm:$port),
                  "in %AL, $port">,  Imp<[], [AL]>;
def IN16ri : Ii16<0xE5, RawFrm, (ops i16imm:$port),
                  "in %AX, $port">,  Imp<[], [AX]>, OpSize;
def IN32ri : Ii16<0xE5, RawFrm, (ops i16imm:$port),
                  "in %EAX, $port">, Imp<[],[EAX]>;

def OUT8rr  : I<0xEE, RawFrm, (ops),
                "out %DX, %AL">,  Imp<[DX,  AL], []>;
def OUT16rr : I<0xEF, RawFrm, (ops),
                "out %DX, %AX">,  Imp<[DX,  AX], []>, OpSize;
def OUT32rr : I<0xEF, RawFrm, (ops),
                "out %DX, %EAX">, Imp<[DX, EAX], []>;

def OUT8ir  : Ii16<0xE6, RawFrm, (ops i16imm:$port),
                   "out $port, %AL">, Imp<[AL], []>;
def OUT16ir : Ii16<0xE7, RawFrm, (ops i16imm:$port),
                   "out $port, %AX">, Imp<[AX], []>, OpSize;
def OUT32ir : Ii16<0xE7, RawFrm, (ops i16imm:$port),
                   "out $port, %EAX">, Imp<[EAX], []>;

//===----------------------------------------------------------------------===//
//  Move Instructions...
//
def MOV8rr  : I<0x88, MRMDestReg, (ops R8 :$dst, R8 :$src), "mov $dst, $src">;
def MOV16rr : I<0x89, MRMDestReg, (ops R16:$dst, R16:$src), "mov $dst, $src">, OpSize;
def MOV32rr : I<0x89, MRMDestReg, (ops R32:$dst, R32:$src), "mov $dst, $src">;
def MOV8ri  : Ii8 <0xB0, AddRegFrm, (ops R8 :$dst, i8imm :$src), "mov $dst, $src">;
def MOV16ri : Ii16<0xB8, AddRegFrm, (ops R16:$dst, i16imm:$src), "mov $dst, $src">, OpSize;
def MOV32ri : Ii32<0xB8, AddRegFrm, (ops R32:$dst, i32imm:$src), "mov $dst, $src">;
def MOV8mi  : Ii8 <0xC6, MRM0m, (ops i8mem :$dst, i8imm :$src), "mov $dst, $src">;
def MOV16mi : Ii16<0xC7, MRM0m, (ops i16mem:$dst, i16imm:$src), "mov $dst, $src">, OpSize;
def MOV32mi : Ii32<0xC7, MRM0m, (ops i32mem:$dst, i32imm:$src), "mov $dst, $src">;

def MOV8rm  : I<0x8A, MRMSrcMem, (ops R8 :$dst, i8mem :$src), "mov $dst, $src">;
def MOV16rm : I<0x8B, MRMSrcMem, (ops R16:$dst, i16mem:$src), "mov $dst, $src">, OpSize;
def MOV32rm : I<0x8B, MRMSrcMem, (ops R32:$dst, i32mem:$src), "mov $dst, $src">;

def MOV8mr  : I<0x88, MRMDestMem, (ops i8mem :$dst, R8 :$src), "mov $dst, $src">;
def MOV16mr : I<0x89, MRMDestMem, (ops i16mem:$dst, R16:$src), "mov $dst, $src">, OpSize;
def MOV32mr : I<0x89, MRMDestMem, (ops i32mem:$dst, R32:$src), "mov $dst, $src">;

//===----------------------------------------------------------------------===//
//  Fixed-Register Multiplication and Division Instructions...
//

// Extra precision multiplication
def MUL8r  : I<0xF6, MRM4r, (ops R8:$src), "mul $src">,
             Imp<[AL],[AX]>;               // AL,AH = AL*R8
def MUL16r : I<0xF7, MRM4r, (ops R16:$src), "mul $src">,
             Imp<[AX],[AX,DX]>, OpSize;    // AX,DX = AX*R16
def MUL32r : I<0xF7, MRM4r, (ops R32:$src), "mul $src">,
             Imp<[EAX],[EAX,EDX]>;         // EAX,EDX = EAX*R32
def MUL8m  : I<0xF6, MRM4m, (ops i8mem :$src),
               "mul $src">, Imp<[AL],[AX]>;               // AL,AH = AL*[mem8]
def MUL16m : I<0xF7, MRM4m, (ops i16mem:$src),
               "mul $src">, Imp<[AX],[AX,DX]>, OpSize;    // AX,DX = AX*[mem16]
def MUL32m : I<0xF7, MRM4m, (ops i32mem:$src),
               "mul $src">, Imp<[EAX],[EAX,EDX]>;         // EAX,EDX = EAX*[mem32]

// unsigned division/remainder
def DIV8r  : I<0xF6, MRM6r, (ops R8:$src), "div $src">,
             Imp<[AX],[AX]>;                                         // AX/r8 = AL,AH
def DIV16r : I<0xF7, MRM6r, (ops R16:$src), "div $src">,
             Imp<[AX,DX],[AX,DX]>, OpSize;                           // DX:AX/r16 = AX,DX
def DIV32r : I<0xF7, MRM6r, (ops R32:$src), "div $src">,
             Imp<[EAX,EDX],[EAX,EDX]>;                               // EDX:EAX/r32 = EAX,EDX
def DIV8m  : I<0xF6, MRM6m, (ops i8mem:$src), "div $src">, Imp<[AX],[AX]>;               // AX/[mem8] = AL,AH
def DIV16m : I<0xF7, MRM6m, (ops i16mem:$src), "div $src">, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX
def DIV32m : I<0xF7, MRM6m, (ops i32mem:$src), "div $src">, Imp<[EAX,EDX],[EAX,EDX]>;     // EDX:EAX/[mem32] = EAX,EDX

// Signed division/remainder.
def IDIV8r : I<0xF6, MRM7r, (ops R8:$src), "idiv $src">,
             Imp<[AX],[AX]>;               // AX/r8 = AL,AH
def IDIV16r: I<0xF7, MRM7r, (ops R16:$src), "idiv $src">,
             Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/r16 = AX,DX
def IDIV32r: I<0xF7, MRM7r, (ops R32:$src), "idiv $src">,
             Imp<[EAX,EDX],[EAX,EDX]>;     // EDX:EAX/r32 = EAX,EDX
def IDIV8m : I<0xF6, MRM7m, (ops i8mem:$src), "idiv $src">, Imp<[AX],[AX]>;               // AX/[mem8] = AL,AH
def IDIV16m: I<0xF7, MRM7m, (ops i16mem:$src), "idiv $src">, Imp<[AX,DX],[AX,DX]>, OpSize; // DX:AX/[mem16] = AX,DX
def IDIV32m: I<0xF7, MRM7m, (ops i32mem:$src), "idiv $src">, Imp<[EAX,EDX],[EAX,EDX]>;     // EDX:EAX/[mem32] = EAX,EDX

// Sign-extenders for division.
def CBW : I<0x98, RawFrm, (ops), "cbw">, Imp<[AL],[AH]>;   // AX = signext(AL)
def CWD : I<0x99, RawFrm, (ops), "cwd">, Imp<[AX],[DX]>;   // DX:AX = signext(AX)
def CDQ : I<0x99, RawFrm, (ops), "cdq">, Imp<[EAX],[EDX]>; // EDX:EAX = signext(EAX)
          

//===----------------------------------------------------------------------===//
//  Two address Instructions...
//
let isTwoAddress = 1 in {

// Conditional moves
def CMOVB16rr : I<0x42, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovb $dst, $src2">, TB, OpSize;                // if <u, R16 = R16
def CMOVB16rm : I<0x42, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovb $dst, $src2">, TB, OpSize;                // if <u, R16 = [mem16]
def CMOVB32rr : I<0x42, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovb $dst, $src2">, TB;                        // if <u, R32 = R32
def CMOVB32rm : I<0x42, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovb $dst, $src2">, TB;                        // if <u, R32 = [mem32]

def CMOVAE16rr: I<0x43, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovae $dst, $src2">, TB, OpSize;               // if >=u, R16 = R16
def CMOVAE16rm: I<0x43, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovae $dst, $src2">, TB, OpSize;               // if >=u, R16 = [mem16]
def CMOVAE32rr: I<0x43, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovae $dst, $src2">, TB;                       // if >=u, R32 = R32
def CMOVAE32rm: I<0x43, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovae $dst, $src2">, TB;                       // if >=u, R32 = [mem32]

def CMOVE16rr : I<0x44, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmove $dst, $src2">, TB, OpSize;                // if ==, R16 = R16
def CMOVE16rm : I<0x44, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmove $dst, $src2">, TB, OpSize;                // if ==, R16 = [mem16]
def CMOVE32rr : I<0x44, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmove $dst, $src2">, TB;                        // if ==, R32 = R32
def CMOVE32rm : I<0x44, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmove $dst, $src2">, TB;                        // if ==, R32 = [mem32]

def CMOVNE16rr: I<0x45, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovne $dst, $src2">, TB, OpSize;               // if !=, R16 = R16
def CMOVNE16rm: I<0x45, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovne $dst, $src2">, TB, OpSize;        // if !=, R16 = [mem16]
def CMOVNE32rr: I<0x45, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovne $dst, $src2">, TB;                       // if !=, R32 = R32
def CMOVNE32rm: I<0x45, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovne $dst, $src2">, TB;                // if !=, R32 = [mem32]

def CMOVBE16rr: I<0x46, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovbe $dst, $src2">, TB, OpSize;                    // if <=u, R16 = R16
def CMOVBE16rm: I<0x46, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovbe $dst, $src2">, TB, OpSize;        // if <=u, R16 = [mem16]
def CMOVBE32rr: I<0x46, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovbe $dst, $src2">, TB;                       // if <=u, R32 = R32
def CMOVBE32rm: I<0x46, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovbe $dst, $src2">, TB;                // if <=u, R32 = [mem32]

def CMOVA16rr : I<0x47, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmova $dst, $src2">, TB, OpSize;                // if >u, R16 = R16
def CMOVA16rm : I<0x47, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmova $dst, $src2">, TB, OpSize;                // if >u, R16 = [mem16]
def CMOVA32rr : I<0x47, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmova $dst, $src2">, TB;                        // if >u, R32 = R32
def CMOVA32rm : I<0x47, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmova $dst, $src2">, TB;                        // if >u, R32 = [mem32]

def CMOVS16rr : I<0x48, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovs $dst, $src2">, TB, OpSize;                // if signed, R16 = R16
def CMOVS16rm : I<0x48, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovs $dst, $src2">, TB, OpSize;                // if signed, R16 = [mem16]
def CMOVS32rr : I<0x48, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovs $dst, $src2">, TB;                        // if signed, R32 = R32
def CMOVS32rm : I<0x48, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovs $dst, $src2">, TB;                        // if signed, R32 = [mem32]

def CMOVNS16rr: I<0x49, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovns $dst, $src2">, TB, OpSize;               // if !signed, R16 = R16
def CMOVNS16rm: I<0x49, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovns $dst, $src2">, TB, OpSize;                // if !signed, R16 = [mem16]
def CMOVNS32rr: I<0x49, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovns $dst, $src2">, TB;                       // if !signed, R32 = R32
def CMOVNS32rm: I<0x49, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovns $dst, $src2">, TB;                        // if !signed, R32 = [mem32]

def CMOVL16rr : I<0x4C, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovl $dst, $src2">, TB, OpSize;                // if <s, R16 = R16
def CMOVL16rm : I<0x4C, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovl $dst, $src2">, TB, OpSize;                // if <s, R16 = [mem16]
def CMOVL32rr : I<0x4C, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovl $dst, $src2">, TB;                        // if <s, R32 = R32
def CMOVL32rm : I<0x4C, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovl $dst, $src2">, TB;                        // if <s, R32 = [mem32]

def CMOVGE16rr: I<0x4D, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovge $dst, $src2">, TB, OpSize;               // if >=s, R16 = R16
def CMOVGE16rm: I<0x4D, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovge $dst, $src2">, TB, OpSize;               // if >=s, R16 = [mem16]
def CMOVGE32rr: I<0x4D, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovge $dst, $src2">, TB;                       // if >=s, R32 = R32
def CMOVGE32rm: I<0x4D, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovge $dst, $src2">, TB;                       // if >=s, R32 = [mem32]

def CMOVLE16rr: I<0x4E, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovle $dst, $src2">, TB, OpSize;               // if <=s, R16 = R16
def CMOVLE16rm: I<0x4E, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovle $dst, $src2">, TB, OpSize;               // if <=s, R16 = [mem16]
def CMOVLE32rr: I<0x4E, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovle $dst, $src2">, TB;                       // if <=s, R32 = R32
def CMOVLE32rm: I<0x4E, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovle $dst, $src2">, TB;                       // if <=s, R32 = [mem32]

def CMOVG16rr : I<0x4F, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
                  "cmovg $dst, $src2">, TB, OpSize;                // if >s, R16 = R16
def CMOVG16rm : I<0x4F, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                  "cmovg $dst, $src2">, TB, OpSize;                // if >s, R16 = [mem16]
def CMOVG32rr : I<0x4F, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "cmovg $dst, $src2">, TB;                        // if >s, R32 = R32
def CMOVG32rm : I<0x4F, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                  "cmovg $dst, $src2">, TB;                        // if >s, R32 = [mem32]

// unary instructions
def NEG8r  : I<0xF6, MRM3r, (ops R8 :$dst, R8 :$src), "neg $dst">;
def NEG16r : I<0xF7, MRM3r, (ops R16:$dst, R16:$src), "neg $dst">, OpSize;
def NEG32r : I<0xF7, MRM3r, (ops R32:$dst, R32:$src), "neg $dst">;
let isTwoAddress = 0 in {
  def NEG8m  : I<0xF6, MRM3m, (ops i8mem :$dst), "neg $dst">;
  def NEG16m : I<0xF7, MRM3m, (ops i16mem:$dst), "neg $dst">, OpSize;
  def NEG32m : I<0xF7, MRM3m, (ops i32mem:$dst), "neg $dst">;
}

def NOT8r  : I<0xF6, MRM2r, (ops R8 :$dst, R8 :$src), "not $dst">;
def NOT16r : I<0xF7, MRM2r, (ops R16:$dst, R16:$src), "not $dst">, OpSize;
def NOT32r : I<0xF7, MRM2r, (ops R32:$dst, R32:$src), "not $dst">;
let isTwoAddress = 0 in {
  def NOT8m  : I<0xF6, MRM2m, (ops i8mem :$dst), "not $dst">;
  def NOT16m : I<0xF7, MRM2m, (ops i16mem:$dst), "not $dst">, OpSize;
  def NOT32m : I<0xF7, MRM2m, (ops i32mem:$dst), "not $dst">;
}

def INC8r  : I<0xFE, MRM0r, (ops R8 :$dst, R8 :$src), "inc $dst">;
def INC16r : I<0xFF, MRM0r, (ops R16:$dst, R16:$src), "inc $dst">, OpSize;
def INC32r : I<0xFF, MRM0r, (ops R32:$dst, R32:$src), "inc $dst">;
let isTwoAddress = 0 in {
  def INC8m  : I<0xFE, MRM0m, (ops i8mem :$dst), "inc $dst">;
  def INC16m : I<0xFF, MRM0m, (ops i16mem:$dst), "inc $dst">, OpSize;
  def INC32m : I<0xFF, MRM0m, (ops i32mem:$dst), "inc $dst">;
}

def DEC8r  : I<0xFE, MRM1r, (ops R8 :$dst, R8 :$src), "dec $dst">;
def DEC16r : I<0xFF, MRM1r, (ops R16:$dst, R16:$src), "dec $dst">, OpSize;
def DEC32r : I<0xFF, MRM1r, (ops R32:$dst, R32:$src), "dec $dst">;

let isTwoAddress = 0 in {
  def DEC8m  : I<0xFE, MRM1m, (ops i8mem :$dst), "dec $dst">;
  def DEC16m : I<0xFF, MRM1m, (ops i16mem:$dst), "dec $dst">, OpSize;
  def DEC32m : I<0xFF, MRM1m, (ops i32mem:$dst), "dec $dst">;
}

// Logical operators...
def AND8rr   : I<0x20, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2), "and $dst, $src2">;
def AND16rr  : I<0x21, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), "and $dst, $src2">, OpSize;
def AND32rr  : I<0x21, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), "and $dst, $src2">;

let isTwoAddress = 0 in {
  def AND8mr   : I<0x20, MRMDestMem, (ops i8mem :$dst, R8 :$src), "and $dst, $src">;
  def AND16mr  : I<0x21, MRMDestMem, (ops i16mem:$dst, R16:$src), "and $dst, $src">, OpSize;
  def AND32mr  : I<0x21, MRMDestMem, (ops i32mem:$dst, R32:$src), "and $dst, $src">;
}

def AND8rm   : I<0x22, MRMSrcMem , (ops R8 :$dst, R8 :$src1, i8mem :$src2), "and $dst, $src2">;
def AND16rm  : I<0x23, MRMSrcMem , (ops R16:$dst, R16:$src1, i16mem:$src2), "and $dst, $src2">, OpSize;
def AND32rm  : I<0x23, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2), "and $dst, $src2">;

def AND8ri   : Ii8 <0x80, MRM4r, (ops R8 :$dst, R8 :$src1, i8imm :$src2),
                    "and $dst, $src2">;
def AND16ri  : Ii16<0x81, MRM4r, (ops R16:$dst, R16:$src1, i16imm:$src2),
                    "and $dst, $src2">, OpSize;
def AND32ri  : Ii32<0x81, MRM4r, (ops R32:$dst, R32:$src1, i32imm:$src2),
                    "and $dst, $src2">;
def AND8mi   : Im8i8  <"and", 0x80, MRM4m    >;            // [mem8]  &= imm8
def AND16mi  : Im16i16<"and", 0x81, MRM4m    >, OpSize;    // [mem16] &= imm16
def AND32mi  : Im32i32<"and", 0x81, MRM4m    >;            // [mem32] &= imm32

def AND16ri8 : Ii8<0x83, MRM4r, (ops R16:$dst, R16:$src1, i8imm:$src2),
                   "and $dst, $src2" >, OpSize;
def AND32ri8 : Ii8<0x83, MRM4r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "and $dst, $src2">;
def AND16mi8 : Im16i8<"and", 0x83, MRM4m     >, OpSize;    // [mem16] &= imm8
def AND32mi8 : Im32i8<"and", 0x83, MRM4m     >;            // [mem32] &= imm8


def OR8rr    : I<0x08, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
                "or $dst, $src2">;
def OR16rr   : I<0x09, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
                 "or $dst, $src2">, OpSize;
def OR32rr   : I<0x09, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
                 "or $dst, $src2">;
let isTwoAddress = 0 in {
  def OR8mr  : I<0x08, MRMDestMem, (ops i8mem:$dst, R8:$src),
                 "or $dst, $src">;
  def OR16mr : I<0x09, MRMDestMem, (ops i16mem:$dst, R16:$src),
                 "or $dst, $src">, OpSize;
  def OR32mr : I<0x09, MRMDestMem, (ops i32mem:$dst, R32:$src),
                 "or $dst, $src">;
}
def OR8rm    : I<0x0A, MRMSrcMem , (ops R8 :$dst, R8 :$src1, i8mem :$src2),
                 "or $dst, $src2">;
def OR16rm   : I<0x0B, MRMSrcMem , (ops R16:$dst, R16:$src1, i16mem:$src2),
                 "or $dst, $src2">, OpSize;
def OR32rm   : I<0x0B, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2),
                 "or $dst, $src2">;

def OR8ri    : Ii8 <0x80, MRM1r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
                    "or $dst, $src2">;
def OR16ri   : Ii16<0x81, MRM1r, (ops R16:$dst, R16:$src1, i16imm:$src2),
                    "or $dst, $src2">, OpSize;
def OR32ri   : Ii32<0x81, MRM1r, (ops R32:$dst, R32:$src1, i32imm:$src2),
                    "or $dst, $src2">;
let isTwoAddress = 0 in {
  def OR8mi    : Im8i8  <"or" , 0x80, MRM1m>;            // [mem8]  |= imm8
  def OR16mi   : Im16i16<"or" , 0x81, MRM1m>, OpSize;    // [mem16] |= imm16
  def OR32mi   : Im32i32<"or" , 0x81, MRM1m>;            // [mem32] |= imm32
}

def OR16ri8  : Ii8<0x83, MRM1r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
                   "or $dst, $src2">, OpSize;
def OR32ri8  : Ii8<0x83, MRM1r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "or $dst, $src2">;
let isTwoAddress = 0 in {
  def OR16mi8  : Im16i8<"or" , 0x83, MRM1m>, OpSize;    // [mem16] |= imm8
  def OR32mi8  : Im32i8<"or" , 0x83, MRM1m>;            // [mem32] |= imm8
}


def XOR8rr   : I<0x30, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2), "xor $dst, $src2">;
def XOR16rr  : I<0x31, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), "xor $dst, $src2">, OpSize;
def XOR32rr  : I<0x31, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), "xor $dst, $src2">;
let isTwoAddress = 0 in {
  def XOR8mr : I<0x30, MRMDestMem, (ops i8mem :$dst, R8 :$src), "xor $dst, $src">;
  def XOR16mr: I<0x31, MRMDestMem, (ops i16mem:$dst, R16:$src), "xor $dst, $src">, OpSize;
  def XOR32mr: I<0x31, MRMDestMem, (ops i32mem:$dst, R32:$src), "xor $dst, $src">;
}
def XOR8rm   : I<0x32, MRMSrcMem , (ops R8 :$dst, R8:$src1, i8mem :$src2), "xor $dst, $src2">;
def XOR16rm  : I<0x33, MRMSrcMem , (ops R16:$dst, R8:$src1, i16mem:$src2), "xor $dst, $src2">, OpSize;
def XOR32rm  : I<0x33, MRMSrcMem , (ops R32:$dst, R8:$src1, i32mem:$src2), "xor $dst, $src2">;

def XOR8ri   : Ii8   <0x80, MRM6r, (ops R8:$dst, R8:$src1, i8imm:$src2), "xor $dst, $src2">;
def XOR16ri  : Ii16  <0x81, MRM6r, (ops R16:$dst, R16:$src1, i16imm:$src2), "xor $dst, $src2">, OpSize;
def XOR32ri  : Ii32  <0x81, MRM6r, (ops R32:$dst, R32:$src1, i32imm:$src2), "xor $dst, $src2">;
let isTwoAddress = 0 in {
  def XOR8mi : Im8i8  <"xor", 0x80, MRM6m    >;            // [mem8] ^= R8
  def XOR16mi: Im16i16<"xor", 0x81, MRM6m    >, OpSize;    // [mem16] ^= R16
  def XOR32mi: Im32i32<"xor", 0x81, MRM6m    >;            // [mem32] ^= R32
}
def XOR16ri8 : Ii8<0x83, MRM6r, (ops R16:$dst, R16:$src1, i8imm:$src2),
                   "xor $dst, $src2">, OpSize;
def XOR32ri8 : Ii8<0x83, MRM6r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "xor $dst, $src2">;
let isTwoAddress = 0 in {
  def XOR16mi8 : Im16i8<"xor", 0x83, MRM6m     >, OpSize;    // [mem16] ^= imm8
  def XOR32mi8 : Im32i8<"xor", 0x83, MRM6m     >;            // [mem32] ^= imm8
}

// Shift instructions
// FIXME: provide shorter instructions when imm8 == 1
def SHL8rCL  : I<0xD2, MRM4r, (ops R8 :$dst, R8 :$src), "shl $dst, %CL">, Imp<[CL],[]>;
def SHL16rCL : I<0xD3, MRM4r, (ops R16:$dst, R16:$src), "shl $dst, %CL">, Imp<[CL],[]>, OpSize;
def SHL32rCL : I<0xD3, MRM4r, (ops R32:$dst, R32:$src), "shl $dst, %CL">, Imp<[CL],[]>;
let isTwoAddress = 0 in {
  def SHL8mCL  : I<0xD2, MRM4m, (ops i8mem :$dst), "shl $dst, %CL">, Imp<[CL],[]>;
  def SHL16mCL : I<0xD3, MRM4m, (ops i16mem:$dst), "shl $dst, %CL">, Imp<[CL],[]>, OpSize;
  def SHL32mCL : I<0xD3, MRM4m, (ops i32mem:$dst), "shl $dst, %CL">, Imp<[CL],[]>;
}

def SHL8ri   : Ii8<0xC0, MRM4r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
                   "shl $dst, $src2">;
def SHL16ri  : Ii8<0xC1, MRM4r, (ops R16:$dst, R16:$src1, i8imm:$src2),
                   "shl $dst, $src2">, OpSize;
def SHL32ri  : Ii8<0xC1, MRM4r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "shl $dst, $src2">;
def SHL8mi   : Im8i8 <"shl", 0xC0, MRM4m     >;                 // [mem8]  <<= imm8
def SHL16mi  : Im16i8<"shl", 0xC1, MRM4m     >, OpSize;         // [mem16] <<= imm8
def SHL32mi  : Im32i8<"shl", 0xC1, MRM4m     >;                 // [mem32] <<= imm8

def SHR8rCL  : I<0xD2, MRM5r, (ops R8 :$dst, R8 :$src), "shr $dst, %CL">, Imp<[CL],[]>;
def SHR16rCL : I<0xD3, MRM5r, (ops R16:$dst, R16:$src), "shr $dst, %CL">, Imp<[CL],[]>, OpSize;
def SHR32rCL : I<0xD3, MRM5r, (ops R32:$dst, R32:$src), "shr $dst, %CL">, Imp<[CL],[]>;
let isTwoAddress = 0 in {
  def SHR8mCL  : I<0xD2, MRM5m, (ops i8mem :$dst), "shr $dst, %CL">, Imp<[CL],[]>;
  def SHR16mCL : I<0xD3, MRM5m, (ops i16mem:$dst), "shr $dst, %CL">, Imp<[CL],[]>, OpSize;
  def SHR32mCL : I<0xD3, MRM5m, (ops i32mem:$dst), "shr $dst, %CL">, Imp<[CL],[]>;
}

def SHR8ri   : Ii8   <0xC0, MRM5r, (ops R8:$dst, R8:$src1, i8imm:$src2), "shr $dst, $src2">;
def SHR16ri  : Ii8   <0xC1, MRM5r, (ops R16:$dst, R16:$src1, i8imm:$src2), "shr $dst, $src2">, OpSize;
def SHR32ri  : Ii8   <0xC1, MRM5r, (ops R32:$dst, R32:$src1, i8imm:$src2), "shr $dst, $src2">;
let isTwoAddress = 0 in {
  def SHR8mi   : Ii8 <0xC0, MRM5m, (ops i8mem :$dst, i8imm:$src), "shr $dst, $src">;
  def SHR16mi  : Ii8<0xC1, MRM5m, (ops i16mem:$dst, i8imm:$src), "shr $dst, $src">, OpSize;
  def SHR32mi  : Ii8<0xC1, MRM5m, (ops i32mem:$dst, i8imm:$src), "shr $dst, $src">;
}

def SAR8rCL  : I<0xD2, MRM7r, (ops R8 :$dst, R8 :$src), "sar $dst, %CL">, Imp<[CL],[]>;
def SAR16rCL : I<0xD3, MRM7r, (ops R16:$dst, R16:$src), "sar $dst, %CL">, Imp<[CL],[]>, OpSize;
def SAR32rCL : I<0xD3, MRM7r, (ops R32:$dst, R32:$src), "sar $dst, %CL">, Imp<[CL],[]>;
let isTwoAddress = 0 in {
  def SAR8mCL  : I<0xD2, MRM7m, (ops i8mem :$dst), "sar $dst, %CL">, Imp<[CL],[]>;
  def SAR16mCL : I<0xD3, MRM7m, (ops i16mem:$dst), "sar $dst, %CL">, Imp<[CL],[]>, OpSize;
  def SAR32mCL : I<0xD3, MRM7m, (ops i32mem:$dst), "sar $dst, %CL">, Imp<[CL],[]>;
}

def SAR8ri   : Ii8<0xC0, MRM7r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
                   "sar $dst, $src2">;
def SAR16ri  : Ii8<0xC1, MRM7r, (ops R16:$dst, R16:$src1, i8imm:$src2),
                   "sar $dst, $src2">, OpSize;
def SAR32ri  : Ii8<0xC1, MRM7r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "sar $dst, $src2">;
def SAR8mi   : Im8i8 <"sar", 0xC0, MRM7m     >;                 // [mem8]  >>>= imm8
def SAR16mi  : Im16i8<"sar", 0xC1, MRM7m     >, OpSize;         // [mem16] >>>= imm8
def SAR32mi  : Im32i8<"sar", 0xC1, MRM7m     >;                 // [mem32] >>>= imm8

def SHLD32rrCL : I<0xA5, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
                  "shld $dst, $src2, %CL">, Imp<[CL],[]>, TB;
def SHRD32rrCL : I<0xAD, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
                   "shrd $dst, $src2, %CL">, Imp<[CL],[]>, TB;
def SHLD32rri8 : Ii8<0xA4, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
                     "shld $dst, $src2, $src3">, TB;
def SHRD32rri8 : Ii8<0xAC, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
                     "shrd $dst, $src2, $src3">, TB;

let isTwoAddress = 0 in {
  def SHLD32mrCL : I<0xA5, MRMDestMem, (ops i32mem:$dst, R32:$src2),
                  "shld $dst, $src2, %CL">, Imp<[CL],[]>, TB;
  def SHRD32mrCL : I<0xAD, MRMDestMem, (ops i32mem:$dst, R32:$src2),
                  "shrd $dst, $src2, %CL">, Imp<[CL],[]>, TB;
  def SHLD32mri8 : Ii8<0xA4, MRMDestMem, (ops i32mem:$dst, R32:$src2, i8imm:$src3),
                  "shld $dst, $src2, $src3">, TB;
  def SHRD32mri8 : Ii8<0xAC, MRMDestMem, (ops i32mem:$dst, R32:$src2, i8imm:$src3),
                  "shrd $dst, $src2, $src3">, TB;
}


// Arithmetic...
def ADD8rr   : I<0x00, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2), "add $dst, $src2">;
def ADD16rr  : I<0x01, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), "add $dst, $src2">, OpSize;
def ADD32rr  : I<0x01, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), "add $dst, $src2">;
let isTwoAddress = 0 in {
  def ADD8mr   : I<0x00, MRMDestMem, (ops i8mem :$dst, R8 :$src2), "add $dst, $src2">;
  def ADD16mr  : I<0x01, MRMDestMem, (ops i16mem:$dst, R16:$src2), "add $dst, $src2">, OpSize;
  def ADD32mr  : I<0x01, MRMDestMem, (ops i32mem:$dst, R32:$src2), "add $dst, $src2">;
}
def ADD8rm   : I<0x02, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$src2), "add $dst, $src2">;
def ADD16rm  : I<0x03, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2), "add $dst, $src2">, OpSize;
def ADD32rm  : I<0x03, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2), "add $dst, $src2">;

def ADD8ri   : Ii8   <0x80, MRM0r, (ops R8:$dst, R8:$src1, i8imm:$src2), "add $dst, $src2">;
def ADD16ri  : Ii16  <0x81, MRM0r, (ops R16:$dst, R16:$src1, i16imm:$src2), "add $dst, $src2">, OpSize;
def ADD32ri  : Ii32  <0x81, MRM0r, (ops R32:$dst, R32:$src1, i32imm:$src2), "add $dst, $src2">;
let isTwoAddress = 0 in {
  def ADD8mi   : Im8i8  <"add", 0x80, MRM0m    >;         // [mem8] += I8
  def ADD16mi  : Im16i16<"add", 0x81, MRM0m    >, OpSize; // [mem16] += I16
  def ADD32mi  : Im32i32<"add", 0x81, MRM0m    >;         // [mem32] += I32
}

def ADD16ri8 : Ii8   <0x83, MRM0r, (ops R16:$dst, R16:$src1, i8imm:$src2), "add $dst, $src2">, OpSize;
def ADD32ri8 : Ii8   <0x83, MRM0r, (ops R32:$dst, R32:$src1, i8imm:$src2), "add $dst, $src2">;

let isTwoAddress = 0 in {
  def ADD16mi8 : Im16i8<"add", 0x83, MRM0m     >, OpSize; // [mem16] += I8
  def ADD32mi8 : Im32i8<"add", 0x83, MRM0m     >;         // [mem32] += I8
}

def ADC32rr  : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), "adc $dst, $src2">;
def ADC32rm  : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2), "adc $dst, $src2">;
def ADC32ri  : Ii32<0x81, MRM2r, (ops R32:$dst, R32:$src1, i32imm:$src2), "adc $dst, $src2">;
def ADC32ri8 : Ii8 <0x83, MRM2r, (ops R32:$dst, R32:$src1, i8imm:$src2), "adc $dst, $src2">;

let isTwoAddress = 0 in {
  def ADC32mr  : I<0x11, MRMDestMem, (ops i32mem:$dst, i32imm:$src2), "adc $dst, $src2">;
  def ADC32mi  : Im32i32<"adc", 0x81, MRM2m     >;         // [mem32] += I32+Carry
  def ADC32mi8 : Im32i8 <"adc", 0x83, MRM2m     >;         // [mem32] += I8+Carry
}

def SUB8rr   : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2), "sub $dst, $src2">;
def SUB16rr  : I<0x29, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2), "sub $dst, $src2">, OpSize;
def SUB32rr  : I<0x29, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2), "sub $dst, $src2">;
let isTwoAddress = 0 in {
  def SUB8mr   : I<0x28, MRMDestMem, (ops i8mem :$dst, R8 :$src2), "sub $dst, $src2">;
  def SUB16mr  : I<0x29, MRMDestMem, (ops i16mem:$dst, R16:$src2), "sub $dst, $src2">, OpSize;
  def SUB32mr  : I<0x29, MRMDestMem, (ops i32mem:$dst, R32:$src2), "sub $dst, $src2">;
}
def SUB8rm   : I<0x2A, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$src2), "sub $dst, $src2">;
def SUB16rm  : I<0x2B, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2), "sub $dst, $src2">, OpSize;
def SUB32rm  : I<0x2B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2), "sub $dst, $src2">;

def SUB8ri   : Ii8 <0x80, MRM5r, (ops R8:$dst, R8:$src1, i8imm:$src2),
                    "sub $dst, $src2">;
def SUB16ri  : Ii16<0x81, MRM5r, (ops R16:$dst, R16:$src1, i16imm:$src2),
                    "sub $dst, $src2">, OpSize;
def SUB32ri  : Ii32<0x81, MRM5r, (ops R32:$dst, R32:$src1, i32imm:$src2),
                    "sub $dst, $src2">;
let isTwoAddress = 0 in {
  def SUB8mi   : Im8i8  <"sub", 0x80, MRM5m    >;         // [mem8] -= I8
  def SUB16mi  : Im16i16<"sub", 0x81, MRM5m    >, OpSize; // [mem16] -= I16
  def SUB32mi  : Im32i32<"sub", 0x81, MRM5m    >;         // [mem32] -= I32
}

def SUB16ri8 : Ii8<0x83, MRM5r, (ops R16:$dst, R16:$src1, i8imm:$src2),
                   "sub $dst, $src2">, OpSize;
def SUB32ri8 : Ii8<0x83, MRM5r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "sub $dst, $src2">;
let isTwoAddress = 0 in {
  def SUB16mi8 : Im16i8<"sub", 0x83, MRM5m     >, OpSize; // [mem16] -= I8
  def SUB32mi8 : Im32i8<"sub", 0x83, MRM5m     >;         // [mem32] -= I8
}

def SBB32rr  : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
                 "adc $dst, $src2">;
let isTwoAddress = 0 in {
  def SBB32mr  : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$src2), "sbb $dst, $src2">;
  def SBB32mi  : Im32i32<"sbb", 0x81, MRM3m>;         // [mem32] -= I32+Carry
  def SBB32mi8 : Im32i8 <"sbb", 0x83, MRM3m>;         // [mem32] -= I8+Carry
}
def SBB32rm  : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                    "sbb $dst, $src2">;
def SBB32ri  : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2),
                    "sbb $dst, $src2">;
def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i8imm:$src2),
                   "sbb $dst, $src2">;

def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2), "imul $dst, $src2">, TB, OpSize;
def IMUL32rr : I<0xAF, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2), "imul $dst, $src2">, TB;
def IMUL16rm : I<0xAF, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2), "imul $dst, $src2">, TB, OpSize;
def IMUL32rm : I<0xAF, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2), "imul $dst, $src2">, TB        ;

} // end Two Address instructions

// These are suprisingly enough not two address instructions!
def IMUL16rri  : Ii16<0x69, MRMSrcReg, (ops R16:$dst, R16:$src1, i16imm:$src2),
                      "imul $dst, $src1, $src2">,     OpSize; // R16 = R16*I16
def IMUL32rri  : Ii32<0x69, MRMSrcReg, (ops R32:$dst, R32:$src1, i32imm:$src2),
                      "imul $dst, $src1, $src2">;             // R32 = R32*I32
def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, (ops R16:$dst, R16:$src1, i8imm:$src2),
                     "imul $dst, $src1, $src2">,     OpSize;  // R16 = R16*I8
def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, (ops R32:$dst, R32:$src1, i8imm:$src2),
                     "imul $dst, $src1, $src2">;           // R32 = R32*I8
def IMUL16rmi  : Im16i16<"imul",0x69, MRMSrcMem>,     OpSize;  // R16 = [mem16]*I16
def IMUL32rmi  : Im32i32<"imul",0x69, MRMSrcMem>;              // R32 = [mem32]*I32
def IMUL16rmi8 : Im16i8<"imul", 0x6B, MRMSrcMem>,     OpSize;  // R16 = [mem16]*I8
def IMUL32rmi8 : Im32i8<"imul", 0x6B, MRMSrcMem>;              // R32 = [mem32]*I8

//===----------------------------------------------------------------------===//
// Test instructions are just like AND, except they don't generate a result.
def TEST8rr  : I<0x84, MRMDestReg, (ops R8:$src1, R8:$src2),
                 "test $src1, $src2">;
def TEST16rr : I<0x85, MRMDestReg, (ops R16:$src1, R16:$src2),
                 "test $src1, $src2">, OpSize;
def TEST32rr : I<0x85, MRMDestReg, (ops R32:$src1, R32:$src2),
                 "test $src1, $src2">;
def TEST8mr  : I<0x84, MRMDestMem, (ops i8mem :$src1, R8 :$src2),
                 "test $src1, $src2">;
def TEST16mr : I<0x85, MRMDestMem, (ops i16mem:$src1, R16:$src2),
                 "test $src1, $src2">, OpSize;
def TEST32mr : I<0x85, MRMDestMem, (ops i32mem:$src1, R32:$src2),
                 "test $src1, $src2">;
def TEST8rm  : I<0x84, MRMSrcMem, (ops R8 :$src1, i8mem :$src2),
                 "test $src1, $src2">;
def TEST16rm : I<0x85, MRMSrcMem, (ops R16:$src1, i16mem:$src2),
                 "test $src1, $src2">, OpSize;
def TEST32rm : I<0x85, MRMSrcMem, (ops R32:$src1, i32mem:$src2),
                 "test $src1, $src2">;

def TEST8ri  : Ii8  <0xF6, MRM0r, (ops R8:$dst, i8imm:$src),
                     "test $dst, $src">;          // flags = R8  & imm8
def TEST16ri : Ii16 <0xF7, MRM0r, (ops R16:$dst, i16imm:$src),
                     "test $dst, $src">, OpSize;  // flags = R16 & imm16
def TEST32ri : Ii32 <0xF7, MRM0r, (ops R32:$dst, i32imm:$src),
                     "test $dst, $src">;          // flags = R32 & imm32
def TEST8mi  : Im8i8  <"test", 0xF6, MRM0m     >;          // flags = [mem8]  & imm8
def TEST16mi : Im16i16<"test", 0xF7, MRM0m     >, OpSize;  // flags = [mem16] & imm16
def TEST32mi : Im32i32<"test", 0xF7, MRM0m     >;          // flags = [mem32] & imm32



// Condition code ops, incl. set if equal/not equal/...
def SAHF     : I<0x9E, RawFrm, (ops), "sahf">, Imp<[AH],[]>;  // flags = AH
def LAHF     : I<0x9F, RawFrm, (ops), "lahf">, Imp<[],[AH]>;  // AH = flags

def SETBr    : I<0x92, MRM0r, (ops R8   :$dst), "setb $dst">, TB;    // R8 = <  unsign
def SETBm    : I<0x92, MRM0m, (ops i8mem:$dst), "setb $dst">, TB;            // [mem8] = <  unsign
def SETAEr   : I<0x93, MRM0r, (ops R8   :$dst), "setae $dst">, TB;   // R8 = >= unsign
def SETAEm   : I<0x93, MRM0m, (ops i8mem:$dst), "setae $dst">, TB;            // [mem8] = >= unsign
def SETEr    : I<0x94, MRM0r, (ops R8   :$dst), "sete $dst">, TB;    // R8 = ==
def SETEm    : I<0x94, MRM0m, (ops i8mem:$dst), "sete $dst">, TB;            // [mem8] = ==
def SETNEr   : I<0x95, MRM0r, (ops R8   :$dst), "setne $dst">, TB;   // R8 = !=
def SETNEm   : I<0x95, MRM0m, (ops i8mem:$dst), "setne $dst">, TB;            // [mem8] = !=
def SETBEr   : I<0x96, MRM0r, (ops R8   :$dst), "setbe $dst">, TB;   // R8 = <= unsign
def SETBEm   : I<0x96, MRM0m, (ops i8mem:$dst), "setbe $dst">, TB;            // [mem8] = <= unsign
def SETAr    : I<0x97, MRM0r, (ops R8   :$dst), "seta $dst">, TB;    // R8 = >  signed
def SETAm    : I<0x97, MRM0m, (ops i8mem:$dst), "seta $dst">, TB;            // [mem8] = >  signed
def SETSr    : I<0x98, MRM0r, (ops R8   :$dst), "sets $dst">, TB;    // R8 = <sign bit>
def SETSm    : I<0x98, MRM0m, (ops i8mem:$dst), "sets $dst">, TB;            // [mem8] = <sign bit>
def SETNSr   : I<0x99, MRM0r, (ops R8   :$dst), "setns $dst">, TB;   // R8 = !<sign bit>
def SETNSm   : I<0x99, MRM0m, (ops i8mem:$dst), "setns $dst">, TB;            // [mem8] = !<sign bit>
def SETPr    : I<0x9A, MRM0r, (ops R8   :$dst), "setp $dst">, TB;    // R8 = parity
def SETPm    : I<0x9A, MRM0m, (ops i8mem:$dst), "setp $dst">, TB;            // [mem8] = parity
def SETLr    : I<0x9C, MRM0r, (ops R8   :$dst), "setl $dst">, TB;    // R8 = <  signed
def SETLm    : I<0x9C, MRM0m, (ops i8mem:$dst), "setl $dst">, TB;            // [mem8] = <  signed
def SETGEr   : I<0x9D, MRM0r, (ops R8   :$dst), "setge $dst">, TB;   // R8 = >= signed
def SETGEm   : I<0x9D, MRM0m, (ops i8mem:$dst), "setge $dst">, TB;            // [mem8] = >= signed
def SETLEr   : I<0x9E, MRM0r, (ops R8   :$dst), "setle $dst">, TB;   // R8 = <= signed
def SETLEm   : I<0x9E, MRM0m, (ops i8mem:$dst), "setle $dst">, TB;            // [mem8] = <= signed
def SETGr    : I<0x9F, MRM0r, (ops R8   :$dst), "setg $dst">, TB;    // R8 = <  signed
def SETGm    : I<0x9F, MRM0m, (ops i8mem:$dst), "setg $dst">, TB;            // [mem8] = <  signed

// Integer comparisons
def CMP8rr  : I<0x38, MRMDestReg, (ops R8 :$src1, R8 :$src2), "cmp $src1, $src2">;
def CMP16rr : I<0x39, MRMDestReg, (ops R16:$src1, R16:$src2), "cmp $src1, $src2">, OpSize;
def CMP32rr : I<0x39, MRMDestReg, (ops R32:$src1, R32:$src2), "cmp $src1, $src2">;
def CMP8mr  : I<0x38, MRMDestMem, (ops i8mem :$src1, R8 :$src2), "cmp $src1, $src2">;
def CMP16mr : I<0x39, MRMDestMem, (ops i16mem:$src1, R16:$src2), "cmp $src1, $src2">, OpSize;
def CMP32mr : I<0x39, MRMDestMem, (ops i32mem:$src1, R32:$src2), "cmp $src1, $src2">;
def CMP8rm  : I<0x3A, MRMSrcMem , (ops R8 :$src1, i8mem :$src2), "cmp $src1, $src2">;
def CMP16rm : I<0x3B, MRMSrcMem , (ops R16:$src1, i16mem:$src2), "cmp $src1, $src2">, OpSize;
def CMP32rm : I<0x3B, MRMSrcMem , (ops R32:$src1, i32mem:$src2), "cmp $src1, $src2">;
def CMP8ri  : Ii8  <0x80, MRM7r, (ops R16:$dst, i8imm:$src), "cmp $dst, $src">;
def CMP16ri : Ii16 <0x81, MRM7r, (ops R16:$dst, i16imm:$src), "cmp $dst, $src">, OpSize;
def CMP32ri : Ii32 <0x81, MRM7r, (ops R32:$dst, i32imm:$src), "cmp $dst, $src">;
def CMP8mi  : Im8i8  <"cmp", 0x80, MRM7m   >;              // compare [mem8], imm8
def CMP16mi : Im16i16<"cmp", 0x81, MRM7m   >, OpSize;      // compare [mem16], imm16
def CMP32mi : Im32i32<"cmp", 0x81, MRM7m   >;              // compare [mem32], imm32

// Sign/Zero extenders
def MOVSX16rr8 : I<0xBE, MRMSrcReg, (ops R16:$dst, R8 :$src), "movsx $dst, $src">, TB, OpSize;
def MOVSX32rr8 : I<0xBE, MRMSrcReg, (ops R32:$dst, R8 :$src), "movsx $dst, $src">, TB;
def MOVSX32rr16: I<0xBF, MRMSrcReg, (ops R32:$dst, R16:$src), "movsx $dst, $src">, TB;
def MOVSX16rm8 : I<0xBE, MRMSrcMem, (ops R16:$dst, i8mem :$src), "movsx $dst, $src">, TB, OpSize;
def MOVSX32rm8 : I<0xBE, MRMSrcMem, (ops R32:$dst, i8mem :$src), "movsx $dst, $src">, TB;
def MOVSX32rm16: I<0xBF, MRMSrcMem, (ops R32:$dst, i16mem:$src), "movsx $dst, $src">, TB;

def MOVZX16rr8 : I<0xB6, MRMSrcReg, (ops R16:$dst, R8 :$src), "movzx $dst, $src">, TB, OpSize;
def MOVZX32rr8 : I<0xB6, MRMSrcReg, (ops R32:$dst, R8 :$src), "movzx $dst, $src">, TB;
def MOVZX32rr16: I<0xB7, MRMSrcReg, (ops R32:$dst, R16:$src), "movzx $dst, $src">, TB;
def MOVZX16rm8 : I<0xB6, MRMSrcMem, (ops R16:$dst, i8mem :$src), "movzx $dst, $src">, TB, OpSize;
def MOVZX32rm8 : I<0xB6, MRMSrcMem, (ops R32:$dst, i8mem :$src), "movzx $dst, $src">, TB;
def MOVZX32rm16: I<0xB7, MRMSrcMem, (ops R32:$dst, i16mem:$src), "movzx $dst, $src">, TB;


//===----------------------------------------------------------------------===//
// Floating point support
//===----------------------------------------------------------------------===//

// FIXME: These need to indicate mod/ref sets for FP regs... & FP 'TOP'

// Floating point instruction templates
class FPInst<string n, bits<8> o, Format F, FPFormat fp, MemType m, ImmType i>
  : X86Inst<n, o, F, m, i> { let FPForm = fp; let FPFormBits = FPForm.Value; }

class FPI<bits<8> o, Format F, FPFormat fp> : FPInst<"", o, F, fp, NoMem, NoImm>;

class FPIM<string n, bits<8> o, Format F, FPFormat fp, MemType m> : FPInst<n, o, F, fp, m, NoImm>;

class FPI16m<string n, bits<8> o, Format F, FPFormat fp> : FPIM<n, o, F, fp, Mem16>;
class FPI32m<string n, bits<8> o, Format F, FPFormat fp> : FPIM<n, o, F, fp, Mem32>;
class FPI64m<string n, bits<8> o, Format F, FPFormat fp> : FPIM<n, o, F, fp, Mem64>;
class FPI80m<string n, bits<8> o, Format F, FPFormat fp> : FPIM<n, o, F, fp, Mem80>;

// Pseudo instructions for floating point.  We use these pseudo instructions
// because they can be expanded by the fp spackifier into one of many different
// forms of instructions for doing these operations.  Until the stackifier runs,
// we prefer to be abstract.
def FpMOV : FPI<0, Pseudo, SpecialFP>;   // f1 = fmov f2
def FpADD : FPI<0, Pseudo, TwoArgFP>;    // f1 = fadd f2, f3
def FpSUB : FPI<0, Pseudo, TwoArgFP>;    // f1 = fsub f2, f3
def FpMUL : FPI<0, Pseudo, TwoArgFP>;    // f1 = fmul f2, f3
def FpDIV : FPI<0, Pseudo, TwoArgFP>;    // f1 = fdiv f2, f3

def FpGETRESULT : FPI<0, Pseudo, SpecialFP>;  // FPR = ST(0)
def FpSETRESULT : FPI<0, Pseudo, SpecialFP>;  // ST(0) = FPR

// FADD reg, mem: Before stackification, these are represented by: R1 = FADD* R2, [mem]
def FADD32m  : FPI32m<"fadd",  0xD8, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem32real]
def FADD64m  : FPI64m<"fadd",  0xDC, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem64real]
def FIADD16m : FPI16m<"fiadd", 0xDE, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem16int]
def FIADD32m : FPI32m<"fiadd", 0xDA, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem32int]

// FMUL reg, mem: Before stackification, these are represented by: R1 = FMUL* R2, [mem]
def FMUL32m  : FPI32m<"fmul",  0xD8, MRM1m, OneArgFPRW>;    // ST(0) = ST(0) * [mem32real]
def FMUL64m  : FPI64m<"fmul",  0xDC, MRM1m, OneArgFPRW>;    // ST(0) = ST(0) * [mem64real]
def FIMUL16m : FPI16m<"fimul", 0xDE, MRM1m, OneArgFPRW>;    // ST(0) = ST(0) * [mem16int]
def FIMUL32m : FPI32m<"fimul", 0xDA, MRM1m, OneArgFPRW>;    // ST(0) = ST(0) * [mem32int]

// FSUB reg, mem: Before stackification, these are represented by: R1 = FSUB* R2, [mem]
def FSUB32m  : FPI32m<"fsub",  0xD8, MRM4m, OneArgFPRW>;    // ST(0) = ST(0) - [mem32real]
def FSUB64m  : FPI64m<"fsub",  0xDC, MRM4m, OneArgFPRW>;    // ST(0) = ST(0) - [mem64real]
def FISUB16m : FPI16m<"fisub", 0xDE, MRM4m, OneArgFPRW>;    // ST(0) = ST(0) - [mem16int]
def FISUB32m : FPI32m<"fisub", 0xDA, MRM4m, OneArgFPRW>;    // ST(0) = ST(0) - [mem32int]

// FSUBR reg, mem: Before stackification, these are represented by: R1 = FSUBR* R2, [mem]
// Note that the order of operands does not reflect the operation being performed.
def FSUBR32m  : FPI32m<"fsubr",  0xD8, MRM5m, OneArgFPRW>;  // ST(0) = [mem32real] - ST(0)
def FSUBR64m  : FPI64m<"fsubr",  0xDC, MRM5m, OneArgFPRW>;  // ST(0) = [mem64real] - ST(0)
def FISUBR16m : FPI16m<"fisubr", 0xDE, MRM5m, OneArgFPRW>;  // ST(0) = [mem16int] - ST(0)
def FISUBR32m : FPI32m<"fisubr", 0xDA, MRM5m, OneArgFPRW>;  // ST(0) = [mem32int] - ST(0)

// FDIV reg, mem: Before stackification, these are represented by: R1 = FDIV* R2, [mem]
def FDIV32m  : FPI32m<"fdiv",  0xD8, MRM6m, OneArgFPRW>;    // ST(0) = ST(0) / [mem32real]
def FDIV64m  : FPI64m<"fdiv",  0xDC, MRM6m, OneArgFPRW>;    // ST(0) = ST(0) / [mem64real]
def FIDIV16m : FPI16m<"fidiv", 0xDE, MRM6m, OneArgFPRW>;    // ST(0) = ST(0) / [mem16int]
def FIDIV32m : FPI32m<"fidiv", 0xDA, MRM6m, OneArgFPRW>;    // ST(0) = ST(0) / [mem32int]

// FDIVR reg, mem: Before stackification, these are represented by: R1 = FDIVR* R2, [mem]
// Note that the order of operands does not reflect the operation being performed.
def FDIVR32m  : FPI32m<"fdivr",  0xD8, MRM7m, OneArgFPRW>;  // ST(0) = [mem32real] / ST(0)
def FDIVR64m  : FPI64m<"fdivr",  0xDC, MRM7m, OneArgFPRW>;  // ST(0) = [mem64real] / ST(0)
def FIDIVR16m : FPI16m<"fidivr", 0xDE, MRM7m, OneArgFPRW>;  // ST(0) = [mem16int] / ST(0)
def FIDIVR32m : FPI32m<"fidivr", 0xDA, MRM7m, OneArgFPRW>;  // ST(0) = [mem32int] / ST(0)


// Floating point cmovs...
let isTwoAddress = 1, Uses = [ST0], Defs = [ST0] in {
  def FCMOVB  : FPI<0xC0, AddRegFrm, CondMovFP>, DA,    // fcmovb  ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmovb %ST(0), $op">;
  def FCMOVBE : FPI<0xD0, AddRegFrm, CondMovFP>, DA,     // fcmovbe ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmovbe %ST(0), $op">;
  def FCMOVE  : FPI<0xC8, AddRegFrm, CondMovFP>, DA,    // fcmove  ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmove %ST(0), $op">;
  def FCMOVAE : FPI<0xC0, AddRegFrm, CondMovFP>, DB,     // fcmovae ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmovae %ST(0), $op">;
  def FCMOVA  : FPI<0xD0, AddRegFrm, CondMovFP>, DB,    // fcmova  ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmova %ST(0), $op">;
  def FCMOVNE : FPI<0xC8, AddRegFrm, CondMovFP>, DB,     // fcmovne ST(i) -> ST(0)
                 II<(ops RST:$op), "fcmovne %ST(0), $op">;
}

// Floating point loads & stores...
let Name = "fld" in
def FLDrr   : FPI<0xC0, AddRegFrm, NotFP>, D9;        // push(ST(i))
def FLD32m  : FPI32m <"fld"   , 0xD9, MRM0m    , ZeroArgFP>;        // load float
def FLD64m  : FPI64m <"fld"   , 0xDD, MRM0m    , ZeroArgFP>;        // load double
def FLD80m  : FPI80m <"fld"   , 0xDB, MRM5m    , ZeroArgFP>;        // load extended
def FILD16m : FPI16m <"fild"  , 0xDF, MRM0m    , ZeroArgFP>;        // load signed short
def FILD32m : FPI32m <"fild"  , 0xDB, MRM0m    , ZeroArgFP>;        // load signed int
def FILD64m : FPI64m <"fild"  , 0xDF, MRM5m    , ZeroArgFP>;        // load signed long

let Name = "fst" in
  def FSTrr  : FPI<0xD0, AddRegFrm, NotFP   >, DD;      // ST(i) = ST(0)
let Name = "fstp" in
  def FSTPrr : FPI<0xD8, AddRegFrm, NotFP   >, DD;      // ST(i) = ST(0), pop
def FST32m   : FPI32m <"fst" , 0xD9, MRM2m    , OneArgFP>;          // store float
def FST64m   : FPI64m <"fst" , 0xDD, MRM2m    , OneArgFP>;          // store double
def FSTP32m  : FPI32m <"fstp", 0xD9, MRM3m    , OneArgFP>;          // store float, pop
def FSTP64m  : FPI64m <"fstp", 0xDD, MRM3m    , OneArgFP>;          // store double, pop
def FSTP80m  : FPI80m <"fstp", 0xDB, MRM7m    , OneArgFP>;          // store extended, pop

def FIST16m  : FPI16m <"fist",    0xDF, MRM2m , OneArgFP>;          // store signed short
def FIST32m  : FPI32m <"fist",    0xDB, MRM2m , OneArgFP>;          // store signed int
def FISTP16m : FPI16m <"fistp",   0xDF, MRM3m , NotFP   >;          // store signed short, pop
def FISTP32m : FPI32m <"fistp",   0xDB, MRM3m , NotFP   >;          // store signed int, pop
def FISTP64m : FPI64m <"fistpll", 0xDF, MRM7m , OneArgFP>;          // store signed long, pop

def FXCH     : FPI<0xC8, AddRegFrm, NotFP>,
               II<(ops RST:$op), "fxch $op">, D9;      // fxch ST(i), ST(0)

// Floating point constant loads...
def FLD0 : FPI<0xEE, RawFrm, ZeroArgFP>, D9,
               II<(ops), "fldz">;
def FLD1 : FPI<0xE8, RawFrm, ZeroArgFP>, D9,
               II<(ops), "fld1">;


// Unary operations...
def FCHS : FPI<0xE0, RawFrm, OneArgFPRW>,           // f1 = fchs f2
               II<(ops), "fchs">, D9;
def FTST : FPI<0xE4, RawFrm, OneArgFP>,             // ftst ST(0)
               II<(ops), "ftst">, D9;

// Binary arithmetic operations...
class FPST0rInst<bits<8> o, dag ops, string asm> : I<o, AddRegFrm, ops, asm>, D8 {
  list<Register> Uses = [ST0];
  list<Register> Defs = [ST0];
}
class FPrST0Inst<bits<8> o, dag ops, string asm> : I<o, AddRegFrm, ops, asm>, DC {
  list<Register> Uses = [ST0];
}
class FPrST0PInst<bits<8> o, dag ops, string asm> : I<o, AddRegFrm, ops, asm>, DE {
  list<Register> Uses = [ST0];
}

def FADDST0r   : FPST0rInst <0xC0, (ops RST:$op), "fadd $op">;
def FADDrST0   : FPrST0Inst <0xC0, (ops RST:$op), "fadd $op, %ST(0)">;
def FADDPrST0  : FPrST0PInst<0xC0, (ops RST:$op), "faddp $op">;

def FSUBRST0r  : FPST0rInst <0xE8, (ops RST:$op), "fsubr $op">;
def FSUBrST0   : FPrST0Inst <0xE8, (ops RST:$op), "fsub $op, %ST(0)">;
def FSUBPrST0  : FPrST0PInst<0xE8, (ops RST:$op), "fsubp $op">;

def FSUBST0r   : FPST0rInst <0xE0, (ops RST:$op), "fsub $op">;
def FSUBRrST0  : FPrST0Inst <0xE0, (ops RST:$op), "fsubr $op, %ST(0)">;
def FSUBRPrST0 : FPrST0PInst<0xE0, (ops RST:$op), "fsubrp $op">;

def FMULST0r   : FPST0rInst <0xC8, (ops RST:$op), "fmul $op">;
def FMULrST0   : FPrST0Inst <0xC8, (ops RST:$op), "fmul $op, %ST(0)">;
def FMULPrST0  : FPrST0PInst<0xC8, (ops RST:$op), "fmulp $op">;

def FDIVRST0r  : FPST0rInst <0xF8, (ops RST:$op), "fdivr $op">;
def FDIVrST0   : FPrST0Inst <0xF8, (ops RST:$op), "fdiv $op, %ST(0)">;
def FDIVPrST0  : FPrST0PInst<0xF8, (ops RST:$op), "fdivp $op">;

def FDIVST0r   : FPST0rInst <0xF0, (ops RST:$op), "fdiv $op">;           // ST(0) = ST(0) / ST(i)
def FDIVRrST0  : FPrST0Inst <0xF0, (ops RST:$op), "fdivr $op, %ST(0)">;  // ST(i) = ST(0) / ST(i)
def FDIVRPrST0 : FPrST0PInst<0xF0, (ops RST:$op), "fdivrp $op">;         // ST(i) = ST(0) / ST(i), pop

// Floating point compares
def FUCOMr    : FPI<0xE0, AddRegFrm, CompareFP>,                         // FPSW = compare ST(0) with ST(i)
                II<(ops RST:$reg), "fucom $reg">, DD, Imp<[ST0],[]>;
def FUCOMPr   : I<0xE8, AddRegFrm, (ops RST:$reg),
                  "fucomp $reg">, DD, Imp<[ST0],[]>;  // FPSW = compare ST(0) with ST(i), pop
def FUCOMPPr  : I<0xE9, RawFrm, (ops),
                  "fucompp">, DA, Imp<[ST0],[]>;  // compare ST(0) with ST(1), pop, pop

def FUCOMIr  : FPI<0xE8, AddRegFrm, CompareFP>, // CC = compare ST(0) with ST(i)
               II<(ops RST:$reg), "fucomi %ST(0), $reg">, DB, Imp<[ST0],[]>;
def FUCOMIPr : I<0xE8, AddRegFrm, (ops RST:$reg),
                 "fucomip %ST(0), $reg">, DF, Imp<[ST0],[]>;  // CC = compare ST(0) with ST(i), pop


// Floating point flag ops
def FNSTSW8r  : I<0xE0, RawFrm, (ops), "fnstsw">, DF, Imp<[],[AX]>;   // AX = fp flags

def FNSTCW16m : I<0xD9, MRM7m, (ops i16mem:$dst), "fnstcw $dst">; // [mem16] = X87 control world
def FLDCW16m  : I<0xD9, MRM5m, (ops i16mem:$dst), "fldcw $dst">;  // X87 control world = [mem16]