Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
35295 views
1
//===-- XtensaMCCodeEmitter.cpp - Convert Xtensa Code to Machine Code -----===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6
// See https://llvm.org/LICENSE.txt for license information.
7
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8
//
9
//===----------------------------------------------------------------------===//
10
//
11
// This file implements the XtensaMCCodeEmitter class.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "MCTargetDesc/XtensaFixupKinds.h"
16
#include "MCTargetDesc/XtensaMCExpr.h"
17
#include "MCTargetDesc/XtensaMCTargetDesc.h"
18
#include "llvm/MC/MCCodeEmitter.h"
19
#include "llvm/MC/MCContext.h"
20
#include "llvm/MC/MCExpr.h"
21
#include "llvm/MC/MCInst.h"
22
#include "llvm/MC/MCInstrInfo.h"
23
#include "llvm/MC/MCRegisterInfo.h"
24
25
#define GET_INSTRMAP_INFO
26
#include "XtensaGenInstrInfo.inc"
27
#undef GET_INSTRMAP_INFO
28
29
using namespace llvm;
30
31
#define DEBUG_TYPE "mccodeemitter"
32
33
namespace {
34
class XtensaMCCodeEmitter : public MCCodeEmitter {
35
const MCInstrInfo &MCII;
36
MCContext &Ctx;
37
bool IsLittleEndian;
38
39
public:
40
XtensaMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx, bool isLE)
41
: MCII(mcii), Ctx(ctx), IsLittleEndian(isLE) {}
42
43
~XtensaMCCodeEmitter() {}
44
45
// OVerride MCCodeEmitter.
46
void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
47
SmallVectorImpl<MCFixup> &Fixups,
48
const MCSubtargetInfo &STI) const override;
49
50
private:
51
// Automatically generated by TableGen.
52
uint64_t getBinaryCodeForInstr(const MCInst &MI,
53
SmallVectorImpl<MCFixup> &Fixups,
54
const MCSubtargetInfo &STI) const;
55
56
// Called by the TableGen code to get the binary encoding of operand
57
// MO in MI. Fixups is the list of fixups against MI.
58
uint32_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
59
SmallVectorImpl<MCFixup> &Fixups,
60
const MCSubtargetInfo &STI) const;
61
62
uint32_t getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
63
SmallVectorImpl<MCFixup> &Fixups,
64
const MCSubtargetInfo &STI) const;
65
66
uint32_t getBranchTargetEncoding(const MCInst &MI, unsigned int OpNum,
67
SmallVectorImpl<MCFixup> &Fixups,
68
const MCSubtargetInfo &STI) const;
69
70
uint32_t getCallEncoding(const MCInst &MI, unsigned int OpNum,
71
SmallVectorImpl<MCFixup> &Fixups,
72
const MCSubtargetInfo &STI) const;
73
74
uint32_t getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
75
SmallVectorImpl<MCFixup> &Fixups,
76
const MCSubtargetInfo &STI) const;
77
78
uint32_t getMemRegEncoding(const MCInst &MI, unsigned OpNo,
79
SmallVectorImpl<MCFixup> &Fixups,
80
const MCSubtargetInfo &STI) const;
81
82
uint32_t getImm8OpValue(const MCInst &MI, unsigned OpNo,
83
SmallVectorImpl<MCFixup> &Fixups,
84
const MCSubtargetInfo &STI) const;
85
86
uint32_t getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
87
SmallVectorImpl<MCFixup> &Fixups,
88
const MCSubtargetInfo &STI) const;
89
90
uint32_t getImm12OpValue(const MCInst &MI, unsigned OpNo,
91
SmallVectorImpl<MCFixup> &Fixups,
92
const MCSubtargetInfo &STI) const;
93
94
uint32_t getUimm4OpValue(const MCInst &MI, unsigned OpNo,
95
SmallVectorImpl<MCFixup> &Fixups,
96
const MCSubtargetInfo &STI) const;
97
98
uint32_t getUimm5OpValue(const MCInst &MI, unsigned OpNo,
99
SmallVectorImpl<MCFixup> &Fixups,
100
const MCSubtargetInfo &STI) const;
101
102
uint32_t getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
103
SmallVectorImpl<MCFixup> &Fixups,
104
const MCSubtargetInfo &STI) const;
105
106
uint32_t getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
107
SmallVectorImpl<MCFixup> &Fixups,
108
const MCSubtargetInfo &STI) const;
109
110
uint32_t getB4constOpValue(const MCInst &MI, unsigned OpNo,
111
SmallVectorImpl<MCFixup> &Fixups,
112
const MCSubtargetInfo &STI) const;
113
114
uint32_t getB4constuOpValue(const MCInst &MI, unsigned OpNo,
115
SmallVectorImpl<MCFixup> &Fixups,
116
const MCSubtargetInfo &STI) const;
117
};
118
} // namespace
119
120
MCCodeEmitter *llvm::createXtensaMCCodeEmitter(const MCInstrInfo &MCII,
121
MCContext &Ctx) {
122
return new XtensaMCCodeEmitter(MCII, Ctx, true);
123
}
124
125
void XtensaMCCodeEmitter::encodeInstruction(const MCInst &MI,
126
SmallVectorImpl<char> &CB,
127
SmallVectorImpl<MCFixup> &Fixups,
128
const MCSubtargetInfo &STI) const {
129
uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
130
unsigned Size = MCII.get(MI.getOpcode()).getSize();
131
132
if (IsLittleEndian) {
133
// Little-endian insertion of Size bytes.
134
unsigned ShiftValue = 0;
135
for (unsigned I = 0; I != Size; ++I) {
136
CB.push_back(char(Bits >> ShiftValue));
137
ShiftValue += 8;
138
}
139
} else {
140
// TODO Big-endian insertion of Size bytes.
141
report_fatal_error("Big-endian mode currently is not supported!");
142
}
143
}
144
145
uint32_t
146
XtensaMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
147
SmallVectorImpl<MCFixup> &Fixups,
148
const MCSubtargetInfo &STI) const {
149
if (MO.isReg())
150
return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
151
if (MO.isImm()) {
152
uint32_t Res = static_cast<uint32_t>(MO.getImm());
153
return Res;
154
}
155
156
report_fatal_error("Unhandled expression!");
157
return 0;
158
}
159
160
uint32_t
161
XtensaMCCodeEmitter::getJumpTargetEncoding(const MCInst &MI, unsigned int OpNum,
162
SmallVectorImpl<MCFixup> &Fixups,
163
const MCSubtargetInfo &STI) const {
164
const MCOperand &MO = MI.getOperand(OpNum);
165
166
if (MO.isImm())
167
return MO.getImm();
168
169
const MCExpr *Expr = MO.getExpr();
170
Fixups.push_back(MCFixup::create(
171
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_jump_18), MI.getLoc()));
172
return 0;
173
}
174
175
uint32_t XtensaMCCodeEmitter::getBranchTargetEncoding(
176
const MCInst &MI, unsigned int OpNum, SmallVectorImpl<MCFixup> &Fixups,
177
const MCSubtargetInfo &STI) const {
178
const MCOperand &MO = MI.getOperand(OpNum);
179
if (MO.isImm())
180
return static_cast<uint32_t>(MO.getImm());
181
182
const MCExpr *Expr = MO.getExpr();
183
switch (MI.getOpcode()) {
184
case Xtensa::BEQZ:
185
case Xtensa::BGEZ:
186
case Xtensa::BLTZ:
187
case Xtensa::BNEZ:
188
Fixups.push_back(MCFixup::create(
189
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_12), MI.getLoc()));
190
return 0;
191
default:
192
Fixups.push_back(MCFixup::create(
193
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_branch_8), MI.getLoc()));
194
return 0;
195
}
196
}
197
198
uint32_t
199
XtensaMCCodeEmitter::getCallEncoding(const MCInst &MI, unsigned int OpNum,
200
SmallVectorImpl<MCFixup> &Fixups,
201
const MCSubtargetInfo &STI) const {
202
const MCOperand &MO = MI.getOperand(OpNum);
203
if (MO.isImm()) {
204
int32_t Res = MO.getImm();
205
if (Res & 0x3) {
206
llvm_unreachable("Unexpected operand value!");
207
}
208
Res >>= 2;
209
return Res;
210
}
211
212
assert((MO.isExpr()) && "Unexpected operand value!");
213
const MCExpr *Expr = MO.getExpr();
214
Fixups.push_back(MCFixup::create(
215
0, Expr, MCFixupKind(Xtensa::fixup_xtensa_call_18), MI.getLoc()));
216
return 0;
217
}
218
219
uint32_t
220
XtensaMCCodeEmitter::getL32RTargetEncoding(const MCInst &MI, unsigned OpNum,
221
SmallVectorImpl<MCFixup> &Fixups,
222
const MCSubtargetInfo &STI) const {
223
const MCOperand &MO = MI.getOperand(OpNum);
224
if (MO.isImm()) {
225
int32_t Res = MO.getImm();
226
// We don't check first 2 bits, because in these bits we could store first 2
227
// bits of instruction address
228
Res >>= 2;
229
return Res;
230
}
231
232
assert((MO.isExpr()) && "Unexpected operand value!");
233
234
Fixups.push_back(MCFixup::create(
235
0, MO.getExpr(), MCFixupKind(Xtensa::fixup_xtensa_l32r_16), MI.getLoc()));
236
return 0;
237
}
238
239
uint32_t
240
XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
241
SmallVectorImpl<MCFixup> &Fixups,
242
const MCSubtargetInfo &STI) const {
243
assert(MI.getOperand(OpNo + 1).isImm());
244
245
uint32_t Res = static_cast<uint32_t>(MI.getOperand(OpNo + 1).getImm());
246
247
switch (MI.getOpcode()) {
248
case Xtensa::S16I:
249
case Xtensa::L16SI:
250
case Xtensa::L16UI:
251
if (Res & 0x1) {
252
report_fatal_error("Unexpected operand value!");
253
}
254
Res >>= 1;
255
break;
256
case Xtensa::S32I:
257
case Xtensa::L32I:
258
if (Res & 0x3) {
259
report_fatal_error("Unexpected operand value!");
260
}
261
Res >>= 2;
262
break;
263
}
264
265
assert((isUInt<8>(Res)) && "Unexpected operand value!");
266
267
uint32_t OffBits = Res << 4;
268
uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
269
270
return ((OffBits & 0xFF0) | RegBits);
271
}
272
273
uint32_t XtensaMCCodeEmitter::getImm8OpValue(const MCInst &MI, unsigned OpNo,
274
SmallVectorImpl<MCFixup> &Fixups,
275
const MCSubtargetInfo &STI) const {
276
const MCOperand &MO = MI.getOperand(OpNo);
277
int32_t Res = MO.getImm();
278
279
assert(((Res >= -128) && (Res <= 127)) && "Unexpected operand value!");
280
281
return (Res & 0xff);
282
}
283
284
uint32_t
285
XtensaMCCodeEmitter::getImm8_sh8OpValue(const MCInst &MI, unsigned OpNo,
286
SmallVectorImpl<MCFixup> &Fixups,
287
const MCSubtargetInfo &STI) const {
288
const MCOperand &MO = MI.getOperand(OpNo);
289
int32_t Res = MO.getImm();
290
291
assert(((Res >= -32768) && (Res <= 32512) && ((Res & 0xff) == 0)) &&
292
"Unexpected operand value!");
293
294
return (Res & 0xffff);
295
}
296
297
uint32_t
298
XtensaMCCodeEmitter::getImm12OpValue(const MCInst &MI, unsigned OpNo,
299
SmallVectorImpl<MCFixup> &Fixups,
300
const MCSubtargetInfo &STI) const {
301
const MCOperand &MO = MI.getOperand(OpNo);
302
int32_t Res = MO.getImm();
303
304
assert(((Res >= -2048) && (Res <= 2047)) && "Unexpected operand value!");
305
306
return (Res & 0xfff);
307
}
308
309
uint32_t
310
XtensaMCCodeEmitter::getUimm4OpValue(const MCInst &MI, unsigned OpNo,
311
SmallVectorImpl<MCFixup> &Fixups,
312
const MCSubtargetInfo &STI) const {
313
const MCOperand &MO = MI.getOperand(OpNo);
314
uint32_t Res = static_cast<uint32_t>(MO.getImm());
315
316
assert((Res <= 15) && "Unexpected operand value!");
317
318
return Res & 0xf;
319
}
320
321
uint32_t
322
XtensaMCCodeEmitter::getUimm5OpValue(const MCInst &MI, unsigned OpNo,
323
SmallVectorImpl<MCFixup> &Fixups,
324
const MCSubtargetInfo &STI) const {
325
const MCOperand &MO = MI.getOperand(OpNo);
326
uint32_t Res = static_cast<uint32_t>(MO.getImm());
327
328
assert((Res <= 31) && "Unexpected operand value!");
329
330
return (Res & 0x1f);
331
}
332
333
uint32_t
334
XtensaMCCodeEmitter::getShimm1_31OpValue(const MCInst &MI, unsigned OpNo,
335
SmallVectorImpl<MCFixup> &Fixups,
336
const MCSubtargetInfo &STI) const {
337
const MCOperand &MO = MI.getOperand(OpNo);
338
uint32_t Res = static_cast<uint32_t>(MO.getImm());
339
340
assert(((Res >= 1) && (Res <= 31)) && "Unexpected operand value!");
341
342
return ((32 - Res) & 0x1f);
343
}
344
345
uint32_t
346
XtensaMCCodeEmitter::getImm1_16OpValue(const MCInst &MI, unsigned OpNo,
347
SmallVectorImpl<MCFixup> &Fixups,
348
const MCSubtargetInfo &STI) const {
349
const MCOperand &MO = MI.getOperand(OpNo);
350
uint32_t Res = static_cast<uint32_t>(MO.getImm());
351
352
assert(((Res >= 1) && (Res <= 16)) && "Unexpected operand value!");
353
354
return (Res - 1);
355
}
356
357
uint32_t
358
XtensaMCCodeEmitter::getB4constOpValue(const MCInst &MI, unsigned OpNo,
359
SmallVectorImpl<MCFixup> &Fixups,
360
const MCSubtargetInfo &STI) const {
361
const MCOperand &MO = MI.getOperand(OpNo);
362
uint32_t Res = static_cast<uint32_t>(MO.getImm());
363
364
switch (Res) {
365
case 0xffffffff:
366
Res = 0;
367
break;
368
case 1:
369
case 2:
370
case 3:
371
case 4:
372
case 5:
373
case 6:
374
case 7:
375
case 8:
376
break;
377
case 10:
378
Res = 9;
379
break;
380
case 12:
381
Res = 10;
382
break;
383
case 16:
384
Res = 11;
385
break;
386
case 32:
387
Res = 12;
388
break;
389
case 64:
390
Res = 13;
391
break;
392
case 128:
393
Res = 14;
394
break;
395
case 256:
396
Res = 15;
397
break;
398
default:
399
llvm_unreachable("Unexpected operand value!");
400
}
401
402
return Res;
403
}
404
405
uint32_t
406
XtensaMCCodeEmitter::getB4constuOpValue(const MCInst &MI, unsigned OpNo,
407
SmallVectorImpl<MCFixup> &Fixups,
408
const MCSubtargetInfo &STI) const {
409
const MCOperand &MO = MI.getOperand(OpNo);
410
uint32_t Res = static_cast<uint32_t>(MO.getImm());
411
412
switch (Res) {
413
case 32768:
414
Res = 0;
415
break;
416
case 65536:
417
Res = 1;
418
break;
419
case 2:
420
case 3:
421
case 4:
422
case 5:
423
case 6:
424
case 7:
425
case 8:
426
break;
427
case 10:
428
Res = 9;
429
break;
430
case 12:
431
Res = 10;
432
break;
433
case 16:
434
Res = 11;
435
break;
436
case 32:
437
Res = 12;
438
break;
439
case 64:
440
Res = 13;
441
break;
442
case 128:
443
Res = 14;
444
break;
445
case 256:
446
Res = 15;
447
break;
448
default:
449
llvm_unreachable("Unexpected operand value!");
450
}
451
452
return Res;
453
}
454
#include "XtensaGenMCCodeEmitter.inc"
455
456