base.isa revision 4172:141705d83494
1// Copyright (c) 2006-2007 The Regents of The University of Michigan
2// All rights reserved.
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// Authors: Ali Saidi
28//          Gabe Black
29//          Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Base class for sparc instructions, and some support functions
34//
35
36output header {{
37
38        union CondCodes
39        {
40            struct
41            {
42                uint8_t c:1;
43                uint8_t v:1;
44                uint8_t z:1;
45                uint8_t n:1;
46            };
47            uint32_t bits;
48        };
49
50        enum CondTest
51        {
52            Always=0x8,
53            Never=0x0,
54            NotEqual=0x9,
55            Equal=0x1,
56            Greater=0xA,
57            LessOrEqual=0x2,
58            GreaterOrEqual=0xB,
59            Less=0x3,
60            GreaterUnsigned=0xC,
61            LessOrEqualUnsigned=0x4,
62            CarryClear=0xD,
63            CarrySet=0x5,
64            Positive=0xE,
65            Negative=0x6,
66            OverflowClear=0xF,
67            OverflowSet=0x7
68        };
69
70        enum FpCondTest
71        {
72            FAlways=0x8,
73            FNever=0x0,
74            FUnordered=0x7,
75            FGreater=0x6,
76            FUnorderedOrGreater=0x5,
77            FLess=0x4,
78            FUnorderedOrLess=0x3,
79            FLessOrGreater=0x2,
80            FNotEqual=0x1,
81            FEqual=0x9,
82            FUnorderedOrEqual=0xA,
83            FGreaterOrEqual=0xB,
84            FUnorderedOrGreaterOrEqual=0xC,
85            FLessOrEqual=0xD,
86            FUnorderedOrLessOrEqual=0xE,
87            FOrdered=0xF
88        };
89
90        extern char * CondTestAbbrev[];
91
92        /**
93         * Base class for all SPARC static instructions.
94         */
95        class SparcStaticInst : public StaticInst
96        {
97          protected:
98            // Constructor.
99            SparcStaticInst(const char *mnem,
100                 ExtMachInst _machInst, OpClass __opClass)
101                    : StaticInst(mnem, _machInst, __opClass)
102                {
103                }
104
105            std::string generateDisassembly(Addr pc,
106                const SymbolTable *symtab) const;
107
108            void printReg(std::ostream &os, int reg) const;
109            void printSrcReg(std::ostream &os, int reg) const;
110            void printDestReg(std::ostream &os, int reg) const;
111
112            void printRegArray(std::ostream &os,
113                const RegIndex indexArray[], int num) const;
114        };
115
116        bool passesFpCondition(uint32_t fcc, uint32_t condition);
117
118        bool passesCondition(uint32_t codes, uint32_t condition);
119
120        inline int64_t sign_ext(uint64_t data, int origWidth)
121        {
122            int shiftAmount = 64 - origWidth;
123            return (((int64_t)data) << shiftAmount) >> shiftAmount;
124        }
125}};
126
127output decoder {{
128
129        char * CondTestAbbrev[] =
130        {
131            "nev", //Never
132            "e", //Equal
133            "le", //Less or Equal
134            "l", //Less
135            "leu", //Less or Equal Unsigned
136            "c", //Carry set
137            "n", //Negative
138            "o", //Overflow set
139            "a", //Always
140            "ne", //Not Equal
141            "g", //Greater
142            "ge", //Greater or Equal
143            "gu", //Greater Unsigned
144            "cc", //Carry clear
145            "p", //Positive
146            "oc" //Overflow Clear
147        };
148}};
149
150def template ROrImmDecode {{
151    {
152        return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
153                  : (SparcStaticInst *)(new %(class_name)s(machInst)));
154    }
155}};
156
157let {{
158    def splitOutImm(code):
159        matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
160        rOrImmMatch = matcher.search(code)
161        if (rOrImmMatch == None):
162            return (False, code, '', '', '')
163        rString = rOrImmMatch.group("rNum")
164        if (rOrImmMatch.group("typeQual") != None):
165            rString += rOrImmMatch.group("typeQual")
166        iString = rOrImmMatch.group("iNum")
167        orig_code = code
168        code = matcher.sub('Rs' + rString, orig_code)
169        imm_code = matcher.sub('imm', orig_code)
170        return (True, code, imm_code, rString, iString)
171}};
172
173output decoder {{
174
175        inline void printMnemonic(std::ostream &os, const char * mnemonic)
176        {
177            ccprintf(os, "\t%s   ", mnemonic);
178        }
179
180        void SparcStaticInst::printRegArray(std::ostream &os,
181            const RegIndex indexArray[], int num) const
182        {
183            if(num <= 0)
184                return;
185            printReg(os, indexArray[0]);
186            for(int x = 1; x < num; x++)
187            {
188                os << ", ";
189                printReg(os, indexArray[x]);
190            }
191        }
192
193        void
194        SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
195        {
196            if(_numSrcRegs > reg)
197                printReg(os, _srcRegIdx[reg]);
198        }
199
200        void
201        SparcStaticInst::printDestReg(std::ostream &os, int reg) const
202        {
203            if(_numDestRegs > reg)
204                printReg(os, _destRegIdx[reg]);
205        }
206
207        void
208        SparcStaticInst::printReg(std::ostream &os, int reg) const
209        {
210            const int MaxGlobal = 8;
211            const int MaxOutput = 16;
212            const int MaxLocal = 24;
213            const int MaxInput = 32;
214            const int MaxMicroReg = 40;
215            if (reg < FP_Base_DepTag) {
216                //If we used a register from the next or previous window,
217                //take out the offset.
218                while (reg >= MaxMicroReg)
219                    reg -= MaxMicroReg;
220                if (reg == FramePointerReg)
221                    ccprintf(os, "%%fp");
222                else if (reg == StackPointerReg)
223                    ccprintf(os, "%%sp");
224                else if(reg < MaxGlobal)
225                    ccprintf(os, "%%g%d", reg);
226                else if(reg < MaxOutput)
227                    ccprintf(os, "%%o%d", reg - MaxGlobal);
228                else if(reg < MaxLocal)
229                    ccprintf(os, "%%l%d", reg - MaxOutput);
230                else if(reg < MaxInput)
231                    ccprintf(os, "%%i%d", reg - MaxLocal);
232                else if(reg < MaxMicroReg)
233                    ccprintf(os, "%%u%d", reg - MaxInput);
234                //The fake int regs that are really control regs
235                else {
236                    switch (reg - MaxMicroReg) {
237                      case 1:
238                        ccprintf(os, "%%y");
239                        break;
240                      case 2:
241                        ccprintf(os, "%%ccr");
242                        break;
243                      case 3:
244                        ccprintf(os, "%%cansave");
245                        break;
246                      case 4:
247                        ccprintf(os, "%%canrestore");
248                        break;
249                      case 5:
250                        ccprintf(os, "%%cleanwin");
251                        break;
252                      case 6:
253                        ccprintf(os, "%%otherwin");
254                        break;
255                      case 7:
256                        ccprintf(os, "%%wstate");
257                        break;
258                    }
259                }
260            } else if (reg < Ctrl_Base_DepTag) {
261                ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
262            } else {
263                switch (reg - Ctrl_Base_DepTag) {
264                  case MISCREG_ASI:
265                    ccprintf(os, "%%asi");
266                    break;
267                  case MISCREG_FPRS:
268                    ccprintf(os, "%%fprs");
269                    break;
270                  case MISCREG_PCR:
271                    ccprintf(os, "%%pcr");
272                    break;
273                  case MISCREG_PIC:
274                    ccprintf(os, "%%pic");
275                    break;
276                  case MISCREG_GSR:
277                    ccprintf(os, "%%gsr");
278                    break;
279                  case MISCREG_SOFTINT:
280                    ccprintf(os, "%%softint");
281                    break;
282                  case MISCREG_SOFTINT_SET:
283                    ccprintf(os, "%%softint_set");
284                    break;
285                  case MISCREG_SOFTINT_CLR:
286                    ccprintf(os, "%%softint_clr");
287                    break;
288                  case MISCREG_TICK_CMPR:
289                    ccprintf(os, "%%tick_cmpr");
290                    break;
291                  case MISCREG_STICK:
292                    ccprintf(os, "%%stick");
293                    break;
294                  case MISCREG_STICK_CMPR:
295                    ccprintf(os, "%%stick_cmpr");
296                    break;
297                  case MISCREG_TPC:
298                    ccprintf(os, "%%tpc");
299                    break;
300                  case MISCREG_TNPC:
301                    ccprintf(os, "%%tnpc");
302                    break;
303                  case MISCREG_TSTATE:
304                    ccprintf(os, "%%tstate");
305                    break;
306                  case MISCREG_TT:
307                    ccprintf(os, "%%tt");
308                    break;
309                  case MISCREG_TICK:
310                    ccprintf(os, "%%tick");
311                    break;
312                  case MISCREG_TBA:
313                    ccprintf(os, "%%tba");
314                    break;
315                  case MISCREG_PSTATE:
316                    ccprintf(os, "%%pstate");
317                    break;
318                  case MISCREG_TL:
319                    ccprintf(os, "%%tl");
320                    break;
321                  case MISCREG_PIL:
322                    ccprintf(os, "%%pil");
323                    break;
324                  case MISCREG_CWP:
325                    ccprintf(os, "%%cwp");
326                    break;
327                  case MISCREG_GL:
328                    ccprintf(os, "%%gl");
329                    break;
330                  case MISCREG_HPSTATE:
331                    ccprintf(os, "%%hpstate");
332                    break;
333                  case MISCREG_HTSTATE:
334                    ccprintf(os, "%%htstate");
335                    break;
336                  case MISCREG_HINTP:
337                    ccprintf(os, "%%hintp");
338                    break;
339                  case MISCREG_HTBA:
340                    ccprintf(os, "%%htba");
341                    break;
342                  case MISCREG_HSTICK_CMPR:
343                    ccprintf(os, "%%hstick_cmpr");
344                    break;
345                  case MISCREG_HVER:
346                    ccprintf(os, "%%hver");
347                    break;
348                  case MISCREG_STRAND_STS_REG:
349                    ccprintf(os, "%%strand_sts_reg");
350                    break;
351                  case MISCREG_FSR:
352                    ccprintf(os, "%%fsr");
353                    break;
354                  default:
355                    ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag);
356                }
357            }
358        }
359
360        std::string SparcStaticInst::generateDisassembly(Addr pc,
361            const SymbolTable *symtab) const
362        {
363            std::stringstream ss;
364
365            printMnemonic(ss, mnemonic);
366
367            // just print the first two source regs... if there's
368            // a third one, it's a read-modify-write dest (Rc),
369            // e.g. for CMOVxx
370            if(_numSrcRegs > 0)
371            {
372                printReg(ss, _srcRegIdx[0]);
373            }
374            if(_numSrcRegs > 1)
375            {
376                ss << ",";
377                printReg(ss, _srcRegIdx[1]);
378            }
379
380            // just print the first dest... if there's a second one,
381            // it's generally implicit
382            if(_numDestRegs > 0)
383            {
384                if(_numSrcRegs > 0)
385                    ss << ",";
386                    printReg(ss, _destRegIdx[0]);
387            }
388
389            return ss.str();
390        }
391
392        bool passesFpCondition(uint32_t fcc, uint32_t condition)
393        {
394            bool u = (fcc == 3);
395            bool g = (fcc == 2);
396            bool l = (fcc == 1);
397            bool e = (fcc == 0);
398            switch(condition)
399            {
400              case FAlways:
401                return 1;
402              case FNever:
403                return 0;
404              case FUnordered:
405                return u;
406              case FGreater:
407                return g;
408              case FUnorderedOrGreater:
409                return u || g;
410              case FLess:
411                return l;
412              case FUnorderedOrLess:
413                return u || l;
414              case FLessOrGreater:
415                return l || g;
416              case FNotEqual:
417                return l || g || u;
418              case FEqual:
419                return e;
420              case FUnorderedOrEqual:
421                return u || e;
422              case FGreaterOrEqual:
423                return g || e;
424              case FUnorderedOrGreaterOrEqual:
425                return u || g || e;
426              case FLessOrEqual:
427                return l || e;
428              case FUnorderedOrLessOrEqual:
429                return u || l || e;
430              case FOrdered:
431                return e || l || g;
432            }
433            panic("Tried testing condition nonexistant "
434                    "condition code %d", condition);
435        }
436
437        bool passesCondition(uint32_t codes, uint32_t condition)
438        {
439            CondCodes condCodes;
440            condCodes.bits =  0;
441            condCodes.c = codes & 0x1 ? 1 : 0;
442            condCodes.v = codes & 0x2 ? 1 : 0;
443            condCodes.z = codes & 0x4 ? 1 : 0;
444            condCodes.n = codes & 0x8 ? 1 : 0;
445
446            switch(condition)
447            {
448              case Always:
449                return true;
450              case Never:
451                return false;
452              case NotEqual:
453                return !condCodes.z;
454              case Equal:
455                return condCodes.z;
456              case Greater:
457                return !(condCodes.z | (condCodes.n ^ condCodes.v));
458              case LessOrEqual:
459                return condCodes.z | (condCodes.n ^ condCodes.v);
460              case GreaterOrEqual:
461                return !(condCodes.n ^ condCodes.v);
462              case Less:
463                return (condCodes.n ^ condCodes.v);
464              case GreaterUnsigned:
465                return !(condCodes.c | condCodes.z);
466              case LessOrEqualUnsigned:
467                return (condCodes.c | condCodes.z);
468              case CarryClear:
469                return !condCodes.c;
470              case CarrySet:
471                return condCodes.c;
472              case Positive:
473                return !condCodes.n;
474              case Negative:
475                return condCodes.n;
476              case OverflowClear:
477                return !condCodes.v;
478              case OverflowSet:
479                return condCodes.v;
480            }
481            panic("Tried testing condition nonexistant "
482                    "condition code %d", condition);
483        }
484}};
485
486output exec {{
487    /// Check "FP enabled" machine status bit.  Called when executing any FP
488    /// instruction in full-system mode.
489    /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
490    /// if not.  Non-full-system mode: always returns NoFault.
491#if FULL_SYSTEM
492    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
493    {
494        Fault fault = NoFault;	// dummy... this ipr access should not fault
495        if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef &&
496            xc->readMiscReg(MISCREG_FPRS) & 0x4)
497            return NoFault;
498        else
499            return new FpDisabled;
500    }
501#else
502    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
503    {
504        return NoFault;
505    }
506#endif
507}};
508
509
510