base.isa (3931:de791fa53d04) base.isa (3978:739bc3a17929)
1// Copyright (c) 2006-2007 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Ali Saidi
28// Gabe Black
29// Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Base class for sparc instructions, and some support functions
34//
35
36output header {{
37
38 union CondCodes
39 {
40 struct
41 {
42 uint8_t c:1;
43 uint8_t v:1;
44 uint8_t z:1;
45 uint8_t n:1;
46 };
47 uint32_t bits;
48 };
49
50 enum CondTest
51 {
52 Always=0x8,
53 Never=0x0,
54 NotEqual=0x9,
55 Equal=0x1,
56 Greater=0xA,
57 LessOrEqual=0x2,
58 GreaterOrEqual=0xB,
59 Less=0x3,
60 GreaterUnsigned=0xC,
61 LessOrEqualUnsigned=0x4,
62 CarryClear=0xD,
63 CarrySet=0x5,
64 Positive=0xE,
65 Negative=0x6,
66 OverflowClear=0xF,
67 OverflowSet=0x7
68 };
69
70 extern char * CondTestAbbrev[];
71
72 /**
73 * Base class for all SPARC static instructions.
74 */
75 class SparcStaticInst : public StaticInst
76 {
77 protected:
78 // Constructor.
79 SparcStaticInst(const char *mnem,
80 ExtMachInst _machInst, OpClass __opClass)
81 : StaticInst(mnem, _machInst, __opClass)
82 {
83 }
84
85 std::string generateDisassembly(Addr pc,
86 const SymbolTable *symtab) const;
87
88 void printReg(std::ostream &os, int reg) const;
89 void printSrcReg(std::ostream &os, int reg) const;
90 void printDestReg(std::ostream &os, int reg) const;
91
92 void printRegArray(std::ostream &os,
93 const RegIndex indexArray[], int num) const;
94 };
95
96 bool passesCondition(uint32_t codes, uint32_t condition);
97
98 inline int64_t sign_ext(uint64_t data, int origWidth)
99 {
100 int shiftAmount = 64 - origWidth;
101 return (((int64_t)data) << shiftAmount) >> shiftAmount;
102 }
103}};
104
105output decoder {{
106
107 char * CondTestAbbrev[] =
108 {
109 "nev", //Never
110 "e", //Equal
111 "le", //Less or Equal
112 "l", //Less
113 "leu", //Less or Equal Unsigned
114 "c", //Carry set
115 "n", //Negative
116 "o", //Overflow set
117 "a", //Always
118 "ne", //Not Equal
119 "g", //Greater
120 "ge", //Greater or Equal
121 "gu", //Greater Unsigned
122 "cc", //Carry clear
123 "p", //Positive
124 "oc" //Overflow Clear
125 };
126}};
127
128def template ROrImmDecode {{
129 {
130 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
131 : (SparcStaticInst *)(new %(class_name)s(machInst)));
132 }
133}};
134
135let {{
136 def splitOutImm(code):
137 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
138 rOrImmMatch = matcher.search(code)
139 if (rOrImmMatch == None):
140 return (False, code, '', '', '')
141 rString = rOrImmMatch.group("rNum")
142 if (rOrImmMatch.group("typeQual") != None):
143 rString += rOrImmMatch.group("typeQual")
144 iString = rOrImmMatch.group("iNum")
145 orig_code = code
146 code = matcher.sub('Rs' + rString, orig_code)
147 imm_code = matcher.sub('imm', orig_code)
148 return (True, code, imm_code, rString, iString)
149}};
150
151output decoder {{
152
153 inline void printMnemonic(std::ostream &os, const char * mnemonic)
154 {
155 ccprintf(os, "\t%s ", mnemonic);
156 }
157
158 void SparcStaticInst::printRegArray(std::ostream &os,
159 const RegIndex indexArray[], int num) const
160 {
161 if(num <= 0)
162 return;
163 printReg(os, indexArray[0]);
164 for(int x = 1; x < num; x++)
165 {
166 os << ", ";
167 printReg(os, indexArray[x]);
168 }
169 }
170
171 void
172 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
173 {
174 if(_numSrcRegs > reg)
175 printReg(os, _srcRegIdx[reg]);
176 }
177
178 void
179 SparcStaticInst::printDestReg(std::ostream &os, int reg) const
180 {
181 if(_numDestRegs > reg)
182 printReg(os, _destRegIdx[reg]);
183 }
184
185 void
186 SparcStaticInst::printReg(std::ostream &os, int reg) const
187 {
188 const int MaxGlobal = 8;
189 const int MaxOutput = 16;
190 const int MaxLocal = 24;
191 const int MaxInput = 32;
1// Copyright (c) 2006-2007 The Regents of The University of Michigan
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met: redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer;
8// redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution;
11// neither the name of the copyright holders nor the names of its
12// contributors may be used to endorse or promote products derived from
13// this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26//
27// Authors: Ali Saidi
28// Gabe Black
29// Steve Reinhardt
30
31////////////////////////////////////////////////////////////////////
32//
33// Base class for sparc instructions, and some support functions
34//
35
36output header {{
37
38 union CondCodes
39 {
40 struct
41 {
42 uint8_t c:1;
43 uint8_t v:1;
44 uint8_t z:1;
45 uint8_t n:1;
46 };
47 uint32_t bits;
48 };
49
50 enum CondTest
51 {
52 Always=0x8,
53 Never=0x0,
54 NotEqual=0x9,
55 Equal=0x1,
56 Greater=0xA,
57 LessOrEqual=0x2,
58 GreaterOrEqual=0xB,
59 Less=0x3,
60 GreaterUnsigned=0xC,
61 LessOrEqualUnsigned=0x4,
62 CarryClear=0xD,
63 CarrySet=0x5,
64 Positive=0xE,
65 Negative=0x6,
66 OverflowClear=0xF,
67 OverflowSet=0x7
68 };
69
70 extern char * CondTestAbbrev[];
71
72 /**
73 * Base class for all SPARC static instructions.
74 */
75 class SparcStaticInst : public StaticInst
76 {
77 protected:
78 // Constructor.
79 SparcStaticInst(const char *mnem,
80 ExtMachInst _machInst, OpClass __opClass)
81 : StaticInst(mnem, _machInst, __opClass)
82 {
83 }
84
85 std::string generateDisassembly(Addr pc,
86 const SymbolTable *symtab) const;
87
88 void printReg(std::ostream &os, int reg) const;
89 void printSrcReg(std::ostream &os, int reg) const;
90 void printDestReg(std::ostream &os, int reg) const;
91
92 void printRegArray(std::ostream &os,
93 const RegIndex indexArray[], int num) const;
94 };
95
96 bool passesCondition(uint32_t codes, uint32_t condition);
97
98 inline int64_t sign_ext(uint64_t data, int origWidth)
99 {
100 int shiftAmount = 64 - origWidth;
101 return (((int64_t)data) << shiftAmount) >> shiftAmount;
102 }
103}};
104
105output decoder {{
106
107 char * CondTestAbbrev[] =
108 {
109 "nev", //Never
110 "e", //Equal
111 "le", //Less or Equal
112 "l", //Less
113 "leu", //Less or Equal Unsigned
114 "c", //Carry set
115 "n", //Negative
116 "o", //Overflow set
117 "a", //Always
118 "ne", //Not Equal
119 "g", //Greater
120 "ge", //Greater or Equal
121 "gu", //Greater Unsigned
122 "cc", //Carry clear
123 "p", //Positive
124 "oc" //Overflow Clear
125 };
126}};
127
128def template ROrImmDecode {{
129 {
130 return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
131 : (SparcStaticInst *)(new %(class_name)s(machInst)));
132 }
133}};
134
135let {{
136 def splitOutImm(code):
137 matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
138 rOrImmMatch = matcher.search(code)
139 if (rOrImmMatch == None):
140 return (False, code, '', '', '')
141 rString = rOrImmMatch.group("rNum")
142 if (rOrImmMatch.group("typeQual") != None):
143 rString += rOrImmMatch.group("typeQual")
144 iString = rOrImmMatch.group("iNum")
145 orig_code = code
146 code = matcher.sub('Rs' + rString, orig_code)
147 imm_code = matcher.sub('imm', orig_code)
148 return (True, code, imm_code, rString, iString)
149}};
150
151output decoder {{
152
153 inline void printMnemonic(std::ostream &os, const char * mnemonic)
154 {
155 ccprintf(os, "\t%s ", mnemonic);
156 }
157
158 void SparcStaticInst::printRegArray(std::ostream &os,
159 const RegIndex indexArray[], int num) const
160 {
161 if(num <= 0)
162 return;
163 printReg(os, indexArray[0]);
164 for(int x = 1; x < num; x++)
165 {
166 os << ", ";
167 printReg(os, indexArray[x]);
168 }
169 }
170
171 void
172 SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
173 {
174 if(_numSrcRegs > reg)
175 printReg(os, _srcRegIdx[reg]);
176 }
177
178 void
179 SparcStaticInst::printDestReg(std::ostream &os, int reg) const
180 {
181 if(_numDestRegs > reg)
182 printReg(os, _destRegIdx[reg]);
183 }
184
185 void
186 SparcStaticInst::printReg(std::ostream &os, int reg) const
187 {
188 const int MaxGlobal = 8;
189 const int MaxOutput = 16;
190 const int MaxLocal = 24;
191 const int MaxInput = 32;
192 const int MaxMicroReg = 33;
193 if (reg == FramePointerReg)
194 ccprintf(os, "%%fp");
195 else if (reg == StackPointerReg)
196 ccprintf(os, "%%sp");
197 else if(reg < MaxGlobal)
198 ccprintf(os, "%%g%d", reg);
199 else if(reg < MaxOutput)
200 ccprintf(os, "%%o%d", reg - MaxGlobal);
201 else if(reg < MaxLocal)
202 ccprintf(os, "%%l%d", reg - MaxOutput);
203 else if(reg < MaxInput)
204 ccprintf(os, "%%i%d", reg - MaxLocal);
205 else if(reg < MaxMicroReg)
206 ccprintf(os, "%%u%d", reg - MaxInput);
207 else {
208 ccprintf(os, "%%f%d", reg - MaxMicroReg);
192 const int MaxMicroReg = 40;
193 if (reg < FP_Base_DepTag) {
194 //If we used a register from the next or previous window,
195 //take out the offset.
196 while (reg >= MaxMicroReg)
197 reg -= MaxMicroReg;
198 if (reg == FramePointerReg)
199 ccprintf(os, "%%fp");
200 else if (reg == StackPointerReg)
201 ccprintf(os, "%%sp");
202 else if(reg < MaxGlobal)
203 ccprintf(os, "%%g%d", reg);
204 else if(reg < MaxOutput)
205 ccprintf(os, "%%o%d", reg - MaxGlobal);
206 else if(reg < MaxLocal)
207 ccprintf(os, "%%l%d", reg - MaxOutput);
208 else if(reg < MaxInput)
209 ccprintf(os, "%%i%d", reg - MaxLocal);
210 else if(reg < MaxMicroReg)
211 ccprintf(os, "%%u%d", reg - MaxInput);
212 //The fake int regs that are really control regs
213 else {
214 switch (reg - MaxMicroReg) {
215 case 1:
216 ccprintf(os, "%%y");
217 break;
218 case 2:
219 ccprintf(os, "%%ccr");
220 break;
221 case 3:
222 ccprintf(os, "%%cansave");
223 break;
224 case 4:
225 ccprintf(os, "%%canrestore");
226 break;
227 case 5:
228 ccprintf(os, "%%cleanwin");
229 break;
230 case 6:
231 ccprintf(os, "%%otherwin");
232 break;
233 case 7:
234 ccprintf(os, "%%wstate");
235 break;
236 }
237 }
238 } else if (reg < Ctrl_Base_DepTag) {
239 ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
240 } else {
241 switch (reg - Ctrl_Base_DepTag) {
242 case MISCREG_ASI:
243 ccprintf(os, "%%asi");
244 break;
245 case MISCREG_FPRS:
246 ccprintf(os, "%%fprs");
247 break;
248 case MISCREG_PCR:
249 ccprintf(os, "%%pcr");
250 break;
251 case MISCREG_PIC:
252 ccprintf(os, "%%pic");
253 break;
254 case MISCREG_GSR:
255 ccprintf(os, "%%gsr");
256 break;
257 case MISCREG_SOFTINT:
258 ccprintf(os, "%%softint");
259 break;
260 case MISCREG_SOFTINT_SET:
261 ccprintf(os, "%%softint_set");
262 break;
263 case MISCREG_SOFTINT_CLR:
264 ccprintf(os, "%%softint_clr");
265 break;
266 case MISCREG_TICK_CMPR:
267 ccprintf(os, "%%tick_cmpr");
268 break;
269 case MISCREG_STICK:
270 ccprintf(os, "%%stick");
271 break;
272 case MISCREG_STICK_CMPR:
273 ccprintf(os, "%%stick_cmpr");
274 break;
275 case MISCREG_TPC:
276 ccprintf(os, "%%tpc");
277 break;
278 case MISCREG_TNPC:
279 ccprintf(os, "%%tnpc");
280 break;
281 case MISCREG_TSTATE:
282 ccprintf(os, "%%tstate");
283 break;
284 case MISCREG_TT:
285 ccprintf(os, "%%tt");
286 break;
287 case MISCREG_TICK:
288 ccprintf(os, "%%tick");
289 break;
290 case MISCREG_TBA:
291 ccprintf(os, "%%tba");
292 break;
293 case MISCREG_PSTATE:
294 ccprintf(os, "%%pstate");
295 break;
296 case MISCREG_TL:
297 ccprintf(os, "%%tl");
298 break;
299 case MISCREG_PIL:
300 ccprintf(os, "%%pil");
301 break;
302 case MISCREG_CWP:
303 ccprintf(os, "%%cwp");
304 break;
305 case MISCREG_GL:
306 ccprintf(os, "%%gl");
307 break;
308 case MISCREG_HPSTATE:
309 ccprintf(os, "%%hpstate");
310 break;
311 case MISCREG_HTSTATE:
312 ccprintf(os, "%%htstate");
313 break;
314 case MISCREG_HINTP:
315 ccprintf(os, "%%hintp");
316 break;
317 case MISCREG_HTBA:
318 ccprintf(os, "%%htba");
319 break;
320 case MISCREG_HSTICK_CMPR:
321 ccprintf(os, "%%hstick_cmpr");
322 break;
323 case MISCREG_HVER:
324 ccprintf(os, "%%hver");
325 break;
326 case MISCREG_STRAND_STS_REG:
327 ccprintf(os, "%%strand_sts_reg");
328 break;
329 case MISCREG_FSR:
330 ccprintf(os, "%%fsr");
331 break;
332 default:
333 ccprintf(os, "%%ctrl%d", reg - Ctrl_Base_DepTag);
334 }
209 }
210 }
211
212 std::string SparcStaticInst::generateDisassembly(Addr pc,
213 const SymbolTable *symtab) const
214 {
215 std::stringstream ss;
216
217 printMnemonic(ss, mnemonic);
218
219 // just print the first two source regs... if there's
220 // a third one, it's a read-modify-write dest (Rc),
221 // e.g. for CMOVxx
222 if(_numSrcRegs > 0)
223 {
224 printReg(ss, _srcRegIdx[0]);
225 }
226 if(_numSrcRegs > 1)
227 {
228 ss << ",";
229 printReg(ss, _srcRegIdx[1]);
230 }
231
232 // just print the first dest... if there's a second one,
233 // it's generally implicit
234 if(_numDestRegs > 0)
235 {
236 if(_numSrcRegs > 0)
237 ss << ",";
238 printReg(ss, _destRegIdx[0]);
239 }
240
241 return ss.str();
242 }
243
244 bool passesCondition(uint32_t codes, uint32_t condition)
245 {
246 CondCodes condCodes;
247 condCodes.bits = 0;
248 condCodes.c = codes & 0x1 ? 1 : 0;
249 condCodes.v = codes & 0x2 ? 1 : 0;
250 condCodes.z = codes & 0x4 ? 1 : 0;
251 condCodes.n = codes & 0x8 ? 1 : 0;
252
253 switch(condition)
254 {
255 case Always:
256 return true;
257 case Never:
258 return false;
259 case NotEqual:
260 return !condCodes.z;
261 case Equal:
262 return condCodes.z;
263 case Greater:
264 return !(condCodes.z | (condCodes.n ^ condCodes.v));
265 case LessOrEqual:
266 return condCodes.z | (condCodes.n ^ condCodes.v);
267 case GreaterOrEqual:
268 return !(condCodes.n ^ condCodes.v);
269 case Less:
270 return (condCodes.n ^ condCodes.v);
271 case GreaterUnsigned:
272 return !(condCodes.c | condCodes.z);
273 case LessOrEqualUnsigned:
274 return (condCodes.c | condCodes.z);
275 case CarryClear:
276 return !condCodes.c;
277 case CarrySet:
278 return condCodes.c;
279 case Positive:
280 return !condCodes.n;
281 case Negative:
282 return condCodes.n;
283 case OverflowClear:
284 return !condCodes.v;
285 case OverflowSet:
286 return condCodes.v;
287 }
288 panic("Tried testing condition nonexistant "
289 "condition code %d", condition);
290 }
291}};
292
335 }
336 }
337
338 std::string SparcStaticInst::generateDisassembly(Addr pc,
339 const SymbolTable *symtab) const
340 {
341 std::stringstream ss;
342
343 printMnemonic(ss, mnemonic);
344
345 // just print the first two source regs... if there's
346 // a third one, it's a read-modify-write dest (Rc),
347 // e.g. for CMOVxx
348 if(_numSrcRegs > 0)
349 {
350 printReg(ss, _srcRegIdx[0]);
351 }
352 if(_numSrcRegs > 1)
353 {
354 ss << ",";
355 printReg(ss, _srcRegIdx[1]);
356 }
357
358 // just print the first dest... if there's a second one,
359 // it's generally implicit
360 if(_numDestRegs > 0)
361 {
362 if(_numSrcRegs > 0)
363 ss << ",";
364 printReg(ss, _destRegIdx[0]);
365 }
366
367 return ss.str();
368 }
369
370 bool passesCondition(uint32_t codes, uint32_t condition)
371 {
372 CondCodes condCodes;
373 condCodes.bits = 0;
374 condCodes.c = codes & 0x1 ? 1 : 0;
375 condCodes.v = codes & 0x2 ? 1 : 0;
376 condCodes.z = codes & 0x4 ? 1 : 0;
377 condCodes.n = codes & 0x8 ? 1 : 0;
378
379 switch(condition)
380 {
381 case Always:
382 return true;
383 case Never:
384 return false;
385 case NotEqual:
386 return !condCodes.z;
387 case Equal:
388 return condCodes.z;
389 case Greater:
390 return !(condCodes.z | (condCodes.n ^ condCodes.v));
391 case LessOrEqual:
392 return condCodes.z | (condCodes.n ^ condCodes.v);
393 case GreaterOrEqual:
394 return !(condCodes.n ^ condCodes.v);
395 case Less:
396 return (condCodes.n ^ condCodes.v);
397 case GreaterUnsigned:
398 return !(condCodes.c | condCodes.z);
399 case LessOrEqualUnsigned:
400 return (condCodes.c | condCodes.z);
401 case CarryClear:
402 return !condCodes.c;
403 case CarrySet:
404 return condCodes.c;
405 case Positive:
406 return !condCodes.n;
407 case Negative:
408 return condCodes.n;
409 case OverflowClear:
410 return !condCodes.v;
411 case OverflowSet:
412 return condCodes.v;
413 }
414 panic("Tried testing condition nonexistant "
415 "condition code %d", condition);
416 }
417}};
418
293output exec {{
294 /// Check "FP enabled" machine status bit. Called when executing any FP
295 /// instruction in full-system mode.
296 /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
297 /// if not. Non-full-system mode: always returns NoFault.
298#if FULL_SYSTEM
299 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
300 {
301 Fault fault = NoFault; // dummy... this ipr access should not fault
302 if (xc->readMiscRegWithEffect(MISCREG_PSTATE) & PSTATE::pef &&
303 xc->readMiscRegWithEffect(MISCREG_FPRS) & 0x4)
304 return NoFault;
305 else
306 return new FpDisabled;
307 }
308#else
309 inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
310 {
311 return NoFault;
312 }
313#endif
314}};
315
316