• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */