Merge more changes in from head.
[gem5.git] / src / arch / x86 / predecoder.cc
1 /*
2 * Copyright (c) 2007 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/predecoder.hh"
59 #include "base/misc.hh"
60 #include "base/trace.hh"
61 #include "sim/host.hh"
62
63 namespace X86ISA
64 {
65 void Predecoder::reset()
66 {
67 origPC = basePC + offset;
68 DPRINTF(Predecoder, "Setting origPC to %#x\n", origPC);
69 emi.rex = 0;
70 emi.legacy = 0;
71 emi.opcode.num = 0;
72
73 immediateCollected = 0;
74 emi.immediate = 0;
75 emi.displacement = 0;
76
77 emi.modRM = 0;
78 emi.sib = 0;
79 emi.mode = 0;
80 }
81
82 void Predecoder::process()
83 {
84 //This function drives the predecoder state machine.
85
86 //Some sanity checks. You shouldn't try to process more bytes if
87 //there aren't any, and you shouldn't overwrite an already
88 //predecoder ExtMachInst.
89 assert(!outOfBytes);
90 assert(!emiIsReady);
91
92 //While there's still something to do...
93 while(!emiIsReady && !outOfBytes)
94 {
95 uint8_t nextByte = getNextByte();
96 switch(state)
97 {
98 case ResetState:
99 reset();
100 state = PrefixState;
101 case PrefixState:
102 state = doPrefixState(nextByte);
103 break;
104 case OpcodeState:
105 state = doOpcodeState(nextByte);
106 break;
107 case ModRMState:
108 state = doModRMState(nextByte);
109 break;
110 case SIBState:
111 state = doSIBState(nextByte);
112 break;
113 case DisplacementState:
114 state = doDisplacementState();
115 break;
116 case ImmediateState:
117 state = doImmediateState();
118 break;
119 case ErrorState:
120 panic("Went to the error state in the predecoder.\n");
121 default:
122 panic("Unrecognized state! %d\n", state);
123 }
124 }
125 }
126
127 //Either get a prefix and record it in the ExtMachInst, or send the
128 //state machine on to get the opcode(s).
129 Predecoder::State Predecoder::doPrefixState(uint8_t nextByte)
130 {
131 uint8_t prefix = Prefixes[nextByte];
132 State nextState = PrefixState;
133 if(prefix)
134 consumeByte();
135 switch(prefix)
136 {
137 //Operand size override prefixes
138 case OperandSizeOverride:
139 DPRINTF(Predecoder, "Found operand size override prefix.\n");
140 emi.legacy.op = true;
141 break;
142 case AddressSizeOverride:
143 DPRINTF(Predecoder, "Found address size override prefix.\n");
144 emi.legacy.addr = true;
145 break;
146 //Segment override prefixes
147 case CSOverride:
148 case DSOverride:
149 case ESOverride:
150 case FSOverride:
151 case GSOverride:
152 case SSOverride:
153 DPRINTF(Predecoder, "Found segment override.\n");
154 emi.legacy.seg = prefix;
155 break;
156 case Lock:
157 DPRINTF(Predecoder, "Found lock prefix.\n");
158 emi.legacy.lock = true;
159 break;
160 case Rep:
161 DPRINTF(Predecoder, "Found rep prefix.\n");
162 emi.legacy.rep = true;
163 break;
164 case Repne:
165 DPRINTF(Predecoder, "Found repne prefix.\n");
166 emi.legacy.repne = true;
167 break;
168 case RexPrefix:
169 DPRINTF(Predecoder, "Found Rex prefix %#x.\n", nextByte);
170 emi.rex = nextByte;
171 break;
172 case 0:
173 nextState = OpcodeState;
174 break;
175 default:
176 panic("Unrecognized prefix %#x\n", nextByte);
177 }
178 return nextState;
179 }
180
181 //Load all the opcodes (currently up to 2) and then figure out
182 //what immediate and/or ModRM is needed.
183 Predecoder::State Predecoder::doOpcodeState(uint8_t nextByte)
184 {
185 State nextState = ErrorState;
186 emi.opcode.num++;
187 //We can't handle 3+ byte opcodes right now
188 assert(emi.opcode.num < 3);
189 consumeByte();
190 if(emi.opcode.num == 1 && nextByte == 0x0f)
191 {
192 nextState = OpcodeState;
193 DPRINTF(Predecoder, "Found two byte opcode.\n");
194 emi.opcode.prefixA = nextByte;
195 }
196 else if(emi.opcode.num == 2 &&
197 (nextByte == 0x0f ||
198 (nextByte & 0xf8) == 0x38))
199 {
200 panic("Three byte opcodes aren't yet supported!\n");
201 nextState = OpcodeState;
202 DPRINTF(Predecoder, "Found three byte opcode.\n");
203 emi.opcode.prefixB = nextByte;
204 }
205 else
206 {
207 DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
208 emi.opcode.op = nextByte;
209
210 //Figure out the effective operand size. This can be overriden to
211 //a fixed value at the decoder level.
212 int logOpSize;
213 if(/*FIXME long mode*/1)
214 {
215 if(emi.rex.w)
216 logOpSize = 3; // 64 bit operand size
217 else if(emi.legacy.op)
218 logOpSize = 1; // 16 bit operand size
219 else
220 logOpSize = 2; // 32 bit operand size
221 }
222 else if(/*FIXME default 32*/1)
223 {
224 if(emi.legacy.op)
225 logOpSize = 1; // 16 bit operand size
226 else
227 logOpSize = 2; // 32 bit operand size
228 }
229 else // 16 bit default operand size
230 {
231 if(emi.legacy.op)
232 logOpSize = 2; // 32 bit operand size
233 else
234 logOpSize = 1; // 16 bit operand size
235 }
236
237 //Set the actual op size
238 emi.opSize = 1 << logOpSize;
239
240 //Figure out the effective address size. This can be overriden to
241 //a fixed value at the decoder level.
242 int logAddrSize;
243 if(/*FIXME 64-bit mode*/1)
244 {
245 if(emi.legacy.addr)
246 logAddrSize = 2; // 32 bit address size
247 else
248 logAddrSize = 3; // 64 bit address size
249 }
250 else if(/*FIXME default 32*/1)
251 {
252 if(emi.legacy.addr)
253 logAddrSize = 1; // 16 bit address size
254 else
255 logAddrSize = 2; // 32 bit address size
256 }
257 else // 16 bit default operand size
258 {
259 if(emi.legacy.addr)
260 logAddrSize = 2; // 32 bit address size
261 else
262 logAddrSize = 1; // 16 bit address size
263 }
264
265 //Set the actual address size
266 emi.addrSize = 1 << logAddrSize;
267
268 //Figure out how big of an immediate we'll retreive based
269 //on the opcode.
270 int immType = ImmediateType[emi.opcode.num - 1][nextByte];
271 immediateSize = SizeTypeToSize[logOpSize - 1][immType];
272
273 //Determine what to expect next
274 if (UsesModRM[emi.opcode.num - 1][nextByte]) {
275 nextState = ModRMState;
276 } else {
277 if(immediateSize) {
278 nextState = ImmediateState;
279 } else {
280 emiIsReady = true;
281 nextState = ResetState;
282 }
283 }
284 }
285 return nextState;
286 }
287
288 //Get the ModRM byte and determine what displacement, if any, there is.
289 //Also determine whether or not to get the SIB byte, displacement, or
290 //immediate next.
291 Predecoder::State Predecoder::doModRMState(uint8_t nextByte)
292 {
293 State nextState = ErrorState;
294 ModRM modRM;
295 modRM = nextByte;
296 DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
297 if (0) {//FIXME in 16 bit mode
298 //figure out 16 bit displacement size
299 if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2)
300 displacementSize = 2;
301 else if(modRM.mod == 1)
302 displacementSize = 1;
303 else
304 displacementSize = 0;
305 } else {
306 //figure out 32/64 bit displacement size
307 if(modRM.mod == 0 && modRM.rm == 5 || modRM.mod == 2)
308 displacementSize = 4;
309 else if(modRM.mod == 1)
310 displacementSize = 1;
311 else
312 displacementSize = 0;
313 }
314 //If there's an SIB, get that next.
315 //There is no SIB in 16 bit mode.
316 if(modRM.rm == 4 && modRM.mod != 3) {
317 // && in 32/64 bit mode)
318 nextState = SIBState;
319 } else if(displacementSize) {
320 nextState = DisplacementState;
321 } else if(immediateSize) {
322 nextState = ImmediateState;
323 } else {
324 emiIsReady = true;
325 nextState = ResetState;
326 }
327 //The ModRM byte is consumed no matter what
328 consumeByte();
329 emi.modRM = modRM;
330 return nextState;
331 }
332
333 //Get the SIB byte. We don't do anything with it at this point, other
334 //than storing it in the ExtMachInst. Determine if we need to get a
335 //displacement or immediate next.
336 Predecoder::State Predecoder::doSIBState(uint8_t nextByte)
337 {
338 State nextState = ErrorState;
339 emi.sib = nextByte;
340 DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
341 consumeByte();
342 if(emi.modRM.mod == 0 && emi.sib.base == 5)
343 displacementSize = 4;
344 if(displacementSize) {
345 nextState = DisplacementState;
346 } else if(immediateSize) {
347 nextState = ImmediateState;
348 } else {
349 emiIsReady = true;
350 nextState = ResetState;
351 }
352 return nextState;
353 }
354
355 //Gather up the displacement, or at least as much of it
356 //as we can get.
357 Predecoder::State Predecoder::doDisplacementState()
358 {
359 State nextState = ErrorState;
360
361 getImmediate(immediateCollected,
362 emi.displacement,
363 displacementSize);
364
365 DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
366 displacementSize, immediateCollected);
367
368 if(displacementSize == immediateCollected) {
369 //Reset this for other immediates.
370 immediateCollected = 0;
371 //Sign extend the displacement
372 switch(displacementSize)
373 {
374 case 1:
375 emi.displacement = sext<8>(emi.displacement);
376 break;
377 case 2:
378 emi.displacement = sext<16>(emi.displacement);
379 break;
380 case 4:
381 emi.displacement = sext<32>(emi.displacement);
382 break;
383 default:
384 panic("Undefined displacement size!\n");
385 }
386 DPRINTF(Predecoder, "Collected displacement %#x.\n",
387 emi.displacement);
388 if(immediateSize) {
389 nextState = ImmediateState;
390 } else {
391 emiIsReady = true;
392 nextState = ResetState;
393 }
394 }
395 else
396 nextState = DisplacementState;
397 return nextState;
398 }
399
400 //Gather up the immediate, or at least as much of it
401 //as we can get
402 Predecoder::State Predecoder::doImmediateState()
403 {
404 State nextState = ErrorState;
405
406 getImmediate(immediateCollected,
407 emi.immediate,
408 immediateSize);
409
410 DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
411 immediateSize, immediateCollected);
412
413 if(immediateSize == immediateCollected)
414 {
415 //Reset this for other immediates.
416 immediateCollected = 0;
417
418 //XXX Warning! The following is an observed pattern and might
419 //not always be true!
420
421 //Instructions which use 64 bit operands but 32 bit immediates
422 //need to have the immediate sign extended to 64 bits.
423 //Instructions which use true 64 bit immediates won't be
424 //affected, and instructions that use true 32 bit immediates
425 //won't notice.
426 switch(immediateSize)
427 {
428 case 4:
429 emi.immediate = sext<32>(emi.immediate);
430 break;
431 case 1:
432 emi.immediate = sext<8>(emi.immediate);
433 }
434
435 DPRINTF(Predecoder, "Collected immediate %#x.\n",
436 emi.immediate);
437 emiIsReady = true;
438 nextState = ResetState;
439 }
440 else
441 nextState = ImmediateState;
442 return nextState;
443 }
444 }