merge code
[gem5.git] / src / arch / x86 / predecoder.cc
1 /*
2 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use. Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 * Director of Intellectual Property Licensing
21 * Office of Strategy and Technology
22 * Hewlett-Packard Company
23 * 1501 Page Mill Road
24 * Palo Alto, California 94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer. Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution. Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission. No right of
34 * sublicense is granted herewith. Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses. Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58 #include "arch/x86/miscregs.hh"
59 #include "arch/x86/predecoder.hh"
60 #include "base/misc.hh"
61 #include "base/trace.hh"
62 #include "cpu/thread_context.hh"
63 #include "sim/host.hh"
64
65 namespace X86ISA
66 {
67 void Predecoder::doReset()
68 {
69 origPC = basePC + offset;
70 DPRINTF(Predecoder, "Setting origPC to %#x\n", origPC);
71 emi.rex = 0;
72 emi.legacy = 0;
73 emi.opcode.num = 0;
74 emi.opcode.op = 0;
75 emi.opcode.prefixA = emi.opcode.prefixB = 0;
76
77 immediateCollected = 0;
78 emi.immediate = 0;
79 emi.displacement = 0;
80
81 emi.modRM = 0;
82 emi.sib = 0;
83 m5Reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
84 emi.mode.mode = m5Reg.mode;
85 emi.mode.submode = m5Reg.submode;
86 }
87
88 void Predecoder::process()
89 {
90 //This function drives the predecoder state machine.
91
92 //Some sanity checks. You shouldn't try to process more bytes if
93 //there aren't any, and you shouldn't overwrite an already
94 //predecoder ExtMachInst.
95 assert(!outOfBytes);
96 assert(!emiIsReady);
97
98 //While there's still something to do...
99 while(!emiIsReady && !outOfBytes)
100 {
101 uint8_t nextByte = getNextByte();
102 switch(state)
103 {
104 case ResetState:
105 doReset();
106 state = PrefixState;
107 case PrefixState:
108 state = doPrefixState(nextByte);
109 break;
110 case OpcodeState:
111 state = doOpcodeState(nextByte);
112 break;
113 case ModRMState:
114 state = doModRMState(nextByte);
115 break;
116 case SIBState:
117 state = doSIBState(nextByte);
118 break;
119 case DisplacementState:
120 state = doDisplacementState();
121 break;
122 case ImmediateState:
123 state = doImmediateState();
124 break;
125 case ErrorState:
126 panic("Went to the error state in the predecoder.\n");
127 default:
128 panic("Unrecognized state! %d\n", state);
129 }
130 }
131 }
132
133 //Either get a prefix and record it in the ExtMachInst, or send the
134 //state machine on to get the opcode(s).
135 Predecoder::State Predecoder::doPrefixState(uint8_t nextByte)
136 {
137 uint8_t prefix = Prefixes[nextByte];
138 State nextState = PrefixState;
139 // REX prefixes are only recognized in 64 bit mode.
140 if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
141 prefix = 0;
142 if (prefix)
143 consumeByte();
144 switch(prefix)
145 {
146 //Operand size override prefixes
147 case OperandSizeOverride:
148 DPRINTF(Predecoder, "Found operand size override prefix.\n");
149 emi.legacy.op = true;
150 break;
151 case AddressSizeOverride:
152 DPRINTF(Predecoder, "Found address size override prefix.\n");
153 emi.legacy.addr = true;
154 break;
155 //Segment override prefixes
156 case CSOverride:
157 case DSOverride:
158 case ESOverride:
159 case FSOverride:
160 case GSOverride:
161 case SSOverride:
162 DPRINTF(Predecoder, "Found segment override.\n");
163 emi.legacy.seg = prefix;
164 break;
165 case Lock:
166 DPRINTF(Predecoder, "Found lock prefix.\n");
167 emi.legacy.lock = true;
168 break;
169 case Rep:
170 DPRINTF(Predecoder, "Found rep prefix.\n");
171 emi.legacy.rep = true;
172 break;
173 case Repne:
174 DPRINTF(Predecoder, "Found repne prefix.\n");
175 emi.legacy.repne = true;
176 break;
177 case RexPrefix:
178 DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
179 emi.rex = nextByte;
180 break;
181 case 0:
182 nextState = OpcodeState;
183 break;
184 default:
185 panic("Unrecognized prefix %#x\n", nextByte);
186 }
187 return nextState;
188 }
189
190 //Load all the opcodes (currently up to 2) and then figure out
191 //what immediate and/or ModRM is needed.
192 Predecoder::State Predecoder::doOpcodeState(uint8_t nextByte)
193 {
194 State nextState = ErrorState;
195 emi.opcode.num++;
196 //We can't handle 3+ byte opcodes right now
197 assert(emi.opcode.num < 3);
198 consumeByte();
199 if(emi.opcode.num == 1 && nextByte == 0x0f)
200 {
201 nextState = OpcodeState;
202 DPRINTF(Predecoder, "Found two byte opcode.\n");
203 emi.opcode.prefixA = nextByte;
204 }
205 else if(emi.opcode.num == 2 &&
206 (nextByte == 0x0f ||
207 (nextByte & 0xf8) == 0x38))
208 {
209 panic("Three byte opcodes aren't yet supported!\n");
210 nextState = OpcodeState;
211 DPRINTF(Predecoder, "Found three byte opcode.\n");
212 emi.opcode.prefixB = nextByte;
213 }
214 else
215 {
216 DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
217 emi.opcode.op = nextByte;
218
219 //Figure out the effective operand size. This can be overriden to
220 //a fixed value at the decoder level.
221 int logOpSize;
222 if (emi.rex.w)
223 logOpSize = 3; // 64 bit operand size
224 else if (emi.legacy.op)
225 logOpSize = m5Reg.altOp;
226 else
227 logOpSize = m5Reg.defOp;
228
229 //Set the actual op size
230 emi.opSize = 1 << logOpSize;
231
232 //Figure out the effective address size. This can be overriden to
233 //a fixed value at the decoder level.
234 int logAddrSize;
235 if(emi.legacy.addr)
236 logAddrSize = m5Reg.altAddr;
237 else
238 logAddrSize = m5Reg.defAddr;
239
240 //Set the actual address size
241 emi.addrSize = 1 << logAddrSize;
242
243 //Figure out the effective stack width. This can be overriden to
244 //a fixed value at the decoder level.
245 emi.stackSize = 1 << m5Reg.stack;
246
247 //Figure out how big of an immediate we'll retreive based
248 //on the opcode.
249 int immType = ImmediateType[emi.opcode.num - 1][nextByte];
250 if (emi.opcode.num == 1 && nextByte >= 0xA0 && nextByte <= 0xA3)
251 immediateSize = SizeTypeToSize[logAddrSize - 1][immType];
252 else
253 immediateSize = SizeTypeToSize[logOpSize - 1][immType];
254
255 //Determine what to expect next
256 if (UsesModRM[emi.opcode.num - 1][nextByte]) {
257 nextState = ModRMState;
258 } else {
259 if(immediateSize) {
260 nextState = ImmediateState;
261 } else {
262 emiIsReady = true;
263 nextState = ResetState;
264 }
265 }
266 }
267 return nextState;
268 }
269
270 //Get the ModRM byte and determine what displacement, if any, there is.
271 //Also determine whether or not to get the SIB byte, displacement, or
272 //immediate next.
273 Predecoder::State Predecoder::doModRMState(uint8_t nextByte)
274 {
275 State nextState = ErrorState;
276 ModRM modRM;
277 modRM = nextByte;
278 DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
279 if (m5Reg.defOp == 1) {
280 //figure out 16 bit displacement size
281 if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
282 displacementSize = 2;
283 else if (modRM.mod == 1)
284 displacementSize = 1;
285 else
286 displacementSize = 0;
287 } else {
288 //figure out 32/64 bit displacement size
289 if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
290 displacementSize = 4;
291 else if (modRM.mod == 1)
292 displacementSize = 1;
293 else
294 displacementSize = 0;
295 }
296
297 // The "test" instruction in group 3 needs an immediate, even though
298 // the other instructions with the same actual opcode don't.
299 if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
300 if (emi.opcode.op == 0xF6)
301 immediateSize = 1;
302 else if (emi.opcode.op == 0xF7)
303 immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
304 }
305
306 //If there's an SIB, get that next.
307 //There is no SIB in 16 bit mode.
308 if (modRM.rm == 4 && modRM.mod != 3) {
309 // && in 32/64 bit mode)
310 nextState = SIBState;
311 } else if(displacementSize) {
312 nextState = DisplacementState;
313 } else if(immediateSize) {
314 nextState = ImmediateState;
315 } else {
316 emiIsReady = true;
317 nextState = ResetState;
318 }
319 //The ModRM byte is consumed no matter what
320 consumeByte();
321 emi.modRM = modRM;
322 return nextState;
323 }
324
325 //Get the SIB byte. We don't do anything with it at this point, other
326 //than storing it in the ExtMachInst. Determine if we need to get a
327 //displacement or immediate next.
328 Predecoder::State Predecoder::doSIBState(uint8_t nextByte)
329 {
330 State nextState = ErrorState;
331 emi.sib = nextByte;
332 DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
333 consumeByte();
334 if (emi.modRM.mod == 0 && emi.sib.base == 5)
335 displacementSize = 4;
336 if (displacementSize) {
337 nextState = DisplacementState;
338 } else if(immediateSize) {
339 nextState = ImmediateState;
340 } else {
341 emiIsReady = true;
342 nextState = ResetState;
343 }
344 return nextState;
345 }
346
347 //Gather up the displacement, or at least as much of it
348 //as we can get.
349 Predecoder::State Predecoder::doDisplacementState()
350 {
351 State nextState = ErrorState;
352
353 getImmediate(immediateCollected,
354 emi.displacement,
355 displacementSize);
356
357 DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
358 displacementSize, immediateCollected);
359
360 if(displacementSize == immediateCollected) {
361 //Reset this for other immediates.
362 immediateCollected = 0;
363 //Sign extend the displacement
364 switch(displacementSize)
365 {
366 case 1:
367 emi.displacement = sext<8>(emi.displacement);
368 break;
369 case 2:
370 emi.displacement = sext<16>(emi.displacement);
371 break;
372 case 4:
373 emi.displacement = sext<32>(emi.displacement);
374 break;
375 default:
376 panic("Undefined displacement size!\n");
377 }
378 DPRINTF(Predecoder, "Collected displacement %#x.\n",
379 emi.displacement);
380 if(immediateSize) {
381 nextState = ImmediateState;
382 } else {
383 emiIsReady = true;
384 nextState = ResetState;
385 }
386 }
387 else
388 nextState = DisplacementState;
389 return nextState;
390 }
391
392 //Gather up the immediate, or at least as much of it
393 //as we can get
394 Predecoder::State Predecoder::doImmediateState()
395 {
396 State nextState = ErrorState;
397
398 getImmediate(immediateCollected,
399 emi.immediate,
400 immediateSize);
401
402 DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
403 immediateSize, immediateCollected);
404
405 if(immediateSize == immediateCollected)
406 {
407 //Reset this for other immediates.
408 immediateCollected = 0;
409
410 //XXX Warning! The following is an observed pattern and might
411 //not always be true!
412
413 //Instructions which use 64 bit operands but 32 bit immediates
414 //need to have the immediate sign extended to 64 bits.
415 //Instructions which use true 64 bit immediates won't be
416 //affected, and instructions that use true 32 bit immediates
417 //won't notice.
418 switch(immediateSize)
419 {
420 case 4:
421 emi.immediate = sext<32>(emi.immediate);
422 break;
423 case 1:
424 emi.immediate = sext<8>(emi.immediate);
425 }
426
427 DPRINTF(Predecoder, "Collected immediate %#x.\n",
428 emi.immediate);
429 emiIsReady = true;
430 nextState = ResetState;
431 }
432 else
433 nextState = ImmediateState;
434 return nextState;
435 }
436 }