gem5  v22.1.0.0
microop_args.hh
Go to the documentation of this file.
1 /*
2  * Copyright 2021 Google Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met: redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer;
8  * redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution;
11  * neither the name of the copyright holders nor the names of its
12  * contributors may be used to endorse or promote products derived from
13  * this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef __ARCH_X86_INSTS_MICROOP_ARGS_HH__
29 #define __ARCH_X86_INSTS_MICROOP_ARGS_HH__
30 
31 #include <cstdint>
32 #include <sstream>
33 #include <string>
34 #include <tuple>
35 #include <type_traits>
36 #include <utility>
37 
39 #include "arch/x86/regs/float.hh"
40 #include "arch/x86/regs/int.hh"
41 #include "arch/x86/regs/misc.hh"
42 #include "arch/x86/regs/segment.hh"
43 #include "arch/x86/types.hh"
44 #include "base/compiler.hh"
45 #include "base/cprintf.hh"
46 #include "cpu/reg_class.hh"
47 #include "sim/faults.hh"
48 
49 namespace gem5
50 {
51 
52 namespace X86ISA
53 {
54 
55 struct DestOp
56 {
57  const RegIndex dest;
58  const size_t size;
59  RegIndex opIndex() const { return dest; }
60 
61  DestOp(RegIndex _dest, size_t _size) : dest(_dest), size(_size) {}
62  template <class InstType>
63  DestOp(RegIndex _dest, InstType *inst) : dest(_dest),
64  size(inst->getDestSize())
65  {}
66 };
67 
68 struct Src1Op
69 {
70  const RegIndex src1;
71  const size_t size;
72  RegIndex opIndex() const { return src1; }
73 
74  Src1Op(RegIndex _src1, size_t _size) : src1(_src1), size(_size) {}
75  template <class InstType>
76  Src1Op(RegIndex _src1, InstType *inst) : src1(_src1),
77  size(inst->getSrcSize())
78  {}
79 };
80 
81 struct Src2Op
82 {
83  const RegIndex src2;
84  const size_t size;
85  RegIndex opIndex() const { return src2; }
86 
87  Src2Op(RegIndex _src2, size_t _size) : src2(_src2), size(_size) {}
88  template <class InstType>
89  Src2Op(RegIndex _src2, InstType *inst) : src2(_src2),
90  size(inst->getSrcSize())
91  {}
92 };
93 
94 struct DataOp
95 {
96  const RegIndex data;
97  const size_t size;
98  RegIndex opIndex() const { return data; }
99 
100  DataOp(RegIndex _data, size_t _size) : data(_data), size(_size) {}
101 };
102 
103 struct DataHiOp
104 {
106  const size_t size;
107  RegIndex opIndex() const { return dataHi; }
108 
109  DataHiOp(RegIndex data_hi, size_t _size) : dataHi(data_hi), size(_size) {}
110 };
111 
112 struct DataLowOp
113 {
115  const size_t size;
116  RegIndex opIndex() const { return dataLow; }
117 
118  DataLowOp(RegIndex data_low, size_t _size) : dataLow(data_low), size(_size)
119  {}
120 };
121 
122 template <class T, class Enabled=void>
123 struct HasDataSize : public std::false_type {};
124 
125 template <class T>
126 struct HasDataSize<T, decltype((void)&T::dataSize)> : public std::true_type {};
127 
128 template <class T>
130 
131 template <class Base>
132 struct IntOp : public Base
133 {
135 
136  template <class Inst>
137  IntOp(Inst *inst, std::enable_if_t<HasDataSizeV<Inst>, ArgType> idx) :
138  Base(idx.index, inst->dataSize)
139  {}
140 
141  template <class Inst>
142  IntOp(Inst *inst, std::enable_if_t<!HasDataSizeV<Inst>, ArgType> idx) :
143  Base(idx.index, inst)
144  {}
145 
146  void
147  print(std::ostream &os) const
148  {
149  X86StaticInst::printReg(os, intRegClass[this->opIndex()], this->size);
150  }
151 };
152 
153 template <class Base>
154 struct FoldedOp : public Base
155 {
157 
158  template <class InstType>
159  FoldedOp(InstType *inst, ArgType idx) :
160  Base(intRegFolded(idx.index, inst->foldOBit), inst->dataSize)
161  {}
162 
163  void
164  print(std::ostream &os) const
165  {
166  X86StaticInst::printReg(os, intRegClass[this->opIndex()], this->size);
167  }
168 };
169 
170 template <class Base>
171 struct CrOp : public Base
172 {
174 
175  template <class InstType>
176  CrOp(InstType *inst, ArgType idx) : Base(idx.index, 0) {}
177 
178  void
179  print(std::ostream &os) const
180  {
181  ccprintf(os, "cr%d", this->opIndex());
182  }
183 };
184 
185 template <class Base>
186 struct DbgOp : public Base
187 {
189 
190  template <class InstType>
191  DbgOp(InstType *inst, ArgType idx) : Base(idx.index, 0) {}
192 
193  void
194  print(std::ostream &os) const
195  {
196  ccprintf(os, "dr%d", this->opIndex());
197  }
198 
199 };
200 
201 template <class Base>
202 struct SegOp : public Base
203 {
205 
206  template <class InstType>
207  SegOp(InstType *inst, ArgType idx) : Base(idx.index, 0) {}
208 
209  void
210  print(std::ostream &os) const
211  {
212  X86StaticInst::printSegment(os, this->opIndex());
213  }
214 };
215 
216 template <class Base>
217 struct MiscOp : public Base
218 {
220 
221  template <class InstType>
222  MiscOp(InstType *inst, ArgType idx) : Base(idx.index, inst->dataSize) {}
223 
224  void
225  print(std::ostream &os) const
226  {
227  X86StaticInst::printReg(os, miscRegClass[this->opIndex()], this->size);
228  }
229 };
230 
231 template <class Base>
232 struct FloatOp : public Base
233 {
235 
236  template <class Inst>
237  FloatOp(Inst *inst, std::enable_if_t<HasDataSizeV<Inst>, ArgType> idx) :
238  Base(idx.index, inst->dataSize)
239  {}
240 
241  template <class Inst>
242  FloatOp(Inst *inst, std::enable_if_t<!HasDataSizeV<Inst>, ArgType> idx) :
243  Base(idx.index, inst)
244  {}
245 
246  void
247  print(std::ostream &os) const
248  {
249  X86StaticInst::printReg(os, floatRegClass[this->opIndex()],
250  this->size);
251  }
252 };
253 
261 
269 
273 
278 
279 struct Imm8Op
280 {
281  using ArgType = uint8_t;
282 
283  uint8_t imm8;
284 
285  template <class InstType>
286  Imm8Op(InstType *inst, ArgType _imm8) : imm8(_imm8) {}
287 
288  void
289  print(std::ostream &os) const
290  {
291  ccprintf(os, "%#x", imm8);
292  }
293 };
294 
295 struct Imm64Op
296 {
297  using ArgType = uint64_t;
298 
299  uint64_t imm64;
300 
301  template <class InstType>
302  Imm64Op(InstType *inst, ArgType _imm64) : imm64(_imm64) {}
303 
304  void
305  print(std::ostream &os) const
306  {
307  ccprintf(os, "%#x", imm64);
308  }
309 };
310 
311 struct UpcOp
312 {
313  using ArgType = MicroPC;
314 
316 
317  template <class InstType>
318  UpcOp(InstType *inst, ArgType _target) : target(_target) {}
319 
320  void
321  print(std::ostream &os) const
322  {
323  ccprintf(os, "%#x", target);
324  }
325 };
326 
327 struct FaultOp
328 {
329  using ArgType = Fault;
330 
332 
333  template <class InstType>
334  FaultOp(InstType *inst, ArgType _fault) : fault(_fault) {}
335 
336  void
337  print(std::ostream &os) const
338  {
339  ccprintf(os, fault ? fault->name() : "NoFault");
340  }
341 };
342 
343 struct AddrOp
344 {
345  struct ArgType
346  {
347  uint8_t scale;
350  uint64_t disp;
352  };
353 
354  const uint8_t scale;
356  const RegIndex base;
357  const uint64_t disp;
358  const uint8_t segment;
359  const size_t size;
360 
361  template <class InstType>
362  AddrOp(InstType *inst, const ArgType &args) : scale(args.scale),
363  index(intRegFolded(args.index.index, inst->foldABit)),
364  base(intRegFolded(args.base.index, inst->foldABit)),
365  disp(args.disp), segment(args.segment.index),
366  size(inst->addressSize)
367  {
368  assert(segment < segment_idx::NumIdxs);
369  }
370 
371  void
372  print(std::ostream &os) const
373  {
375  os, segment, scale, index, base, disp, size, false);
376  }
377 };
378 
379 template <typename Base, typename ...Operands>
380 class InstOperands : public Base, public Operands...
381 {
382  private:
383  using ArgTuple = std::tuple<typename Operands::ArgType...>;
384 
385  template <std::size_t ...I, typename ...CTorArgs>
386  InstOperands(std::index_sequence<I...>, ExtMachInst mach_inst,
387  const char *mnem, const char *inst_mnem, uint64_t set_flags,
388  OpClass op_class, [[maybe_unused]] ArgTuple args,
389  CTorArgs... ctor_args) :
390  Base(mach_inst, mnem, inst_mnem, set_flags, op_class, ctor_args...),
391  Operands(this, std::get<I>(args))...
392  {}
393 
394  protected:
395  template <typename ...CTorArgs>
396  InstOperands(ExtMachInst mach_inst, const char *mnem,
397  const char *inst_mnem, uint64_t set_flags, OpClass op_class,
398  ArgTuple args, CTorArgs... ctor_args) :
399  InstOperands(std::make_index_sequence<sizeof...(Operands)>{},
400  mach_inst, mnem, inst_mnem, set_flags, op_class,
401  std::move(args), ctor_args...)
402  {}
403 
404  std::string
406  const loader::SymbolTable *symtab) const override
407  {
408  std::stringstream response;
409  Base::printMnemonic(response, this->instMnem, this->mnemonic);
410  int count = 0;
411  GEM5_FOR_EACH_IN_PACK(ccprintf(response, count++ ? ", " : ""),
412  Operands::print(response));
413  return response.str();
414  }
415 };
416 
417 } // namespace X86ISA
418 } // namespace gem5
419 
420 #endif //__ARCH_X86_INSTS_MICROOP_ARGS_HH__
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
InstOperands(ExtMachInst mach_inst, const char *mnem, const char *inst_mnem, uint64_t set_flags, OpClass op_class, ArgTuple args, CTorArgs... ctor_args)
InstOperands(std::index_sequence< I... >, ExtMachInst mach_inst, const char *mnem, const char *inst_mnem, uint64_t set_flags, OpClass op_class, [[maybe_unused]] ArgTuple args, CTorArgs... ctor_args)
std::tuple< typename Operands::ArgType... > ArgTuple
static void printMem(std::ostream &os, uint8_t segment, uint8_t scale, RegIndex index, RegIndex base, uint64_t disp, uint8_t addressSize, bool rip)
Definition: static_inst.cc:258
static void printSegment(std::ostream &os, int segment)
Definition: static_inst.cc:63
static void printReg(std::ostream &os, RegId reg, int size)
Definition: static_inst.cc:142
Bitfield< 19 > pc
Definition: misc.hh:812
Bitfield< 17 > os
Definition: misc.hh:810
constexpr RegClass miscRegClass(MiscRegClass, MiscRegClassName, misc_reg::NumRegs, debug::MiscRegs)
constexpr RegClass intRegClass
Definition: int.hh:123
constexpr bool HasDataSizeV
Bitfield< 5, 3 > index
Definition: types.hh:98
static constexpr RegId intRegFolded(RegIndex index, RegIndex foldBit)
Definition: int.hh:187
constexpr RegClass floatRegClass
Definition: float.hh:143
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< FaultBase > Fault
Definition: types.hh:248
uint16_t RegIndex
Definition: types.hh:176
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint16_t MicroPC
Definition: types.hh:149
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
Overload hash function for BasicBlockRange type.
Definition: misc.hh:2826
const uint8_t scale
const uint64_t disp
const RegIndex index
void print(std::ostream &os) const
const uint8_t segment
AddrOp(InstType *inst, const ArgType &args)
const RegIndex base
CrOp(InstType *inst, ArgType idx)
void print(std::ostream &os) const
RegIndex opIndex() const
DataHiOp(RegIndex data_hi, size_t _size)
const RegIndex dataHi
const RegIndex dataLow
DataLowOp(RegIndex data_low, size_t _size)
RegIndex opIndex() const
const RegIndex data
Definition: microop_args.hh:96
DataOp(RegIndex _data, size_t _size)
RegIndex opIndex() const
Definition: microop_args.hh:98
void print(std::ostream &os) const
DbgOp(InstType *inst, ArgType idx)
DestOp(RegIndex _dest, InstType *inst)
Definition: microop_args.hh:63
const RegIndex dest
Definition: microop_args.hh:57
DestOp(RegIndex _dest, size_t _size)
Definition: microop_args.hh:61
RegIndex opIndex() const
Definition: microop_args.hh:59
void print(std::ostream &os) const
FaultOp(InstType *inst, ArgType _fault)
FloatOp(Inst *inst, std::enable_if_t< HasDataSizeV< Inst >, ArgType > idx)
FloatOp(Inst *inst, std::enable_if_t<!HasDataSizeV< Inst >, ArgType > idx)
void print(std::ostream &os) const
void print(std::ostream &os) const
FoldedOp(InstType *inst, ArgType idx)
Classes for register indices passed to instruction constructors.
Definition: static_inst.hh:61
void print(std::ostream &os) const
Imm64Op(InstType *inst, ArgType _imm64)
Imm8Op(InstType *inst, ArgType _imm8)
void print(std::ostream &os) const
IntOp(Inst *inst, std::enable_if_t<!HasDataSizeV< Inst >, ArgType > idx)
void print(std::ostream &os) const
IntOp(Inst *inst, std::enable_if_t< HasDataSizeV< Inst >, ArgType > idx)
MiscOp(InstType *inst, ArgType idx)
void print(std::ostream &os) const
SegOp(InstType *inst, ArgType idx)
void print(std::ostream &os) const
const RegIndex src1
Definition: microop_args.hh:70
Src1Op(RegIndex _src1, size_t _size)
Definition: microop_args.hh:74
Src1Op(RegIndex _src1, InstType *inst)
Definition: microop_args.hh:76
RegIndex opIndex() const
Definition: microop_args.hh:72
const RegIndex src2
Definition: microop_args.hh:83
Src2Op(RegIndex _src2, InstType *inst)
Definition: microop_args.hh:89
Src2Op(RegIndex _src2, size_t _size)
Definition: microop_args.hh:87
RegIndex opIndex() const
Definition: microop_args.hh:85
UpcOp(InstType *inst, ArgType _target)
void print(std::ostream &os) const

Generated on Wed Dec 21 2022 10:22:28 for gem5 by doxygen 1.9.1