gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
operand.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
3  * All rights reserved.
4  *
5  * For use for simulation and test purposes only
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its contributors
18  * may be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Author: Steve Reinhardt
34  */
35 
36 #include "arch/hsail/operand.hh"
37 
38 using namespace Brig;
39 
40 bool
41 BaseRegOperand::init(unsigned opOffset, const BrigObject *obj,
42  unsigned &maxRegIdx, char _regFileChar)
43 {
44  regFileChar = _regFileChar;
45  const BrigOperand *brigOp = obj->getOperand(opOffset);
46 
47  if (brigOp->kind != BRIG_KIND_OPERAND_REGISTER)
48  return false;
49 
50  const BrigOperandRegister *brigRegOp = (const BrigOperandRegister*)brigOp;
51 
52  regIdx = brigRegOp->regNum;
53 
54  DPRINTF(GPUReg, "Operand: regNum: %d, kind: %d\n", regIdx,
55  brigRegOp->regKind);
56 
57  maxRegIdx = std::max(maxRegIdx, regIdx);
58 
59  return true;
60 }
61 
62 void
63 ListOperand::init(unsigned opOffset, const BrigObject *obj)
64 {
65  const BrigOperand *brigOp = (const BrigOperand*)obj->getOperand(opOffset);
66 
67  switch (brigOp->kind) {
69  {
70  const BrigOperandCodeList *opList =
71  (const BrigOperandCodeList*)brigOp;
72 
73  const Brig::BrigData *oprnd_data =
74  obj->getBrigBaseData(opList->elements);
75 
76  // Note: for calls Dest list of operands could be size of 0.
77  elementCount = oprnd_data->byteCount / 4;
78 
79  DPRINTF(GPUReg, "Operand Code List: # elements: %d\n",
80  elementCount);
81 
82  for (int i = 0; i < elementCount; ++i) {
83  unsigned *data_offset =
84  (unsigned*)obj->getData(opList->elements + 4 * (i + 1));
85 
86  const BrigDirectiveVariable *p =
87  (const BrigDirectiveVariable*)obj->
88  getCodeSectionEntry(*data_offset);
89 
91  findSymbol(BRIG_SEGMENT_ARG, p);
92 
93  assert(se);
94  callArgs.push_back(se);
95  }
96  }
97  break;
98  default:
99  fatal("ListOperand: bad operand kind %d\n", brigOp->kind);
100  }
101 }
102 
103 std::string
105 {
106  std::string res_str("");
107 
108  for (auto it : callArgs) {
109  res_str += csprintf("%s ", it->name.c_str());
110  }
111 
112  return res_str;
113 }
114 
115 void
116 FunctionRefOperand::init(unsigned opOffset, const BrigObject *obj)
117 {
118  const BrigOperand *baseOp = obj->getOperand(opOffset);
119 
120  if (baseOp->kind != BRIG_KIND_OPERAND_CODE_REF) {
121  fatal("FunctionRefOperand: bad operand kind %d\n", baseOp->kind);
122  }
123 
124  const BrigOperandCodeRef *brigOp = (const BrigOperandCodeRef*)baseOp;
125 
126  const BrigDirectiveExecutable *p =
127  (const BrigDirectiveExecutable*)obj->getCodeSectionEntry(brigOp->ref);
128 
129  func_name = obj->getString(p->name);
130 }
131 
132 std::string
134 {
135  DPRINTF(GPUReg, "Operand Func-ref name: %s\n", func_name);
136 
137  return csprintf("%s", func_name);
138 }
139 
140 bool
141 BaseRegOperand::init_from_vect(unsigned opOffset, const BrigObject *obj,
142  int at, unsigned &maxRegIdx, char _regFileChar)
143 {
144  regFileChar = _regFileChar;
145  const BrigOperand *brigOp = obj->getOperand(opOffset);
146 
147  if (brigOp->kind != BRIG_KIND_OPERAND_OPERAND_LIST)
148  return false;
149 
150 
151  const Brig::BrigOperandOperandList *brigRegVecOp =
152  (const Brig::BrigOperandOperandList*)brigOp;
153 
154  unsigned *data_offset =
155  (unsigned*)obj->getData(brigRegVecOp->elements + 4 * (at + 1));
156 
157  const BrigOperand *p =
158  (const BrigOperand*)obj->getOperand(*data_offset);
159  if (p->kind != BRIG_KIND_OPERAND_REGISTER) {
160  return false;
161  }
162 
163  const BrigOperandRegister *brigRegOp =(const BrigOperandRegister*)p;
164 
165  regIdx = brigRegOp->regNum;
166 
167  DPRINTF(GPUReg, "Operand: regNum: %d, kind: %d \n", regIdx,
168  brigRegOp->regKind);
169 
170  maxRegIdx = std::max(maxRegIdx, regIdx);
171 
172  return true;
173 }
174 
175 void
176 BaseRegOperand::initWithStrOffset(unsigned strOffset, const BrigObject *obj,
177  unsigned &maxRegIdx, char _regFileChar)
178 {
179  const char *name = obj->getString(strOffset);
180  char *endptr;
181  regIdx = strtoul(name + 2, &endptr, 10);
182 
183  if (name[0] != '$' || name[1] != _regFileChar) {
184  fatal("register operand parse error on \"%s\"\n", name);
185  }
186 
187  maxRegIdx = std::max(maxRegIdx, regIdx);
188 }
189 
190 unsigned SRegOperand::maxRegIdx;
191 unsigned DRegOperand::maxRegIdx;
192 unsigned CRegOperand::maxRegIdx;
193 
194 std::string
196 {
197  return csprintf("$s%d", regIdx);
198 }
199 
200 std::string
202 {
203  return csprintf("$d%d", regIdx);
204 }
205 
206 std::string
208 {
209  return csprintf("$c%d", regIdx);
210 }
211 
213 findRegDataType(unsigned opOffset, const BrigObject *obj)
214 {
215  const BrigOperand *baseOp = obj->getOperand(opOffset);
216 
217  switch (baseOp->kind) {
219  {
220  const BrigOperandRegister *op = (BrigOperandRegister*)baseOp;
221 
222  return BrigRegOperandInfo((BrigKind16_t)baseOp->kind,
224  }
225  break;
226 
228  {
230  return BrigRegOperandInfo((BrigKind16_t)baseOp->kind, reg_kind);
231  }
232 
234  {
235  const BrigOperandOperandList *op =
236  (BrigOperandOperandList*)baseOp;
237  const BrigData *data_p = (BrigData*)obj->getData(op->elements);
238 
239 
240  int num_operands = 0;
241  BrigRegisterKind reg_kind = (BrigRegisterKind)0;
242  for (int offset = 0; offset < data_p->byteCount; offset += 4) {
243  const BrigOperand *op_p = (const BrigOperand *)
244  obj->getOperand(((int *)data_p->bytes)[offset/4]);
245 
246  if (op_p->kind == BRIG_KIND_OPERAND_REGISTER) {
247  const BrigOperandRegister *brigRegOp =
248  (const BrigOperandRegister*)op_p;
249  reg_kind = (BrigRegisterKind)brigRegOp->regKind;
250  } else if (op_p->kind == BRIG_KIND_OPERAND_CONSTANT_BYTES) {
251  uint16_t num_bytes =
252  ((Brig::BrigOperandConstantBytes*)op_p)->base.byteCount
253  - sizeof(BrigBase);
254  if (num_bytes == sizeof(uint32_t)) {
255  reg_kind = BRIG_REGISTER_KIND_SINGLE;
256  } else if (num_bytes == sizeof(uint64_t)) {
257  reg_kind = BRIG_REGISTER_KIND_DOUBLE;
258  } else {
259  fatal("OperandList: bad operand size %d\n", num_bytes);
260  }
261  } else if (op_p->kind == BRIG_KIND_OPERAND_WAVESIZE) {
262  reg_kind = BRIG_REGISTER_KIND_DOUBLE;
263  } else {
264  fatal("OperandList: bad operand kind %d\n", op_p->kind);
265  }
266 
267  num_operands++;
268  }
269  assert(baseOp->kind == BRIG_KIND_OPERAND_OPERAND_LIST);
270 
271  return BrigRegOperandInfo((BrigKind16_t)baseOp->kind, reg_kind);
272  }
273  break;
274 
276  {
277  const BrigOperandAddress *op = (BrigOperandAddress*)baseOp;
278 
279  if (!op->reg) {
281 
282  if (op->symbol) {
283  const BrigDirective *dir = (BrigDirective*)
284  obj->getCodeSectionEntry(op->symbol);
285 
286  assert(dir->kind == BRIG_KIND_DIRECTIVE_VARIABLE);
287 
288  const BrigDirectiveVariable *sym =
289  (const BrigDirectiveVariable*)dir;
290 
291  type = (BrigType)sym->type;
292  }
294  (BrigType)type);
295  } else {
296  const BrigOperandAddress *b = (const BrigOperandAddress*)baseOp;
297  const BrigOperand *reg = obj->getOperand(b->reg);
298  const BrigOperandRegister *rop = (BrigOperandRegister*)reg;
299 
301  (BrigRegisterKind)rop->regKind);
302  }
303  }
304  break;
305 
306  default:
307  fatal("AddrOperand: bad operand kind %d\n", baseOp->kind);
308  break;
309  }
310 }
311 
312 void
314 {
315  assert(op->base.kind == BRIG_KIND_OPERAND_ADDRESS);
316 
317  const BrigDirective *d =
319 
329  warn("HSAIL implementation does not support instructions with "
330  "address calculations where the operand is not a variable\n");
331  }
332 
334  name = obj->getString(sym->name);
335 
336  if (sym->segment != BRIG_SEGMENT_ARG) {
337  storageElement =
339  offset = 0;
340  } else {
341  // sym->name does not work for BRIG_SEGMENT_ARG for the following case:
342  //
343  // void foo(int a);
344  // void bar(double a);
345  //
346  // foo(...) --> arg_u32 %param_p0;
347  // st_arg_u32 $s0, [%param_p0];
348  // call &foo (%param_p0);
349  // bar(...) --> arg_f64 %param_p0;
350  // st_arg_u64 $d0, [%param_p0];
351  // call &foo (%param_p0);
352  //
353  // Both functions use the same variable name (param_p0)!!!
354  //
355  // Maybe this is a bug in the compiler (I don't know).
356  //
357  // Solution:
358  // Use directive pointer (BrigDirectiveVariable) to differentiate 2
359  // versions of param_p0.
360  //
361  // Note this solution is kind of stupid, because we are pulling stuff
362  // out of the brig binary via the directive pointer and putting it into
363  // the symbol table, but now we are indexing the symbol table by the
364  // brig directive pointer! It makes the symbol table sort of pointless.
365  // But I don't want to mess with the rest of the infrastructure, so
366  // let's go with this for now.
367  //
368  // When we update the compiler again, we should see if this problem goes
369  // away. If so, we can fold some of this functionality into the code for
370  // kernel arguments. If not, maybe we can index the symbol name on a
371  // hash of the variable AND function name
372  storageElement = obj->currentCode->
373  storageMap->findSymbol((Brig::BrigSegment)sym->segment, sym);
374 
375  assert(storageElement);
376  }
377 }
378 
379 uint64_t
381 {
382  // start with offset, will be 0 if not specified
383  uint64_t address = offset;
384 
385  // add in symbol value if specified
386  if (storageElement) {
387  address += storageElement->offset;
388  }
389 
390  return address;
391 }
392 
393 std::string
394 AddrOperandBase::disassemble(std::string reg_disassembly)
395 {
396  std::string disasm;
397 
398  if (offset || reg_disassembly != "") {
399  disasm += "[";
400 
401  if (reg_disassembly != "") {
402  disasm += reg_disassembly;
403 
404  if (offset > 0) {
405  disasm += "+";
406  }
407  }
408 
409  if (offset) {
410  disasm += csprintf("%d", offset);
411  }
412 
413  disasm += "]";
414  } else if (name) {
415  disasm += csprintf("[%s]", name);
416  }
417 
418  return disasm;
419 }
420 
421 void
422 NoRegAddrOperand::init(unsigned opOffset, const BrigObject *obj)
423 {
424  const BrigOperand *baseOp = obj->getOperand(opOffset);
425 
426  if (baseOp->kind == BRIG_KIND_OPERAND_ADDRESS) {
427  BrigOperandAddress *addrOp = (BrigOperandAddress*)baseOp;
428  parseAddr(addrOp, obj);
429  offset = (uint64_t(addrOp->offset.hi) << 32) |
430  uint64_t(addrOp->offset.lo);
431  } else {
432  fatal("NoRegAddrOperand: bad operand kind %d\n", baseOp->kind);
433  }
434 
435 }
436 
437 std::string
439 {
440  return AddrOperandBase::disassemble(std::string(""));
441 }
442 
443 void
444 LabelOperand::init(unsigned opOffset, const BrigObject *obj)
445 {
446  const BrigOperandCodeRef *op =
447  (const BrigOperandCodeRef*)obj->getOperand(opOffset);
448 
449  assert(op->base.kind == BRIG_KIND_OPERAND_CODE_REF);
450 
451  const BrigDirective *dir =
452  (const BrigDirective*)obj->getCodeSectionEntry(op->ref);
453 
454  assert(dir->kind == BRIG_KIND_DIRECTIVE_LABEL);
455  label = obj->currentCode->refLabel((BrigDirectiveLabel*)dir, obj);
456 }
457 
458 uint32_t
460 {
461  return label->get();
462 }
463 
464 std::string
466 {
467  return label->name;
468 }
HsailCode * currentCode
Definition: brig_object.hh:118
#define DPRINTF(x,...)
Definition: trace.hh:212
void init(unsigned opOffset, const BrigObject *obj)
Definition: operand.cc:63
uint32_t getTarget(Wavefront *w, int lane)
Definition: operand.cc:459
BrigDataOffsetCodeList32_t elements
Definition: Brig.h:1476
Bitfield< 5, 3 > reg
Definition: types.hh:89
const Brig::BrigOperand * getOperand(int offs) const
Definition: brig_object.cc:116
Defines classes encapsulating HSAIL instruction operands.
std::string disassemble()
Definition: operand.cc:438
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
void init(unsigned opOffset, const BrigObject *obj)
Definition: operand.cc:422
uint16_t BrigKind16_t
Definition: Brig.h:102
Label * refLabel(const Brig::BrigDirectiveLabel *lbl, const BrigObject *obj)
Definition: hsail_code.hh:441
std::string disassemble(std::string reg_disassembly)
Definition: operand.cc:394
void init(unsigned opOffset, const BrigObject *obj)
Definition: operand.cc:116
std::string disassemble()
Definition: operand.cc:195
Bitfield< 23, 0 > offset
Definition: types.hh:149
BrigCodeOffset32_t ref
Definition: Brig.h:1486
StorageElement * findSymbol(Brig::BrigSegment segment, std::string name)
Definition: hsail_code.cc:404
static unsigned maxRegIdx
Definition: operand.hh:292
std::string disassemble()
Definition: operand.cc:104
std::string disassemble()
Definition: operand.cc:201
const uint8_t * getData(int offs) const
Definition: brig_object.cc:110
static unsigned maxRegIdx
Definition: operand.hh:228
std::string disassemble()
Definition: operand.cc:465
BrigCodeOffset32_t symbol
Definition: Brig.h:1463
BrigKind16_t kind
Definition: Brig.h:1180
#define warn(...)
Definition: misc.hh:219
BrigUInt64 offset
Definition: Brig.h:1465
Bitfield< 7 > b
Definition: miscregs.hh:1564
uint32_t lo
Definition: Brig.h:1164
const char * getString(int offs) const
Definition: brig_object.cc:92
BrigType
Definition: Brig.h:974
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
void init(unsigned opOffset, const BrigObject *obj)
Definition: operand.cc:444
StorageElement * findSymbol(Brig::BrigSegment segment, uint64_t addr)
Definition: hsail_code.hh:429
Bitfield< 9 > d
Definition: miscregs.hh:1375
#define fatal(...)
Definition: misc.hh:163
StorageMap * storageMap
Definition: hsail_code.hh:326
Bitfield< 14, 13 > at
std::string disassemble()
Definition: operand.cc:207
Bitfield< 0 > w
const Brig::BrigBase * getCodeSectionEntry(int offs) const
Definition: brig_object.cc:98
BrigRegisterKind
Definition: Brig.h:795
BrigSegment
Definition: Brig.h:925
static unsigned maxRegIdx
Definition: operand.hh:123
type
Definition: misc.hh:728
void parseAddr(const Brig::BrigOperandAddress *op, const BrigObject *obj)
Definition: operand.cc:313
const Brig::BrigData * getBrigBaseData(int offs) const
Definition: brig_object.cc:104
uint32_t byteCount
Definition: Brig.h:1189
BrigSegment8_t segment
Definition: Brig.h:1299
BrigDataOffsetOperandList32_t elements
Definition: Brig.h:1523
uint32_t hi
Definition: Brig.h:1165
std::string disassemble()
Definition: operand.cc:133
void initWithStrOffset(unsigned strOffset, const BrigObject *obj, unsigned &maxRegIdx, char _regFileChar)
Definition: operand.cc:176
bool init(unsigned opOffset, const BrigObject *obj, unsigned &maxRegIdx, char _regFileChar)
Definition: operand.cc:41
BrigDataOffsetString32_t name
Definition: Brig.h:1289
uint64_t calcUniformBase()
Definition: operand.cc:380
BrigRegOperandInfo findRegDataType(unsigned opOffset, const BrigObject *obj)
Definition: operand.cc:213
Bitfield< 4 > op
Definition: types.hh:80
BrigDataOffsetString32_t name
Definition: Brig.h:1237
bool init_from_vect(unsigned opOffset, const BrigObject *obj, int at, unsigned &maxRegIdx, char _regFileChar)
Definition: operand.cc:141
Bitfield< 0 > p
BrigRegisterKind16_t regKind
Definition: Brig.h:1533
uint8_t bytes[1]
Definition: Brig.h:1190
BrigOperandOffset32_t reg
Definition: Brig.h:1464

Generated on Fri Jun 9 2017 13:03:39 for gem5 by doxygen 1.8.6