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 * Authors: Gabe Black
30 */
31
32#include "arch/sparc/insts/static_inst.hh"
33
34namespace SparcISA
35{
36
37const char *CondTestAbbrev[] =
38{
39    [Never] = "nev",
40    [Equal] = "e",
41    [LessOrEqual] = "le",
42    [Less] = "l",
43    [LessOrEqualUnsigned] = "leu",
44    [CarrySet] = "c",
45    [Negative] = "n",
46    [OverflowSet] = "o",
47    [Always] = "a",
48    [NotEqual] = "ne",
49    [Greater] = "g",
50    [GreaterOrEqual] = "ge",
51    [GreaterUnsigned] = "gu",
52    [CarryClear] = "cc",
53    [Positive] = "p",
54    [OverflowClear] = "oc"
55};
56
57void
58SparcStaticInst::printMnemonic(std::ostream &os, const char *mnemonic)
59{
60    ccprintf(os, "\t%s   ", mnemonic);
61}
62
63void
64SparcStaticInst::printRegArray(std::ostream &os, const RegId indexArray[],
65                               int num) const
66{
67    if (num <= 0)
68        return;
69    printReg(os, indexArray[0]);
70    for (int x = 1; x < num; x++) {
71        os << ", ";
72        printReg(os, indexArray[x]);
73    }
74}
75
76void
77SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
78{
79    pcState.advance();
80}
81
82void
83SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
84{
85    if (_numSrcRegs > reg)
86        printReg(os, _srcRegIdx[reg]);
87}
88
89void
90SparcStaticInst::printDestReg(std::ostream &os, int reg) const
91{
92    if (_numDestRegs > reg)
93        printReg(os, _destRegIdx[reg]);
94}
95
96void
97SparcStaticInst::printReg(std::ostream &os, RegId reg)
98{
99    const int MaxGlobal = 8;
100    const int MaxOutput = 16;
101    const int MaxLocal = 24;
102    const int MaxInput = 32;
103    const int MaxMicroReg = 40;
104    RegIndex reg_idx = reg.index();
105    if (reg.isIntReg()) {
106        // If we used a register from the next or previous window,
107        // take out the offset.
108        while (reg_idx >= MaxMicroReg)
109            reg_idx -= MaxMicroReg;
110        if (reg_idx == FramePointerReg)
111            ccprintf(os, "%%fp");
112        else if (reg_idx == StackPointerReg)
113            ccprintf(os, "%%sp");
114        else if (reg_idx < MaxGlobal)
115            ccprintf(os, "%%g%d", reg_idx);
116        else if (reg_idx < MaxOutput)
117            ccprintf(os, "%%o%d", reg_idx - MaxGlobal);
118        else if (reg_idx < MaxLocal)
119            ccprintf(os, "%%l%d", reg_idx - MaxOutput);
120        else if (reg_idx < MaxInput)
121            ccprintf(os, "%%i%d", reg_idx - MaxLocal);
122        else if (reg_idx < MaxMicroReg)
123            ccprintf(os, "%%u%d", reg_idx - MaxInput);
124        // The fake int regs that are really control regs
125        else {
126            switch (reg_idx - MaxMicroReg) {
127              case 1:
128                ccprintf(os, "%%y");
129                break;
130              case 2:
131                ccprintf(os, "%%ccr");
132                break;
133              case 3:
134                ccprintf(os, "%%cansave");
135                break;
136              case 4:
137                ccprintf(os, "%%canrestore");
138                break;
139              case 5:
140                ccprintf(os, "%%cleanwin");
141                break;
142              case 6:
143                ccprintf(os, "%%otherwin");
144                break;
145              case 7:
146                ccprintf(os, "%%wstate");
147                break;
148            }
149        }
150    } else if (reg.isFloatReg()) {
151        ccprintf(os, "%%f%d", reg_idx);
152    } else {
153        switch (reg_idx) {
154          case MISCREG_ASI:
155            ccprintf(os, "%%asi");
156            break;
157          case MISCREG_FPRS:
158            ccprintf(os, "%%fprs");
159            break;
160          case MISCREG_PCR:
161            ccprintf(os, "%%pcr");
162            break;
163          case MISCREG_PIC:
164            ccprintf(os, "%%pic");
165            break;
166          case MISCREG_GSR:
167            ccprintf(os, "%%gsr");
168            break;
169          case MISCREG_SOFTINT:
170            ccprintf(os, "%%softint");
171            break;
172          case MISCREG_SOFTINT_SET:
173            ccprintf(os, "%%softint_set");
174            break;
175          case MISCREG_SOFTINT_CLR:
176            ccprintf(os, "%%softint_clr");
177            break;
178          case MISCREG_TICK_CMPR:
179            ccprintf(os, "%%tick_cmpr");
180            break;
181          case MISCREG_STICK:
182            ccprintf(os, "%%stick");
183            break;
184          case MISCREG_STICK_CMPR:
185            ccprintf(os, "%%stick_cmpr");
186            break;
187          case MISCREG_TPC:
188            ccprintf(os, "%%tpc");
189            break;
190          case MISCREG_TNPC:
191            ccprintf(os, "%%tnpc");
192            break;
193          case MISCREG_TSTATE:
194            ccprintf(os, "%%tstate");
195            break;
196          case MISCREG_TT:
197            ccprintf(os, "%%tt");
198            break;
199          case MISCREG_TICK:
200            ccprintf(os, "%%tick");
201            break;
202          case MISCREG_TBA:
203            ccprintf(os, "%%tba");
204            break;
205          case MISCREG_PSTATE:
206            ccprintf(os, "%%pstate");
207            break;
208          case MISCREG_TL:
209            ccprintf(os, "%%tl");
210            break;
211          case MISCREG_PIL:
212            ccprintf(os, "%%pil");
213            break;
214          case MISCREG_CWP:
215            ccprintf(os, "%%cwp");
216            break;
217          case MISCREG_GL:
218            ccprintf(os, "%%gl");
219            break;
220          case MISCREG_HPSTATE:
221            ccprintf(os, "%%hpstate");
222            break;
223          case MISCREG_HTSTATE:
224            ccprintf(os, "%%htstate");
225            break;
226          case MISCREG_HINTP:
227            ccprintf(os, "%%hintp");
228            break;
229          case MISCREG_HTBA:
230            ccprintf(os, "%%htba");
231            break;
232          case MISCREG_HSTICK_CMPR:
233            ccprintf(os, "%%hstick_cmpr");
234            break;
235          case MISCREG_HVER:
236            ccprintf(os, "%%hver");
237            break;
238          case MISCREG_STRAND_STS_REG:
239            ccprintf(os, "%%strand_sts_reg");
240            break;
241          case MISCREG_FSR:
242            ccprintf(os, "%%fsr");
243            break;
244          default:
245            ccprintf(os, "%%ctrl%d", reg_idx);
246        }
247    }
248}
249
250std::string
251SparcStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
252{
253    std::stringstream ss;
254
255    printMnemonic(ss, mnemonic);
256
257    // just print the first two source regs... if there's
258    // a third one, it's a read-modify-write dest (Rc),
259    // e.g. for CMOVxx
260    if (_numSrcRegs > 0)
261        printReg(ss, _srcRegIdx[0]);
262    if (_numSrcRegs > 1) {
263        ss << ",";
264        printReg(ss, _srcRegIdx[1]);
265    }
266
267    // just print the first dest... if there's a second one,
268    // it's generally implicit
269    if (_numDestRegs > 0) {
270        if (_numSrcRegs > 0)
271            ss << ",";
272        printReg(ss, _destRegIdx[0]);
273    }
274
275    return ss.str();
276}
277
278bool
279SparcStaticInst::passesFpCondition(uint32_t fcc, uint32_t condition)
280{
281    bool u = (fcc == 3);
282    bool g = (fcc == 2);
283    bool l = (fcc == 1);
284    bool e = (fcc == 0);
285
286    switch (condition) {
287      case FAlways:
288        return 1;
289      case FNever:
290        return 0;
291      case FUnordered:
292        return u;
293      case FGreater:
294        return g;
295      case FUnorderedOrGreater:
296        return u || g;
297      case FLess:
298        return l;
299      case FUnorderedOrLess:
300        return u || l;
301      case FLessOrGreater:
302        return l || g;
303      case FNotEqual:
304        return l || g || u;
305      case FEqual:
306        return e;
307      case FUnorderedOrEqual:
308        return u || e;
309      case FGreaterOrEqual:
310        return g || e;
311      case FUnorderedOrGreaterOrEqual:
312        return u || g || e;
313      case FLessOrEqual:
314        return l || e;
315      case FUnorderedOrLessOrEqual:
316        return u || l || e;
317      case FOrdered:
318        return e || l || g;
319    }
320    panic("Tried testing condition nonexistant condition code %d", condition);
321}
322
323bool
324SparcStaticInst::passesCondition(uint32_t codes, uint32_t condition)
325{
326    BitUnion32(CondCodes)
327        Bitfield<0> c;
328        Bitfield<1> v;
329        Bitfield<2> z;
330        Bitfield<3> n;
331    EndBitUnion(CondCodes)
332    CondCodes condCodes = codes;
333
334    switch (condition) {
335      case Always:
336        return true;
337      case Never:
338        return false;
339      case NotEqual:
340        return !condCodes.z;
341      case Equal:
342        return condCodes.z;
343      case Greater:
344        return !(condCodes.z | (condCodes.n ^ condCodes.v));
345      case LessOrEqual:
346        return condCodes.z | (condCodes.n ^ condCodes.v);
347      case GreaterOrEqual:
348        return !(condCodes.n ^ condCodes.v);
349      case Less:
350        return (condCodes.n ^ condCodes.v);
351      case GreaterUnsigned:
352        return !(condCodes.c | condCodes.z);
353      case LessOrEqualUnsigned:
354        return (condCodes.c | condCodes.z);
355      case CarryClear:
356        return !condCodes.c;
357      case CarrySet:
358        return condCodes.c;
359      case Positive:
360        return !condCodes.n;
361      case Negative:
362        return condCodes.n;
363      case OverflowClear:
364        return !condCodes.v;
365      case OverflowSet:
366        return condCodes.v;
367    }
368    panic("Tried testing condition nonexistant "
369            "condition code %d", condition);
370}
371
372}
373