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