base.isa (4362:95e5f28ce484) base.isa (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
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[];
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
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[] =
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
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