1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef X64_ASSEMBLER_OPERAND_H 17 #define X64_ASSEMBLER_OPERAND_H 18 19 #include <unordered_map> 20 #include <string> 21 #include "util.h" 22 23 namespace assembler { 24 using ImmOpnd = std::pair<int64, bool>; 25 26 /* Use 16 bits to represent a register: 27 The high 8 bits is register's size. 28 The low 4 bits is register's id. 29 The fifth bit from right to left is used to identity register rip, the bit equals 1 represents the RIP register. 30 The sixth bit from right to left is used to identity float register, the bit equals 1 represents the float register. 31 The eighth bit from right to left is used to determine whether 32 it is the high 8-bit register or the lower 8-bit register, the bit equals 1 represents the lower 8-bit register. 33 The specific distribution of the 16 bits is shown below: 34 +-----------------------------------+-----------+-------+---------+-------+-------------------+ 35 | 15 14 13 12 11 10 9 8 | 7 | 6 | 5 | 4 | 3 2 1 0 | 36 +-----------------------------------+-----------+-------+---------+-------+-------------------+ 37 | Reg's size in bits | H/L8-reg | unuse | IsFloat | IsRIP | Reg's id | 38 +-----------------------------------+-----------+-------+---------+-------+-------------------+ 39 | 0 0 0 0 0 0 0 0 | 0 | 0 | 0 | 0 | 0 0 0 0 | 40 +-----------------------------------+-----------+-------+---------+------+--------------------+ 41 */ 42 enum Reg : uint16 { 43 XMM0 = 0x8000, 44 XMM1, 45 XMM2, 46 XMM3, 47 XMM4, 48 XMM5, 49 XMM6, 50 XMM7, 51 XMM8, 52 XMM9, 53 XMM10, 54 XMM11, 55 XMM12, 56 XMM13, 57 XMM14, 58 XMM15, 59 MMX0 = 0x4020, MMX1, MMX2, MMX3, MMX4, MMX5, MMX6, MMX7, 60 RAX = 0x4000, 61 RCX, 62 RDX, 63 RBX, 64 RSP, 65 RBP, 66 RSI, 67 RDI, 68 R8, 69 R9, 70 R10, 71 R11, 72 R12, 73 R13, 74 R14, 75 R15, 76 RIP = 0x4015, 77 EAX = 0x2000, 78 ECX, 79 EDX, 80 EBX, 81 ESP, 82 EBP, 83 ESI, 84 EDI, 85 R8D, 86 R9D, 87 R10D, 88 R11D, 89 R12D, 90 R13D, 91 R14D, 92 R15D, 93 AX = 0x1000, 94 CX, 95 DX, 96 BX, 97 SP, 98 BP, 99 SI, 100 DI, 101 R8W, 102 R9W, 103 R10W, 104 R11W, 105 R12W, 106 R13W, 107 R14W, 108 R15W, 109 AL = 0x0880, 110 CL, 111 DL, 112 BL, 113 SPL, 114 BPL, 115 SIL, 116 DIL, 117 R8B, 118 R9B, 119 R10B, 120 R11B, 121 R12B, 122 R13B, 123 R14B, 124 R15B, 125 AH = 0x0804, 126 CH, 127 DH, 128 BH, 129 ES = 0, 130 CS, 131 SS, 132 DS, 133 FS, 134 GS, 135 ERR = 0xFFFF 136 }; 137 138 static const uint8 kMaxRegNum = 35; 139 static const uint8 kRegSizeType = 6; 140 // To implement operating 64/32 bit float with 128bit asm insn, 141 // 32bit/64bit/128bit regs in kRegArray has done some processes same with openArkCompiler. 142 static const std::array<std::array<Reg, kMaxRegNum>, kRegSizeType> kRegArray = { 143 {{ERR, AL, CL, DL, BL, SPL, BPL, SIL, DIL, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B}, 144 {ERR, AH, CH, DH, BH}, 145 {ERR, AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W}, 146 {ERR, EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D, ERR, 147 XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15}, 148 {ERR, RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15, 149 RIP, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15}, 150 {ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, 151 XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15}} 152 }; 153 154 static const std::unordered_map<Reg, std::string> kRegStrMap = { 155 {XMM0, "xmm0"}, {XMM1, "xmm1"}, {XMM2, "xmm2"}, {XMM3, "xmm3"}, {XMM4, "xmm4"}, {XMM5, "xmm5"}, 156 {XMM6, "xmm6"}, {XMM7, "xmm7"}, {XMM8, "xmm8"}, {XMM9, "xmm9"}, {XMM10, "xmm10"}, {XMM11, "xmm11"}, 157 {XMM12, "xmm12"}, {XMM13, "xmm13"}, {XMM14, "xmm14"}, {XMM15, "xmm15"}, 158 {MMX0, "mmx0"}, {MMX1, "mmx1"}, {MMX2, "mmx2"}, {MMX3, "mmx3"}, {MMX4, "mmx4"}, {MMX5, "mmx5"}, {MMX6, "mmx6"}, 159 {MMX7, "mmx7"}, 160 {RAX, "rax"}, {RDX, "rdx"}, 161 {RCX, "rcx"}, {RBX, "rbx"}, {RSP, "rsp"}, {RBP, "rbp"}, {RSI, "rsi"}, {RDI, "rdi"}, 162 {R8, "r8"}, {R9, "r9"}, {R10, "r10"}, {R11, "r11"}, {R12, "r12"}, {R13, "r13"}, 163 {R14, "r14"}, {R15, "r15"}, {RIP, "rip"}, {EAX, "eax"}, {ECX, "ecx"}, {EDX, "edx"}, 164 {EBX, "ebx"}, {ESP, "esp"}, {EBP, "ebp"}, {ESI, "esi"}, {EDI, "edi"}, {R8D, "r8d"}, 165 {R9D, "r9d"}, {R10D, "r10d"}, {R11D, "r11d"}, {R12D, "r12d"}, {R13D, "r13d"}, {R14D, "r14d"}, 166 {R15D, "r15d"}, {AX, "ax"}, {CX, "cx"}, {DX, "dx"}, {BX, "bx"}, {SP, "sp"}, 167 {BP, "bp"}, {SI, "si"}, {DI, "di"}, {R8W, "r8w"}, {R9W, "r9w"}, {R10W, "r10w"}, 168 {R11W, "r11w"}, {R12W, "r12w"}, {R13W, "r13w"}, {R14W, "r14w"}, {R15W, "r15w"}, {AL, "al"}, 169 {CL, "cl"}, {DL, "dl"}, {BL, "bl"}, {SPL, "spl"}, {BPL, "bpl"}, {SIL, "sil"}, 170 {DIL, "dil"}, {R8B, "r8b"}, {R9B, "r9b"}, {R10B, "r10b"}, {R11B, "r11b"}, {R12B, "r12b"}, 171 {R13B, "r13b"}, {R14B, "r14b"}, {R15B, "r15b"}, {AH, "ah"}, {CH, "ch"}, {DH, "dh"}, 172 {BH, "bh"}, {ES, "es"}, {CS, "cs"}, {SS, "ss"}, {DS, "ds"}, {FS, "fs"}, 173 {GS, "gs"}, {ERR, "err"}}; 174 175 enum MemType { 176 kNone, 177 kOnlyBase, 178 kOnlyDisp, 179 kBaseAndDisp, 180 kIndexAndDisp, /* If there is a index register in the mem, there must be a scasle. */ 181 kSIB, /* SIB is abbreviation of Scale, Index, Base. */ 182 kSIBAndDisp 183 }; 184 185 struct Mem { 186 Reg base = ERR; 187 Reg index = ERR; 188 uint8 s = 0; /* scale = log2(s) */ 189 std::pair<int64, int64> disp = {0, 0}; /* first: symbol id, second: offset */ 190 uint32 size = 32; 191 MemType memType = kNone; 192 MemMem193 Mem() {} 194 SetMemTypeMem195 void SetMemType() 196 { 197 if (base != ERR && index != ERR && (disp.second != 0 || disp.first != 0)) { 198 memType = kSIBAndDisp; 199 } else if (base != ERR && index != ERR && disp.second == 0 && disp.first == 0) { 200 memType = kSIB; 201 } else if (base == ERR && index != ERR && (disp.second != 0 || disp.first != 0)) { 202 memType = kIndexAndDisp; 203 } else if (base != ERR && index == ERR && (disp.second != 0 || disp.first != 0)) { 204 memType = kBaseAndDisp; 205 } else if (base == ERR && index == ERR && (disp.second != 0 || disp.first != 0)) { 206 memType = kOnlyDisp; 207 } else if (base != ERR && index == ERR && disp.second == 0 && disp.first == 0) { 208 memType = kOnlyBase; 209 } else { 210 memType = kNone; 211 } 212 } 213 }; /* struct Mem */ 214 215 enum FixupKind { 216 kFNone, 217 kRelative, 218 kRelative64, 219 kAbsolute, 220 kAbsolute64, 221 kPLT, 222 }; 223 224 enum class LabelType { 225 kLNone, 226 kBBLabel, 227 kFunc, 228 kConst, 229 kGlobal, 230 kStatic, 231 kGlobalUninitialized, 232 kLocalUninitialized, 233 kStrLabel, 234 kJmpLabel, 235 kFloatLabel, 236 kDoubleLabel, 237 /* for debug */ 238 kDebugStrLabel, 239 }; 240 241 class Label { 242 public: Label(int64 index,uint32 relOffsetVal,LabelType type)243 Label(int64 index, uint32 relOffsetVal, LabelType type) 244 : labelIndex(index), relOffset(relOffsetVal), labelType(type) 245 { 246 } 247 248 ~Label() = default; 249 GetlabelIdx()250 int64 GetlabelIdx() const 251 { 252 return labelIndex; 253 } 254 GetRelOffset()255 uint32 GetRelOffset() const 256 { 257 return relOffset; 258 } 259 GetLabelType()260 LabelType GetLabelType() const 261 { 262 return labelType; 263 } 264 SetRelOffset(uint32 value)265 void SetRelOffset(uint32 value) 266 { 267 relOffset = value; 268 } 269 SetLabelType(LabelType type)270 void SetLabelType(LabelType type) 271 { 272 labelType = type; 273 } 274 275 private: 276 int64 labelIndex; /* target label index */ 277 uint32 relOffset; /* record the label's position */ 278 LabelType labelType; /* target label type */ 279 }; /* class Label */ 280 281 class Fixup { 282 public: Fixup(int64 index,FixupKind kind,const std::pair<uint32,size_t> & offset,int64 dispVal)283 Fixup(int64 index, FixupKind kind, const std::pair<uint32, size_t> &offset, int64 dispVal) 284 : labelIndex(index), fixupKind(kind), offset(offset), disp(dispVal) 285 { 286 } 287 GetlabelIdx()288 int64 GetlabelIdx() const 289 { 290 return labelIndex; 291 } 292 SetLabelIdx(int64 index)293 void SetLabelIdx(int64 index) 294 { 295 labelIndex = index; 296 } 297 GetFixupKind()298 FixupKind GetFixupKind() const 299 { 300 return fixupKind; 301 } 302 SetFixupKind(FixupKind kind)303 void SetFixupKind(FixupKind kind) 304 { 305 fixupKind = kind; 306 } 307 GetOffset()308 const std::pair<uint32, size_t> &GetOffset() const 309 { 310 return offset; 311 } 312 SetOffset(const std::pair<uint32,size_t> & fixupOffset)313 void SetOffset(const std::pair<uint32, size_t> &fixupOffset) 314 { 315 offset = fixupOffset; 316 } 317 GetDisp()318 int64 GetDisp() const 319 { 320 return disp; 321 } 322 SetDisp(int64 value)323 void SetDisp(int64 value) 324 { 325 disp = value; 326 } 327 328 private: 329 int64 labelIndex; /* record the label needs to fix up */ 330 FixupKind fixupKind; /* record how to fix up */ 331 std::pair<uint32, uint64> offset; /* record the location and size to fixup, 332 the first is offset, the second is offset's size */ 333 int64 disp; /* record the symbol's addend for relocation */ 334 }; /* class Fixup */ 335 } /* namespace assembler */ 336 337 #endif /* X64_ASSEMBLER_OPERAND_H */