arch-gcn3: Fix operand size reporting for Flat insts
[gem5.git] / src / arch / sparc / insts / static_inst.cc
1 /*
2 * Copyright (c) 2006-2007 The Regents of The University of Michigan
3 * All rights reserved
4 * Copyright 2017 Google Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "arch/sparc/insts/static_inst.hh"
31
32 namespace SparcISA
33 {
34
35 const char *CondTestAbbrev[] =
36 {
37 [Never] = "nev",
38 [Equal] = "e",
39 [LessOrEqual] = "le",
40 [Less] = "l",
41 [LessOrEqualUnsigned] = "leu",
42 [CarrySet] = "c",
43 [Negative] = "n",
44 [OverflowSet] = "o",
45 [Always] = "a",
46 [NotEqual] = "ne",
47 [Greater] = "g",
48 [GreaterOrEqual] = "ge",
49 [GreaterUnsigned] = "gu",
50 [CarryClear] = "cc",
51 [Positive] = "p",
52 [OverflowClear] = "oc"
53 };
54
55 void
56 SparcStaticInst::printMnemonic(std::ostream &os, const char *mnemonic)
57 {
58 ccprintf(os, "\t%s ", mnemonic);
59 }
60
61 void
62 SparcStaticInst::printRegArray(std::ostream &os, const RegId indexArray[],
63 int num) const
64 {
65 if (num <= 0)
66 return;
67 printReg(os, indexArray[0]);
68 for (int x = 1; x < num; x++) {
69 os << ", ";
70 printReg(os, indexArray[x]);
71 }
72 }
73
74 void
75 SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
76 {
77 pcState.advance();
78 }
79
80 void
81 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
82 {
83 if (_numSrcRegs > reg)
84 printReg(os, _srcRegIdx[reg]);
85 }
86
87 void
88 SparcStaticInst::printDestReg(std::ostream &os, int reg) const
89 {
90 if (_numDestRegs > reg)
91 printReg(os, _destRegIdx[reg]);
92 }
93
94 void
95 SparcStaticInst::printReg(std::ostream &os, RegId reg)
96 {
97 const int MaxGlobal = 8;
98 const int MaxOutput = 16;
99 const int MaxLocal = 24;
100 const int MaxInput = 32;
101 const int MaxMicroReg = 40;
102 RegIndex reg_idx = reg.index();
103 if (reg.isIntReg()) {
104 // If we used a register from the next or previous window,
105 // take out the offset.
106 while (reg_idx >= MaxMicroReg)
107 reg_idx -= MaxMicroReg;
108 if (reg_idx == FramePointerReg)
109 ccprintf(os, "%%fp");
110 else if (reg_idx == StackPointerReg)
111 ccprintf(os, "%%sp");
112 else if (reg_idx < MaxGlobal)
113 ccprintf(os, "%%g%d", reg_idx);
114 else if (reg_idx < MaxOutput)
115 ccprintf(os, "%%o%d", reg_idx - MaxGlobal);
116 else if (reg_idx < MaxLocal)
117 ccprintf(os, "%%l%d", reg_idx - MaxOutput);
118 else if (reg_idx < MaxInput)
119 ccprintf(os, "%%i%d", reg_idx - MaxLocal);
120 else if (reg_idx < MaxMicroReg)
121 ccprintf(os, "%%u%d", reg_idx - MaxInput);
122 // The fake int regs that are really control regs
123 else {
124 switch (reg_idx - MaxMicroReg) {
125 case 1:
126 ccprintf(os, "%%y");
127 break;
128 case 2:
129 ccprintf(os, "%%ccr");
130 break;
131 case 3:
132 ccprintf(os, "%%cansave");
133 break;
134 case 4:
135 ccprintf(os, "%%canrestore");
136 break;
137 case 5:
138 ccprintf(os, "%%cleanwin");
139 break;
140 case 6:
141 ccprintf(os, "%%otherwin");
142 break;
143 case 7:
144 ccprintf(os, "%%wstate");
145 break;
146 }
147 }
148 } else if (reg.isFloatReg()) {
149 ccprintf(os, "%%f%d", reg_idx);
150 } else {
151 switch (reg_idx) {
152 case MISCREG_ASI:
153 ccprintf(os, "%%asi");
154 break;
155 case MISCREG_FPRS:
156 ccprintf(os, "%%fprs");
157 break;
158 case MISCREG_PCR:
159 ccprintf(os, "%%pcr");
160 break;
161 case MISCREG_PIC:
162 ccprintf(os, "%%pic");
163 break;
164 case MISCREG_GSR:
165 ccprintf(os, "%%gsr");
166 break;
167 case MISCREG_SOFTINT:
168 ccprintf(os, "%%softint");
169 break;
170 case MISCREG_SOFTINT_SET:
171 ccprintf(os, "%%softint_set");
172 break;
173 case MISCREG_SOFTINT_CLR:
174 ccprintf(os, "%%softint_clr");
175 break;
176 case MISCREG_TICK_CMPR:
177 ccprintf(os, "%%tick_cmpr");
178 break;
179 case MISCREG_STICK:
180 ccprintf(os, "%%stick");
181 break;
182 case MISCREG_STICK_CMPR:
183 ccprintf(os, "%%stick_cmpr");
184 break;
185 case MISCREG_TPC:
186 ccprintf(os, "%%tpc");
187 break;
188 case MISCREG_TNPC:
189 ccprintf(os, "%%tnpc");
190 break;
191 case MISCREG_TSTATE:
192 ccprintf(os, "%%tstate");
193 break;
194 case MISCREG_TT:
195 ccprintf(os, "%%tt");
196 break;
197 case MISCREG_TICK:
198 ccprintf(os, "%%tick");
199 break;
200 case MISCREG_TBA:
201 ccprintf(os, "%%tba");
202 break;
203 case MISCREG_PSTATE:
204 ccprintf(os, "%%pstate");
205 break;
206 case MISCREG_TL:
207 ccprintf(os, "%%tl");
208 break;
209 case MISCREG_PIL:
210 ccprintf(os, "%%pil");
211 break;
212 case MISCREG_CWP:
213 ccprintf(os, "%%cwp");
214 break;
215 case MISCREG_GL:
216 ccprintf(os, "%%gl");
217 break;
218 case MISCREG_HPSTATE:
219 ccprintf(os, "%%hpstate");
220 break;
221 case MISCREG_HTSTATE:
222 ccprintf(os, "%%htstate");
223 break;
224 case MISCREG_HINTP:
225 ccprintf(os, "%%hintp");
226 break;
227 case MISCREG_HTBA:
228 ccprintf(os, "%%htba");
229 break;
230 case MISCREG_HSTICK_CMPR:
231 ccprintf(os, "%%hstick_cmpr");
232 break;
233 case MISCREG_HVER:
234 ccprintf(os, "%%hver");
235 break;
236 case MISCREG_STRAND_STS_REG:
237 ccprintf(os, "%%strand_sts_reg");
238 break;
239 case MISCREG_FSR:
240 ccprintf(os, "%%fsr");
241 break;
242 default:
243 ccprintf(os, "%%ctrl%d", reg_idx);
244 }
245 }
246 }
247
248 std::string
249 SparcStaticInst::generateDisassembly(
250 Addr pc, const Loader::SymbolTable *symtab) const
251 {
252 std::stringstream ss;
253
254 printMnemonic(ss, mnemonic);
255
256 // just print the first two source regs... if there's
257 // a third one, it's a read-modify-write dest (Rc),
258 // e.g. for CMOVxx
259 if (_numSrcRegs > 0)
260 printReg(ss, _srcRegIdx[0]);
261 if (_numSrcRegs > 1) {
262 ss << ",";
263 printReg(ss, _srcRegIdx[1]);
264 }
265
266 // just print the first dest... if there's a second one,
267 // it's generally implicit
268 if (_numDestRegs > 0) {
269 if (_numSrcRegs > 0)
270 ss << ",";
271 printReg(ss, _destRegIdx[0]);
272 }
273
274 return ss.str();
275 }
276
277 bool
278 SparcStaticInst::passesFpCondition(uint32_t fcc, uint32_t condition)
279 {
280 bool u = (fcc == 3);
281 bool g = (fcc == 2);
282 bool l = (fcc == 1);
283 bool e = (fcc == 0);
284
285 switch (condition) {
286 case FAlways:
287 return 1;
288 case FNever:
289 return 0;
290 case FUnordered:
291 return u;
292 case FGreater:
293 return g;
294 case FUnorderedOrGreater:
295 return u || g;
296 case FLess:
297 return l;
298 case FUnorderedOrLess:
299 return u || l;
300 case FLessOrGreater:
301 return l || g;
302 case FNotEqual:
303 return l || g || u;
304 case FEqual:
305 return e;
306 case FUnorderedOrEqual:
307 return u || e;
308 case FGreaterOrEqual:
309 return g || e;
310 case FUnorderedOrGreaterOrEqual:
311 return u || g || e;
312 case FLessOrEqual:
313 return l || e;
314 case FUnorderedOrLessOrEqual:
315 return u || l || e;
316 case FOrdered:
317 return e || l || g;
318 }
319 panic("Tried testing condition nonexistant condition code %d", condition);
320 }
321
322 bool
323 SparcStaticInst::passesCondition(uint32_t codes, uint32_t condition)
324 {
325 BitUnion32(CondCodes)
326 Bitfield<0> c;
327 Bitfield<1> v;
328 Bitfield<2> z;
329 Bitfield<3> n;
330 EndBitUnion(CondCodes)
331 CondCodes condCodes = codes;
332
333 switch (condition) {
334 case Always:
335 return true;
336 case Never:
337 return false;
338 case NotEqual:
339 return !condCodes.z;
340 case Equal:
341 return condCodes.z;
342 case Greater:
343 return !(condCodes.z | (condCodes.n ^ condCodes.v));
344 case LessOrEqual:
345 return condCodes.z | (condCodes.n ^ condCodes.v);
346 case GreaterOrEqual:
347 return !(condCodes.n ^ condCodes.v);
348 case Less:
349 return (condCodes.n ^ condCodes.v);
350 case GreaterUnsigned:
351 return !(condCodes.c | condCodes.z);
352 case LessOrEqualUnsigned:
353 return (condCodes.c | condCodes.z);
354 case CarryClear:
355 return !condCodes.c;
356 case CarrySet:
357 return condCodes.c;
358 case Positive:
359 return !condCodes.n;
360 case Negative:
361 return condCodes.n;
362 case OverflowClear:
363 return !condCodes.v;
364 case OverflowSet:
365 return condCodes.v;
366 }
367 panic("Tried testing condition nonexistant "
368 "condition code %d", condition);
369 }
370
371 }