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