]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
Merge llvm, clang, lld and lldb trunk r291476.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / BPF / Disassembler / BPFDisassembler.cpp
1 //===- BPFDisassembler.cpp - Disassembler for BPF ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is part of the BPF Disassembler.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "BPF.h"
15 #include "BPFSubtarget.h"
16 #include "MCTargetDesc/BPFMCTargetDesc.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19 #include "llvm/MC/MCFixedLenDisassembler.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/Support/MathExtras.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include <cstdint>
24
25 using namespace llvm;
26
27 #define DEBUG_TYPE "bpf-disassembler"
28
29 typedef MCDisassembler::DecodeStatus DecodeStatus;
30
31 namespace {
32
33 /// A disassembler class for BPF.
34 class BPFDisassembler : public MCDisassembler {
35 public:
36   BPFDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
37       : MCDisassembler(STI, Ctx) {}
38   ~BPFDisassembler() override = default;
39
40   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
41                               ArrayRef<uint8_t> Bytes, uint64_t Address,
42                               raw_ostream &VStream,
43                               raw_ostream &CStream) const override;
44 };
45
46 } // end anonymous namespace
47
48 static MCDisassembler *createBPFDisassembler(const Target &T,
49                                              const MCSubtargetInfo &STI,
50                                              MCContext &Ctx) {
51   return new BPFDisassembler(STI, Ctx);
52 }
53
54
55 extern "C" void LLVMInitializeBPFDisassembler() {
56   // Register the disassembler.
57   TargetRegistry::RegisterMCDisassembler(getTheBPFTarget(),
58                                          createBPFDisassembler);
59   TargetRegistry::RegisterMCDisassembler(getTheBPFleTarget(),
60                                          createBPFDisassembler);
61   TargetRegistry::RegisterMCDisassembler(getTheBPFbeTarget(),
62                                          createBPFDisassembler);
63 }
64
65 static const unsigned GPRDecoderTable[] = {
66     BPF::R0,  BPF::R1,  BPF::R2,  BPF::R3,  BPF::R4,  BPF::R5,
67     BPF::R6,  BPF::R7,  BPF::R8,  BPF::R9,  BPF::R10, BPF::R11};
68
69 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
70                                            uint64_t /*Address*/,
71                                            const void * /*Decoder*/) {
72   if (RegNo > 11)
73     return MCDisassembler::Fail;
74
75   unsigned Reg = GPRDecoderTable[RegNo];
76   Inst.addOperand(MCOperand::createReg(Reg));
77   return MCDisassembler::Success;
78 }
79
80 static DecodeStatus decodeMemoryOpValue(MCInst &Inst, unsigned Insn,
81                                         uint64_t Address, const void *Decoder) {
82   unsigned Register = (Insn >> 16) & 0xf;
83   Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
84   unsigned Offset = (Insn & 0xffff);
85   Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
86
87   return MCDisassembler::Success;
88 }
89
90 #include "BPFGenDisassemblerTables.inc"
91
92 static DecodeStatus readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
93                                       uint64_t &Size, uint64_t &Insn) {
94   uint64_t Lo, Hi;
95
96   if (Bytes.size() < 8) {
97     Size = 0;
98     return MCDisassembler::Fail;
99   }
100
101   Size = 8;
102   Hi = (Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 0) | (Bytes[3] << 8);
103   Lo = (Bytes[4] << 0) | (Bytes[5] << 8) | (Bytes[6] << 16) | (Bytes[7] << 24);
104   Insn = Make_64(Hi, Lo);
105
106   return MCDisassembler::Success;
107 }
108
109 DecodeStatus BPFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
110                                              ArrayRef<uint8_t> Bytes,
111                                              uint64_t Address,
112                                              raw_ostream &VStream,
113                                              raw_ostream &CStream) const {
114   uint64_t Insn;
115   DecodeStatus Result;
116
117   Result = readInstruction64(Bytes, Address, Size, Insn);
118   if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
119
120   Result = decodeInstruction(DecoderTableBPF64, Instr, Insn,
121                              Address, this, STI);
122   if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
123
124   switch (Instr.getOpcode()) {
125   case BPF::LD_imm64: {
126     if (Bytes.size() < 16) {
127       Size = 0;
128       return MCDisassembler::Fail;
129     }
130     Size = 16;
131     uint64_t Hi = (Bytes[12] << 0) | (Bytes[13] << 8) | (Bytes[14] << 16) | (Bytes[15] << 24);
132     auto& Op = Instr.getOperand(1);
133     Op.setImm(Make_64(Hi, Op.getImm()));
134     break;
135   }
136   case BPF::LD_ABS_B:
137   case BPF::LD_ABS_H:
138   case BPF::LD_ABS_W:
139   case BPF::LD_IND_B:
140   case BPF::LD_IND_H:
141   case BPF::LD_IND_W: {
142     auto Op = Instr.getOperand(0);
143     Instr.clear();
144     Instr.addOperand(MCOperand::createReg(BPF::R6));
145     Instr.addOperand(Op);
146     break;
147   }
148   }
149
150   return Result;
151 }
152
153 typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
154                                    const void *Decoder);