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
|
31def template ROrImmDecode {{ 32 { 33 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) 34 : (SparcStaticInst *)(new %(class_name)s(machInst))); 35 } 36}}; 37 38output header {{ 39 union DoubleSingle 40 { 41 double d; 42 uint64_t ui; 43 uint32_t s[2]; 44 DoubleSingle(double _d) : d(_d) 45 {} 46 DoubleSingle(uint64_t _ui) : ui(_ui) 47 {} 48 DoubleSingle(uint32_t _s0, uint32_t _s1) 49 { 50 s[0] = _s0; 51 s[1] = _s1; 52 } 53 }; 54}}; 55 56let {{ 57 def filterDoubles(code): 58 assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE) 59 for opName in ("Frd", "Frs1", "Frs2", "Frd_N"): 60 next_pos = 0 61 operandsREString = (r''' 62 (?<!\w) # neg. lookbehind assertion: prevent partial matches 63 ((%s)(?:_([^\W_]+))?) # match: operand with optional '.' then suffix 64 (?!\w) # neg. lookahead assertion: prevent partial matches 65 ''' % opName) 66 operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE) 67 is_src = False 68 is_dest = False 69 extension = None 70 foundOne = False 71 while 1: 72 match = operandsRE.search(code, next_pos) 73 if not match: 74 break 75 foundOne = True 76 op = match.groups() 77 (op_full, op_base, op_ext) = op 78 is_dest_local = (assignRE.match(code, match.end()) != None) 79 is_dest = is_dest or is_dest_local 80 is_src = is_src or not is_dest_local 81 if extension and extension != op_ext: 82 raise Exception, "Inconsistent extensions in double filter." 83 extension = op_ext 84 next_pos = match.end() 85 if foundOne: 86 # Get rid of any unwanted extension 87 code = operandsRE.sub(op_base, code) 88 is_int = False 89 member = "d" 90 if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"): 91 is_int = True 92 member = "ui" 93 if is_src: 94 code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \ 95 (opName, opName, opName, member)) + code 96 if is_dest: 97 code += ''' 98 %s_low = DoubleSingle(%s).s[1]; 99 %s_high = DoubleSingle(%s).s[0];''' % \ 100 (opName, opName, opName, opName) 101 if is_int: 102 code = ("uint64_t %s;" % opName) + code 103 else: 104 code = ("double %s;" % opName) + code 105 return code 106}}; 107 108let {{ 109 def splitOutImm(code): 110 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>_[^\W_]+)?') 111 rOrImmMatch = matcher.search(code) 112 if (rOrImmMatch == None): 113 return (False, code, '', '', '') 114 rString = rOrImmMatch.group("rNum") 115 if (rOrImmMatch.group("typeQual") != None): 116 rString += rOrImmMatch.group("typeQual") 117 iString = rOrImmMatch.group("iNum") 118 orig_code = code 119 code = matcher.sub('Rs' + rString, orig_code) 120 imm_code = matcher.sub('imm', orig_code) 121 return (True, code, imm_code, rString, iString) 122}}; 123
|
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.index();
294 if (reg.isIntReg()) {
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.isFloatReg()) {
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
|
124output exec {{ 125 /// Check "FP enabled" machine status bit. Called when executing any FP 126 /// instruction. 127 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled 128 /// if not. Non-full-system mode: always returns NoFault. 129 static inline Fault 130 checkFpEnableFault(ExecContext *xc) 131 { 132 if (FullSystem) { 133 PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE); 134 if (pstate.pef && xc->readMiscReg(MISCREG_FPRS) & 0x4) { 135 return NoFault; 136 } else { 137 return std::make_shared<FpDisabled>(); 138 } 139 } else { 140 return NoFault; 141 } 142 }
|
143 |
144 static inline Fault 145 checkVecEnableFault(ExecContext *xc) 146 { 147 return std::make_shared<VecDisabled>(); 148 } 149}}; 150 151
|