X86: Implement some SSE fp microops and instructions.
[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
315 // The "test" instruction in group 3 needs an immediate, even though
316 // the other instructions with the same actual opcode don't.
317 if (emi.opcode.num == 1 && (modRM.reg & 0x6) == 0) {
318 if (emi.opcode.op == 0xF6)
319 immediateSize = 1;
320 else if (emi.opcode.op == 0xF7)
321 immediateSize = (emi.opSize == 8) ? 4 : emi.opSize;
322 }
323
324 //If there's an SIB, get that next.
325 //There is no SIB in 16 bit mode.
326 if (modRM.rm == 4 && modRM.mod != 3) {
327 // && in 32/64 bit mode)
328 nextState = SIBState;
329 } else if(displacementSize) {
330 nextState = DisplacementState;
331 } else if(immediateSize) {
332 nextState = ImmediateState;
333 } else {
334 emiIsReady = true;
335 nextState = ResetState;
336 }
337 //The ModRM byte is consumed no matter what
338 consumeByte();
339 emi.modRM = modRM;
340 return nextState;
341 }
342
343 //Get the SIB byte. We don't do anything with it at this point, other
344 //than storing it in the ExtMachInst. Determine if we need to get a
345 //displacement or immediate next.
346 Predecoder::State Predecoder::doSIBState(uint8_t nextByte)
347 {
348 State nextState = ErrorState;
349 emi.sib = nextByte;
350 DPRINTF(Predecoder, "Found SIB byte %#x.\n", nextByte);
351 consumeByte();
352 if (emi.modRM.mod == 0 && emi.sib.base == 5)
353 displacementSize = 4;
354 if (displacementSize) {
355 nextState = DisplacementState;
356 } else if(immediateSize) {
357 nextState = ImmediateState;
358 } else {
359 emiIsReady = true;
360 nextState = ResetState;
361 }
362 return nextState;
363 }
364
365 //Gather up the displacement, or at least as much of it
366 //as we can get.
367 Predecoder::State Predecoder::doDisplacementState()
368 {
369 State nextState = ErrorState;
370
371 getImmediate(immediateCollected,
372 emi.displacement,
373 displacementSize);
374
375 DPRINTF(Predecoder, "Collecting %d byte displacement, got %d bytes.\n",
376 displacementSize, immediateCollected);
377
378 if(displacementSize == immediateCollected) {
379 //Reset this for other immediates.
380 immediateCollected = 0;
381 //Sign extend the displacement
382 switch(displacementSize)
383 {
384 case 1:
385 emi.displacement = sext<8>(emi.displacement);
386 break;
387 case 2:
388 emi.displacement = sext<16>(emi.displacement);
389 break;
390 case 4:
391 emi.displacement = sext<32>(emi.displacement);
392 break;
393 default:
394 panic("Undefined displacement size!\n");
395 }
396 DPRINTF(Predecoder, "Collected displacement %#x.\n",
397 emi.displacement);
398 if(immediateSize) {
399 nextState = ImmediateState;
400 } else {
401 emiIsReady = true;
402 nextState = ResetState;
403 }
404 }
405 else
406 nextState = DisplacementState;
407 return nextState;
408 }
409
410 //Gather up the immediate, or at least as much of it
411 //as we can get
412 Predecoder::State Predecoder::doImmediateState()
413 {
414 State nextState = ErrorState;
415
416 getImmediate(immediateCollected,
417 emi.immediate,
418 immediateSize);
419
420 DPRINTF(Predecoder, "Collecting %d byte immediate, got %d bytes.\n",
421 immediateSize, immediateCollected);
422
423 if(immediateSize == immediateCollected)
424 {
425 //Reset this for other immediates.
426 immediateCollected = 0;
427
428 //XXX Warning! The following is an observed pattern and might
429 //not always be true!
430
431 //Instructions which use 64 bit operands but 32 bit immediates
432 //need to have the immediate sign extended to 64 bits.
433 //Instructions which use true 64 bit immediates won't be
434 //affected, and instructions that use true 32 bit immediates
435 //won't notice.
436 switch(immediateSize)
437 {
438 case 4:
439 emi.immediate = sext<32>(emi.immediate);
440 break;
441 case 1:
442 emi.immediate = sext<8>(emi.immediate);
443 }
444
445 DPRINTF(Predecoder, "Collected immediate %#x.\n",
446 emi.immediate);
447 emiIsReady = true;
448 nextState = ResetState;
449 }
450 else
451 nextState = ImmediateState;
452 return nextState;
453 }
454 }