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