• 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 "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 */