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