base.isa (11981:0c5089b6133d) base.isa (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
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, int reg) const;
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,
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;
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,
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 RegIndex indexArray[], int num) const
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
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, int reg) const
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;
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 if (reg < FP_Reg_Base) {
293 RegIndex reg_idx = reg.regIdx;
294 if (reg.regClass == IntRegClass) {
294 // If we used a register from the next or previous window,
295 // take out the offset.
295 // If we used a register from the next or previous window,
296 // take out the offset.
296 while (reg >= MaxMicroReg)
297 reg -= MaxMicroReg;
298 if (reg == FramePointerReg)
297 while (reg_idx >= MaxMicroReg)
298 reg_idx -= MaxMicroReg;
299 if (reg_idx == FramePointerReg)
299 ccprintf(os, "%%fp");
300 ccprintf(os, "%%fp");
300 else if (reg == StackPointerReg)
301 else if (reg_idx == StackPointerReg)
301 ccprintf(os, "%%sp");
302 ccprintf(os, "%%sp");
302 else if (reg < MaxGlobal)
303 ccprintf(os, "%%g%d", reg);
304 else if (reg < MaxOutput)
305 ccprintf(os, "%%o%d", reg - MaxGlobal);
306 else if (reg < MaxLocal)
307 ccprintf(os, "%%l%d", reg - MaxOutput);
308 else if (reg < MaxInput)
309 ccprintf(os, "%%i%d", reg - MaxLocal);
310 else if (reg < MaxMicroReg)
311 ccprintf(os, "%%u%d", reg - MaxInput);
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);
312 // The fake int regs that are really control regs
313 else {
313 // The fake int regs that are really control regs
314 else {
314 switch (reg - MaxMicroReg) {
315 switch (reg_idx - MaxMicroReg) {
315 case 1:
316 ccprintf(os, "%%y");
317 break;
318 case 2:
319 ccprintf(os, "%%ccr");
320 break;
321 case 3:
322 ccprintf(os, "%%cansave");
323 break;
324 case 4:
325 ccprintf(os, "%%canrestore");
326 break;
327 case 5:
328 ccprintf(os, "%%cleanwin");
329 break;
330 case 6:
331 ccprintf(os, "%%otherwin");
332 break;
333 case 7:
334 ccprintf(os, "%%wstate");
335 break;
336 }
337 }
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 }
338 } else if (reg < Misc_Reg_Base) {
339 ccprintf(os, "%%f%d", reg - FP_Reg_Base);
339 } else if (reg.regClass == FloatRegClass) {
340 ccprintf(os, "%%f%d", reg_idx);
340 } else {
341 } else {
341 switch (reg - Misc_Reg_Base) {
342 switch (reg_idx) {
342 case MISCREG_ASI:
343 ccprintf(os, "%%asi");
344 break;
345 case MISCREG_FPRS:
346 ccprintf(os, "%%fprs");
347 break;
348 case MISCREG_PCR:
349 ccprintf(os, "%%pcr");
350 break;
351 case MISCREG_PIC:
352 ccprintf(os, "%%pic");
353 break;
354 case MISCREG_GSR:
355 ccprintf(os, "%%gsr");
356 break;
357 case MISCREG_SOFTINT:
358 ccprintf(os, "%%softint");
359 break;
360 case MISCREG_SOFTINT_SET:
361 ccprintf(os, "%%softint_set");
362 break;
363 case MISCREG_SOFTINT_CLR:
364 ccprintf(os, "%%softint_clr");
365 break;
366 case MISCREG_TICK_CMPR:
367 ccprintf(os, "%%tick_cmpr");
368 break;
369 case MISCREG_STICK:
370 ccprintf(os, "%%stick");
371 break;
372 case MISCREG_STICK_CMPR:
373 ccprintf(os, "%%stick_cmpr");
374 break;
375 case MISCREG_TPC:
376 ccprintf(os, "%%tpc");
377 break;
378 case MISCREG_TNPC:
379 ccprintf(os, "%%tnpc");
380 break;
381 case MISCREG_TSTATE:
382 ccprintf(os, "%%tstate");
383 break;
384 case MISCREG_TT:
385 ccprintf(os, "%%tt");
386 break;
387 case MISCREG_TICK:
388 ccprintf(os, "%%tick");
389 break;
390 case MISCREG_TBA:
391 ccprintf(os, "%%tba");
392 break;
393 case MISCREG_PSTATE:
394 ccprintf(os, "%%pstate");
395 break;
396 case MISCREG_TL:
397 ccprintf(os, "%%tl");
398 break;
399 case MISCREG_PIL:
400 ccprintf(os, "%%pil");
401 break;
402 case MISCREG_CWP:
403 ccprintf(os, "%%cwp");
404 break;
405 case MISCREG_GL:
406 ccprintf(os, "%%gl");
407 break;
408 case MISCREG_HPSTATE:
409 ccprintf(os, "%%hpstate");
410 break;
411 case MISCREG_HTSTATE:
412 ccprintf(os, "%%htstate");
413 break;
414 case MISCREG_HINTP:
415 ccprintf(os, "%%hintp");
416 break;
417 case MISCREG_HTBA:
418 ccprintf(os, "%%htba");
419 break;
420 case MISCREG_HSTICK_CMPR:
421 ccprintf(os, "%%hstick_cmpr");
422 break;
423 case MISCREG_HVER:
424 ccprintf(os, "%%hver");
425 break;
426 case MISCREG_STRAND_STS_REG:
427 ccprintf(os, "%%strand_sts_reg");
428 break;
429 case MISCREG_FSR:
430 ccprintf(os, "%%fsr");
431 break;
432 default:
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:
433 ccprintf(os, "%%ctrl%d", reg - Misc_Reg_Base);
434 ccprintf(os, "%%ctrl%d", reg_idx);
434 }
435 }
436 }
437
438 std::string
439 SparcStaticInst::generateDisassembly(Addr pc,
440 const SymbolTable *symtab) const
441 {
442 std::stringstream ss;
443
444 printMnemonic(ss, mnemonic);
445
446 // just print the first two source regs... if there's
447 // a third one, it's a read-modify-write dest (Rc),
448 // e.g. for CMOVxx
449 if (_numSrcRegs > 0)
450 printReg(ss, _srcRegIdx[0]);
451 if (_numSrcRegs > 1) {
452 ss << ",";
453 printReg(ss, _srcRegIdx[1]);
454 }
455
456 // just print the first dest... if there's a second one,
457 // it's generally implicit
458 if (_numDestRegs > 0) {
459 if (_numSrcRegs > 0)
460 ss << ",";
461 printReg(ss, _destRegIdx[0]);
462 }
463
464 return ss.str();
465 }
466
467 bool
468 passesFpCondition(uint32_t fcc, uint32_t condition)
469 {
470 bool u = (fcc == 3);
471 bool g = (fcc == 2);
472 bool l = (fcc == 1);
473 bool e = (fcc == 0);
474 switch (condition) {
475 case FAlways:
476 return 1;
477 case FNever:
478 return 0;
479 case FUnordered:
480 return u;
481 case FGreater:
482 return g;
483 case FUnorderedOrGreater:
484 return u || g;
485 case FLess:
486 return l;
487 case FUnorderedOrLess:
488 return u || l;
489 case FLessOrGreater:
490 return l || g;
491 case FNotEqual:
492 return l || g || u;
493 case FEqual:
494 return e;
495 case FUnorderedOrEqual:
496 return u || e;
497 case FGreaterOrEqual:
498 return g || e;
499 case FUnorderedOrGreaterOrEqual:
500 return u || g || e;
501 case FLessOrEqual:
502 return l || e;
503 case FUnorderedOrLessOrEqual:
504 return u || l || e;
505 case FOrdered:
506 return e || l || g;
507 }
508 panic("Tried testing condition nonexistant "
509 "condition code %d", condition);
510 }
511
512 bool
513 passesCondition(uint32_t codes, uint32_t condition)
514 {
515 CondCodes condCodes;
516 condCodes.bits = 0;
517 condCodes.c = codes & 0x1 ? 1 : 0;
518 condCodes.v = codes & 0x2 ? 1 : 0;
519 condCodes.z = codes & 0x4 ? 1 : 0;
520 condCodes.n = codes & 0x8 ? 1 : 0;
521
522 switch (condition) {
523 case Always:
524 return true;
525 case Never:
526 return false;
527 case NotEqual:
528 return !condCodes.z;
529 case Equal:
530 return condCodes.z;
531 case Greater:
532 return !(condCodes.z | (condCodes.n ^ condCodes.v));
533 case LessOrEqual:
534 return condCodes.z | (condCodes.n ^ condCodes.v);
535 case GreaterOrEqual:
536 return !(condCodes.n ^ condCodes.v);
537 case Less:
538 return (condCodes.n ^ condCodes.v);
539 case GreaterUnsigned:
540 return !(condCodes.c | condCodes.z);
541 case LessOrEqualUnsigned:
542 return (condCodes.c | condCodes.z);
543 case CarryClear:
544 return !condCodes.c;
545 case CarrySet:
546 return condCodes.c;
547 case Positive:
548 return !condCodes.n;
549 case Negative:
550 return condCodes.n;
551 case OverflowClear:
552 return !condCodes.v;
553 case OverflowSet:
554 return condCodes.v;
555 }
556 panic("Tried testing condition nonexistant "
557 "condition code %d", condition);
558 }
559}};
560
561output exec {{
562 /// Check "FP enabled" machine status bit. Called when executing any FP
563 /// instruction.
564 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
565 /// if not. Non-full-system mode: always returns NoFault.
566 static inline Fault
567 checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
568 {
569 if (FullSystem) {
570 PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE);
571 if (pstate.pef && xc->readMiscReg(MISCREG_FPRS) & 0x4) {
572 return NoFault;
573 } else {
574 return std::make_shared<FpDisabled>();
575 }
576 } else {
577 return NoFault;
578 }
579 }
580}};
581
582
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