base.isa revision 5202:ff56fa8c2091
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 const 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        const 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
157output header {{
158    union DoubleSingle
159    {
160        double d;
161        uint64_t ui;
162        uint32_t s[2];
163        DoubleSingle(double _d) : d(_d)
164        {}
165        DoubleSingle(uint64_t _ui) : ui(_ui)
166        {}
167        DoubleSingle(uint32_t _s0, uint32_t _s1)
168        {
169            s[0] = _s0;
170            s[1] = _s1;
171        }
172    };
173}};
174
175let {{
176    def filterDoubles(code):
177        assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
178        for opName in ("Frd", "Frs1", "Frs2", "Frd_N"):
179            next_pos = 0
180            operandsREString = (r'''
181            (?<![\w\.])             # neg. lookbehind assertion: prevent partial matches
182            ((%s)(?:\.(\w+))?)   # match: operand with optional '.' then suffix
183            (?![\w\.])             # neg. lookahead assertion: prevent partial matches
184            ''' % opName)
185            operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
186            is_src = False
187            is_dest = False
188            extension = None
189            foundOne = False
190            while 1:
191                match = operandsRE.search(code, next_pos)
192                if not match:
193                    break
194                foundOne = True
195                op = match.groups()
196                (op_full, op_base, op_ext) = op
197                is_dest_local = (assignRE.match(code, match.end()) != None)
198                is_dest = is_dest or is_dest_local
199                is_src = is_src or not is_dest_local
200                if extension and extension != op_ext:
201                    raise Exception, "Inconsistent extensions in double filter."
202                extension = op_ext
203                next_pos = match.end()
204            if foundOne:
205                # Get rid of any unwanted extension
206                code = operandsRE.sub(op_base, code)
207                is_int = False
208                member = "d"
209                if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"):
210                    is_int = True
211                    member = "ui"
212                if is_src:
213                    code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \
214                        (opName, opName, opName, member)) + code
215                if is_dest:
216                    code += '''
217                        %s_low = DoubleSingle(%s).s[1];
218                        %s_high = DoubleSingle(%s).s[0];''' % \
219                             (opName, opName, opName, opName)
220                if is_int:
221                    code = ("uint64_t %s;" % opName) + code
222                else:
223                    code = ("double %s;" % opName) + code
224        return code
225}};
226
227let {{
228    def splitOutImm(code):
229        matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
230        rOrImmMatch = matcher.search(code)
231        if (rOrImmMatch == None):
232            return (False, code, '', '', '')
233        rString = rOrImmMatch.group("rNum")
234        if (rOrImmMatch.group("typeQual") != None):
235            rString += rOrImmMatch.group("typeQual")
236        iString = rOrImmMatch.group("iNum")
237        orig_code = code
238        code = matcher.sub('Rs' + rString, orig_code)
239        imm_code = matcher.sub('imm', orig_code)
240        return (True, code, imm_code, rString, iString)
241}};
242
243output decoder {{
244
245        inline void printMnemonic(std::ostream &os, const char * mnemonic)
246        {
247            ccprintf(os, "\t%s   ", mnemonic);
248        }
249
250        void SparcStaticInst::printRegArray(std::ostream &os,
251            const RegIndex indexArray[], int num) const
252        {
253            if(num <= 0)
254                return;
255            printReg(os, indexArray[0]);
256            for(int x = 1; x < num; x++)
257            {
258                os << ", ";
259                printReg(os, indexArray[x]);
260            }
261        }
262
263        void
264        SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
265        {
266            if(_numSrcRegs > reg)
267                printReg(os, _srcRegIdx[reg]);
268        }
269
270        void
271        SparcStaticInst::printDestReg(std::ostream &os, int reg) const
272        {
273            if(_numDestRegs > reg)
274                printReg(os, _destRegIdx[reg]);
275        }
276
277        void
278        SparcStaticInst::printReg(std::ostream &os, int reg) const
279        {
280            const int MaxGlobal = 8;
281            const int MaxOutput = 16;
282            const int MaxLocal = 24;
283            const int MaxInput = 32;
284            const int MaxMicroReg = 40;
285            if (reg < FP_Base_DepTag) {
286                //If we used a register from the next or previous window,
287                //take out the offset.
288                while (reg >= MaxMicroReg)
289                    reg -= MaxMicroReg;
290                if (reg == FramePointerReg)
291                    ccprintf(os, "%%fp");
292                else if (reg == StackPointerReg)
293                    ccprintf(os, "%%sp");
294                else if(reg < MaxGlobal)
295                    ccprintf(os, "%%g%d", reg);
296                else if(reg < MaxOutput)
297                    ccprintf(os, "%%o%d", reg - MaxGlobal);
298                else if(reg < MaxLocal)
299                    ccprintf(os, "%%l%d", reg - MaxOutput);
300                else if(reg < MaxInput)
301                    ccprintf(os, "%%i%d", reg - MaxLocal);
302                else if(reg < MaxMicroReg)
303                    ccprintf(os, "%%u%d", reg - MaxInput);
304                //The fake int regs that are really control regs
305                else {
306                    switch (reg - MaxMicroReg) {
307                      case 1:
308                        ccprintf(os, "%%y");
309                        break;
310                      case 2:
311                        ccprintf(os, "%%ccr");
312                        break;
313                      case 3:
314                        ccprintf(os, "%%cansave");
315                        break;
316                      case 4:
317                        ccprintf(os, "%%canrestore");
318                        break;
319                      case 5:
320                        ccprintf(os, "%%cleanwin");
321                        break;
322                      case 6:
323                        ccprintf(os, "%%otherwin");
324                        break;
325                      case 7:
326                        ccprintf(os, "%%wstate");
327                        break;
328                    }
329                }
330            } else if (reg < Ctrl_Base_DepTag) {
331                ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
332            } else {
333                switch (reg - Ctrl_Base_DepTag) {
334                  case MISCREG_ASI:
335                    ccprintf(os, "%%asi");
336                    break;
337                  case MISCREG_FPRS:
338                    ccprintf(os, "%%fprs");
339                    break;
340                  case MISCREG_PCR:
341                    ccprintf(os, "%%pcr");
342                    break;
343                  case MISCREG_PIC:
344                    ccprintf(os, "%%pic");
345                    break;
346                  case MISCREG_GSR:
347                    ccprintf(os, "%%gsr");
348                    break;
349                  case MISCREG_SOFTINT:
350                    ccprintf(os, "%%softint");
351                    break;
352                  case MISCREG_SOFTINT_SET:
353                    ccprintf(os, "%%softint_set");
354                    break;
355                  case MISCREG_SOFTINT_CLR:
356                    ccprintf(os, "%%softint_clr");
357                    break;
358                  case MISCREG_TICK_CMPR:
359                    ccprintf(os, "%%tick_cmpr");
360                    break;
361                  case MISCREG_STICK:
362                    ccprintf(os, "%%stick");
363                    break;
364                  case MISCREG_STICK_CMPR:
365                    ccprintf(os, "%%stick_cmpr");
366                    break;
367                  case MISCREG_TPC:
368                    ccprintf(os, "%%tpc");
369                    break;
370                  case MISCREG_TNPC:
371                    ccprintf(os, "%%tnpc");
372                    break;
373                  case MISCREG_TSTATE:
374                    ccprintf(os, "%%tstate");
375                    break;
376                  case MISCREG_TT:
377                    ccprintf(os, "%%tt");
378                    break;
379                  case MISCREG_TICK:
380                    ccprintf(os, "%%tick");
381                    break;
382                  case MISCREG_TBA:
383                    ccprintf(os, "%%tba");
384                    break;
385                  case MISCREG_PSTATE:
386                    ccprintf(os, "%%pstate");
387                    break;
388                  case MISCREG_TL:
389                    ccprintf(os, "%%tl");
390                    break;
391                  case MISCREG_PIL:
392                    ccprintf(os, "%%pil");
393                    break;
394                  case MISCREG_CWP:
395                    ccprintf(os, "%%cwp");
396                    break;
397                  case MISCREG_GL:
398                    ccprintf(os, "%%gl");
399                    break;
400                  case MISCREG_HPSTATE:
401                    ccprintf(os, "%%hpstate");
402                    break;
403                  case MISCREG_HTSTATE:
404                    ccprintf(os, "%%htstate");
405                    break;
406                  case MISCREG_HINTP:
407                    ccprintf(os, "%%hintp");
408                    break;
409                  case MISCREG_HTBA:
410                    ccprintf(os, "%%htba");
411                    break;
412                  case MISCREG_HSTICK_CMPR:
413                    ccprintf(os, "%%hstick_cmpr");
414                    break;
415                  case MISCREG_HVER:
416                    ccprintf(os, "%%hver");
417                    break;
418                  case MISCREG_STRAND_STS_REG:
419                    ccprintf(os, "%%strand_sts_reg");
420                    break;
421                  case MISCREG_FSR:
422                    ccprintf(os, "%%fsr");
423                    break;
424                  default:
425                    ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag);
426                }
427            }
428        }
429
430        std::string SparcStaticInst::generateDisassembly(Addr pc,
431            const SymbolTable *symtab) const
432        {
433            std::stringstream ss;
434
435            printMnemonic(ss, mnemonic);
436
437            // just print the first two source regs... if there's
438            // a third one, it's a read-modify-write dest (Rc),
439            // e.g. for CMOVxx
440            if(_numSrcRegs > 0)
441            {
442                printReg(ss, _srcRegIdx[0]);
443            }
444            if(_numSrcRegs > 1)
445            {
446                ss << ",";
447                printReg(ss, _srcRegIdx[1]);
448            }
449
450            // just print the first dest... if there's a second one,
451            // it's generally implicit
452            if(_numDestRegs > 0)
453            {
454                if(_numSrcRegs > 0)
455                    ss << ",";
456                    printReg(ss, _destRegIdx[0]);
457            }
458
459            return ss.str();
460        }
461
462        bool passesFpCondition(uint32_t fcc, uint32_t condition)
463        {
464            bool u = (fcc == 3);
465            bool g = (fcc == 2);
466            bool l = (fcc == 1);
467            bool e = (fcc == 0);
468            switch(condition)
469            {
470              case FAlways:
471                return 1;
472              case FNever:
473                return 0;
474              case FUnordered:
475                return u;
476              case FGreater:
477                return g;
478              case FUnorderedOrGreater:
479                return u || g;
480              case FLess:
481                return l;
482              case FUnorderedOrLess:
483                return u || l;
484              case FLessOrGreater:
485                return l || g;
486              case FNotEqual:
487                return l || g || u;
488              case FEqual:
489                return e;
490              case FUnorderedOrEqual:
491                return u || e;
492              case FGreaterOrEqual:
493                return g || e;
494              case FUnorderedOrGreaterOrEqual:
495                return u || g || e;
496              case FLessOrEqual:
497                return l || e;
498              case FUnorderedOrLessOrEqual:
499                return u || l || e;
500              case FOrdered:
501                return e || l || g;
502            }
503            panic("Tried testing condition nonexistant "
504                    "condition code %d", condition);
505        }
506
507        bool passesCondition(uint32_t codes, uint32_t condition)
508        {
509            CondCodes condCodes;
510            condCodes.bits =  0;
511            condCodes.c = codes & 0x1 ? 1 : 0;
512            condCodes.v = codes & 0x2 ? 1 : 0;
513            condCodes.z = codes & 0x4 ? 1 : 0;
514            condCodes.n = codes & 0x8 ? 1 : 0;
515
516            switch(condition)
517            {
518              case Always:
519                return true;
520              case Never:
521                return false;
522              case NotEqual:
523                return !condCodes.z;
524              case Equal:
525                return condCodes.z;
526              case Greater:
527                return !(condCodes.z | (condCodes.n ^ condCodes.v));
528              case LessOrEqual:
529                return condCodes.z | (condCodes.n ^ condCodes.v);
530              case GreaterOrEqual:
531                return !(condCodes.n ^ condCodes.v);
532              case Less:
533                return (condCodes.n ^ condCodes.v);
534              case GreaterUnsigned:
535                return !(condCodes.c | condCodes.z);
536              case LessOrEqualUnsigned:
537                return (condCodes.c | condCodes.z);
538              case CarryClear:
539                return !condCodes.c;
540              case CarrySet:
541                return condCodes.c;
542              case Positive:
543                return !condCodes.n;
544              case Negative:
545                return condCodes.n;
546              case OverflowClear:
547                return !condCodes.v;
548              case OverflowSet:
549                return condCodes.v;
550            }
551            panic("Tried testing condition nonexistant "
552                    "condition code %d", condition);
553        }
554}};
555
556output exec {{
557    /// Check "FP enabled" machine status bit.  Called when executing any FP
558    /// instruction in full-system mode.
559    /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
560    /// if not.  Non-full-system mode: always returns NoFault.
561#if FULL_SYSTEM
562    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
563    {
564        Fault fault = NoFault;	// dummy... this ipr access should not fault
565        if (xc->readMiscReg(MISCREG_PSTATE) & PSTATE::pef &&
566            xc->readMiscReg(MISCREG_FPRS) & 0x4)
567            return NoFault;
568        else
569            return new FpDisabled;
570    }
571#else
572    inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
573    {
574        return NoFault;
575    }
576#endif
577}};
578
579
580