| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | ////////////////////////////////////////////////////////////////////////////// |
| 5 | |
| 6 | // |
| 7 | // This file was previously known as emitfmts.h |
| 8 | // |
| 9 | |
| 10 | // clang-format off |
| 11 | #if !defined(_TARGET_XARCH_) |
| 12 | #error Unexpected target type |
| 13 | #endif |
| 14 | |
| 15 | #ifdef DEFINE_ID_OPS |
| 16 | ////////////////////////////////////////////////////////////////////////////// |
| 17 | |
| 18 | #undef DEFINE_ID_OPS |
| 19 | |
| 20 | enum ID_OPS |
| 21 | { |
| 22 | ID_OP_NONE, // no additional arguments |
| 23 | ID_OP_SCNS, // small const operand (21-bits or less, no reloc) |
| 24 | ID_OP_CNS, // constant operand |
| 25 | ID_OP_DSP, // displacement operand |
| 26 | ID_OP_DSP_CNS, // displacement + constant |
| 27 | ID_OP_AMD, // addrmode with dsp |
| 28 | ID_OP_AMD_CNS, // addrmode with dsp + constant |
| 29 | ID_OP_JMP, // local jump |
| 30 | ID_OP_LBL, // label operand |
| 31 | ID_OP_CALL, // direct method call |
| 32 | ID_OP_SPEC, // special handling required |
| 33 | }; |
| 34 | |
| 35 | ////////////////////////////////////////////////////////////////////////////// |
| 36 | #else // !DEFINE_ID_OPS |
| 37 | ////////////////////////////////////////////////////////////////////////////// |
| 38 | |
| 39 | #ifdef DEFINE_IS_OPS |
| 40 | #undef DEFINE_IS_OPS |
| 41 | |
| 42 | #else // DEFINE_IS_OPS |
| 43 | |
| 44 | ////////////////////////////////////////////////////////////////////////////// |
| 45 | |
| 46 | #ifndef IF_DEF |
| 47 | #error Must define IF_DEF macro before including this file |
| 48 | #endif |
| 49 | |
| 50 | ////////////////////////////////////////////////////////////////////////////// |
| 51 | // |
| 52 | // A note on the naming convention for instruction forms (IF_xxxxx). |
| 53 | // For 3-character code XYY, generally we have: |
| 54 | // X = |
| 55 | // R - register |
| 56 | // M - memory |
| 57 | // S - stack |
| 58 | // A - address mode |
| 59 | // YY = |
| 60 | // RD - read |
| 61 | // WR - write |
| 62 | // RW - read / write |
| 63 | // |
| 64 | // The following sequences don't follow this pattern: |
| 65 | // XYY = |
| 66 | // CNS - constant |
| 67 | // SHF - shift-constant |
| 68 | // |
| 69 | // For IF_XXX_YYY, the first operand is XXX, the second operand is YYY. |
| 70 | // |
| 71 | ////////////////////////////////////////////////////////////////////////////// |
| 72 | |
| 73 | ////////////////////////////////////////////////////////////////////////////// |
| 74 | // |
| 75 | // enum insFormat instruction enum ID_OPS |
| 76 | // scheduling |
| 77 | // (unused) |
| 78 | ////////////////////////////////////////////////////////////////////////////// |
| 79 | |
| 80 | IF_DEF(NONE, IS_NONE, NONE) // no operands |
| 81 | |
| 82 | IF_DEF(LABEL, IS_NONE, JMP ) // label |
| 83 | IF_DEF(RWR_LABEL, IS_R1_WR, JMP ) // write label to register |
| 84 | IF_DEF(SWR_LABEL, IS_SF_WR, LBL ) // write label to stack |
| 85 | |
| 86 | IF_DEF(METHOD, IS_NONE, CALL) // method |
| 87 | IF_DEF(METHPTR, IS_NONE, CALL) // method ptr (glbl) |
| 88 | |
| 89 | IF_DEF(CNS, IS_NONE, SCNS) // const |
| 90 | |
| 91 | //---------------------------------------------------------------------------- |
| 92 | // NOTE: The order of the "RD/WR/RW" varieties must match that of |
| 93 | // the "insUpdateModes" enum in "instr.h". |
| 94 | //---------------------------------------------------------------------------- |
| 95 | |
| 96 | IF_DEF(RRD, IS_R1_RD, NONE) // read reg |
| 97 | IF_DEF(RWR, IS_R1_WR, NONE) // write reg |
| 98 | IF_DEF(RRW, IS_R1_RW, NONE) // r/w reg |
| 99 | |
| 100 | IF_DEF(RRD_CNS, IS_R1_RD, SCNS) // read reg , const |
| 101 | IF_DEF(RWR_CNS, IS_R1_WR, SCNS) // write reg , const |
| 102 | IF_DEF(RRW_CNS, IS_R1_RW, SCNS) // r/w reg , const |
| 103 | IF_DEF(RRW_SHF, IS_R1_RW, SCNS) // r/w reg , shift-const |
| 104 | |
| 105 | IF_DEF(RRD_RRD, IS_R1_RD|IS_R2_RD, NONE) // read reg , read reg2 |
| 106 | IF_DEF(RWR_RRD, IS_R1_WR|IS_R2_RD, NONE) // write reg , read reg2 |
| 107 | IF_DEF(RRW_RRD, IS_R1_RW|IS_R2_RD, NONE) // r/w reg , read reg2 |
| 108 | IF_DEF(RRW_RRW, IS_R1_RW|IS_R2_RW, NONE) // r/w reg , r/w reg2 - for XCHG reg, reg2 |
| 109 | IF_DEF(RRW_RRW_CNS, IS_R1_RW|IS_R2_RW, SCNS) // r/w reg , r/w reg2 , const |
| 110 | |
| 111 | IF_DEF(RWR_RRD_RRD, IS_R1_WR|IS_R2_RD|IS_R3_RD, NONE) // write reg , read reg2 , read reg3 |
| 112 | IF_DEF(RWR_RRD_RRD_CNS, IS_R1_WR|IS_R2_RD|IS_R3_RD, SCNS) // write reg , read reg2 , read reg3, const |
| 113 | |
| 114 | IF_DEF(RWR_RRD_RRD_RRD, IS_R1_WR|IS_R2_RD|IS_R3_RD|IS_R4_RD, CNS) // write reg , read reg2 , read reg3 , read reg4 |
| 115 | //---------------------------------------------------------------------------- |
| 116 | // The following formats are used for direct addresses (e.g. static data members) |
| 117 | //---------------------------------------------------------------------------- |
| 118 | |
| 119 | IF_DEF(MRD, IS_GM_RD, SPEC) // read [mem] (indirect call req. SPEC) |
| 120 | IF_DEF(MWR, IS_GM_WR, DSP) // write [mem] |
| 121 | IF_DEF(MRW, IS_GM_RW, DSP) // r/w [mem] |
| 122 | IF_DEF(MRD_OFF, IS_GM_RD, DSP) // offset mem |
| 123 | |
| 124 | IF_DEF(RRD_MRD, IS_GM_RD|IS_R1_RD, DSP) // read reg , read [mem] |
| 125 | IF_DEF(RWR_MRD, IS_GM_RD|IS_R1_WR, DSP) // write reg , read [mem] |
| 126 | IF_DEF(RRW_MRD, IS_GM_RD|IS_R1_RW, DSP) // r/w reg , read [mem] |
| 127 | IF_DEF(RRW_MRD_CNS, IS_GM_RD|IS_R1_RW, DSP_CNS) // r/w reg , read [mem], const |
| 128 | |
| 129 | IF_DEF(RWR_RRD_MRD, IS_GM_RD|IS_R1_WR|IS_R2_RD, DSP) // write reg , read reg2 , read [mem] |
| 130 | IF_DEF(RWR_MRD_CNS, IS_GM_RD|IS_R1_WR, DSP_CNS) // write reg , read [mem], const |
| 131 | IF_DEF(RWR_RRD_MRD_CNS, IS_GM_RD|IS_R1_WR|IS_R2_RD, DSP_CNS) // write reg , read reg2 , read [mem], const |
| 132 | IF_DEF(RWR_RRD_MRD_RRD, IS_GM_RD|IS_R1_WR|IS_R2_RD|IS_R3_RD, DSP_CNS) // write reg , read reg2 , read [mem], read reg3 |
| 133 | IF_DEF(RWR_MRD_OFF, IS_GM_RD|IS_R1_WR, DSP) // write reg , offset mem |
| 134 | |
| 135 | IF_DEF(MRD_RRD, IS_GM_RD|IS_R1_RD, DSP) // read [mem], read reg |
| 136 | IF_DEF(MWR_RRD, IS_GM_WR|IS_R1_RD, DSP) // write [mem], read reg |
| 137 | IF_DEF(MRW_RRD, IS_GM_RW|IS_R1_RD, DSP) // r/w [mem], read reg |
| 138 | |
| 139 | IF_DEF(MRD_CNS, IS_GM_RD, DSP_CNS) // read [mem], const |
| 140 | IF_DEF(MWR_CNS, IS_GM_WR, DSP_CNS) // write [mem], const |
| 141 | IF_DEF(MRW_CNS, IS_GM_RW, DSP_CNS) // r/w [mem], const |
| 142 | |
| 143 | IF_DEF(MWR_RRD_CNS, IS_GM_WR|IS_R1_RD, DSP_CNS) // write [mem], read reg, const |
| 144 | |
| 145 | IF_DEF(MRW_SHF, IS_GM_RW, DSP_CNS) // shift [mem], const |
| 146 | |
| 147 | //---------------------------------------------------------------------------- |
| 148 | // The following formats are used for stack frame refs |
| 149 | //---------------------------------------------------------------------------- |
| 150 | |
| 151 | IF_DEF(SRD, IS_SF_RD, SPEC) // read [stk] (indirect call req. SPEC) |
| 152 | IF_DEF(SWR, IS_SF_WR, NONE) // write [stk] |
| 153 | IF_DEF(SRW, IS_SF_RW, NONE) // r/w [stk] |
| 154 | |
| 155 | IF_DEF(RRD_SRD, IS_SF_RD|IS_R1_RD, NONE) // read reg , read [stk] |
| 156 | IF_DEF(RWR_SRD, IS_SF_RD|IS_R1_WR, NONE) // write reg , read [stk] |
| 157 | IF_DEF(RRW_SRD, IS_SF_RD|IS_R1_RW, NONE) // r/w reg , read [stk] |
| 158 | IF_DEF(RRW_SRD_CNS, IS_SF_RD|IS_R1_RW, CNS ) // r/w reg , read [stk], const |
| 159 | |
| 160 | IF_DEF(RWR_RRD_SRD, IS_SF_RD|IS_R1_WR|IS_R2_RD, NONE) // write reg , read reg2, read [stk] |
| 161 | IF_DEF(RWR_SRD_CNS, IS_SF_RD|IS_R1_WR, CNS ) // write reg , read [stk], const |
| 162 | IF_DEF(RWR_RRD_SRD_CNS, IS_SF_RD|IS_R1_WR|IS_R2_RD, CNS ) // write reg , read reg2, read [stk], const |
| 163 | IF_DEF(RWR_RRD_SRD_RRD, IS_SF_RD|IS_R1_WR|IS_R2_RD|IS_R3_RD, CNS ) // write reg , read reg2, read [stk], read reg3 |
| 164 | |
| 165 | IF_DEF(SRD_RRD, IS_SF_RD|IS_R1_RD, NONE) // read [stk], read reg |
| 166 | IF_DEF(SWR_RRD, IS_SF_WR|IS_R1_RD, NONE) // write [stk], read reg |
| 167 | IF_DEF(SRW_RRD, IS_SF_RW|IS_R1_RD, NONE) // r/w [stk], read reg |
| 168 | |
| 169 | IF_DEF(SRD_CNS, IS_SF_RD, CNS ) // read [stk], const |
| 170 | IF_DEF(SWR_CNS, IS_SF_WR, CNS ) // write [stk], const |
| 171 | IF_DEF(SRW_CNS, IS_SF_RW, CNS ) // r/w [stk], const |
| 172 | |
| 173 | IF_DEF(SRW_SHF, IS_SF_RW, CNS ) // shift [stk], const |
| 174 | |
| 175 | //---------------------------------------------------------------------------- |
| 176 | // The following formats are used for indirect address modes |
| 177 | //---------------------------------------------------------------------------- |
| 178 | |
| 179 | |
| 180 | IF_DEF(ARD, IS_AM_RD, SPEC) // read [adr] (indirect call req. SPEC) |
| 181 | IF_DEF(AWR, IS_AM_WR, AMD ) // write [adr] |
| 182 | IF_DEF(ARW, IS_AM_RW, AMD ) // r/w [adr] |
| 183 | |
| 184 | IF_DEF(RRD_ARD, IS_AM_RD|IS_R1_RD, AMD ) // read reg , read [adr] |
| 185 | IF_DEF(RWR_ARD, IS_AM_RD|IS_R1_WR, AMD ) // write reg , read [adr] |
| 186 | IF_DEF(RRW_ARD, IS_AM_RD|IS_R1_RW, AMD ) // r/w reg , read [adr] |
| 187 | IF_DEF(RRW_ARD_CNS, IS_AM_RD|IS_R1_RW, AMD_CNS) // r/w reg , read [adr], const |
| 188 | |
| 189 | IF_DEF(RWR_RRD_ARD, IS_AM_RD|IS_R1_WR|IS_R2_RD, AMD ) // write reg , read reg2, read [adr] |
| 190 | IF_DEF(RWR_ARD_CNS, IS_AM_RD|IS_R1_WR, AMD_CNS) // write reg , read [adr], const |
| 191 | IF_DEF(RWR_ARD_RRD, IS_AM_RD|IS_R1_WR|IS_R2_RD, AMD) // write reg , read [adr], read reg2 |
| 192 | IF_DEF(RWR_RRD_ARD_CNS, IS_AM_RD|IS_R1_WR|IS_R2_RD, AMD_CNS) // write reg , read reg2, read [adr], const |
| 193 | IF_DEF(RWR_RRD_ARD_RRD, IS_AM_RD|IS_R1_WR|IS_R2_RD|IS_R3_RD, AMD_CNS) // write reg , read reg2, read [adr], read reg3 |
| 194 | |
| 195 | IF_DEF(ARD_RRD, IS_AM_RD|IS_R1_RD, AMD ) // read [adr], read reg |
| 196 | IF_DEF(AWR_RRD, IS_AM_WR|IS_R1_RD, AMD ) // write [adr], read reg |
| 197 | IF_DEF(ARW_RRD, IS_AM_RW|IS_R1_RD, AMD ) // r/w [adr], read reg |
| 198 | |
| 199 | IF_DEF(AWR_RRD_RRD, IS_AM_WR|IS_R1_RD|IS_R2_RD, AMD ) // write [adr], read reg, read reg |
| 200 | |
| 201 | IF_DEF(ARD_CNS, IS_AM_RD, AMD_CNS) // read [adr], const |
| 202 | IF_DEF(AWR_CNS, IS_AM_WR, AMD_CNS) // write [adr], const |
| 203 | IF_DEF(ARW_CNS, IS_AM_RW, AMD_CNS) // r/w [adr], const |
| 204 | |
| 205 | IF_DEF(AWR_RRD_CNS, IS_AM_WR|IS_R1_RD, AMD_CNS) // write [adr], read reg, const |
| 206 | |
| 207 | IF_DEF(ARW_SHF, IS_AM_RW, AMD_CNS) // shift [adr], const |
| 208 | |
| 209 | ////////////////////////////////////////////////////////////////////////////// |
| 210 | |
| 211 | #undef IF_DEF |
| 212 | |
| 213 | ////////////////////////////////////////////////////////////////////////////// |
| 214 | #endif // DEFINE_IS_OPS |
| 215 | #endif // DEFINE_ID_OPS |
| 216 | ////////////////////////////////////////////////////////////////////////////// |
| 217 | // clang-format on |
| 218 | |