base.isa (12106:7784fac1b159) base.isa (12110:c24ee249b8ba)
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.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
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 }
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.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
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 static inline Fault
582 checkVecEnableFault(CPU_EXEC_CONTEXT *xc)
583 {
584 return std::make_shared<VecDisabled>();
585 }
581}};
582
583
586}};
587
588