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