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