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