Mercurial > hg > graal-jvmci-8
comparison agent/src/share/classes/sun/jvm/hotspot/asm/x86/InstructionDecoder.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 package sun.jvm.hotspot.asm.x86; | |
26 | |
27 import sun.jvm.hotspot.asm.*; | |
28 | |
29 // basic instruction decoder class | |
30 public class InstructionDecoder implements /* imports */ X86Opcodes , RTLDataTypes, RTLOperations { | |
31 | |
32 protected String name; | |
33 protected int addrMode1; | |
34 protected int operandType1; | |
35 protected int addrMode2; | |
36 protected int operandType2; | |
37 protected int addrMode3; | |
38 protected int operandType3; | |
39 | |
40 private int mod; | |
41 private int regOrOpcode; | |
42 private int rm; | |
43 protected int prefixes; | |
44 | |
45 protected int byteIndex; | |
46 protected int instrStartIndex; | |
47 | |
48 public InstructionDecoder(String name) { | |
49 this.name = name; | |
50 this.operandType1 = INVALID_OPERANDTYPE; | |
51 this.operandType2 = INVALID_OPERANDTYPE; | |
52 this.operandType3 = INVALID_OPERANDTYPE; | |
53 this.addrMode1 = INVALID_ADDRMODE; | |
54 this.addrMode2 = INVALID_ADDRMODE; | |
55 this.addrMode3 = INVALID_ADDRMODE; | |
56 } | |
57 public InstructionDecoder(String name, int addrMode1, int operandType1) { | |
58 this(name); | |
59 this.addrMode1 = addrMode1; | |
60 this.operandType1 = operandType1; | |
61 } | |
62 public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2) { | |
63 this(name, addrMode1, operandType1); | |
64 this.addrMode2 = addrMode2; | |
65 this.operandType2 = operandType2; | |
66 } | |
67 public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2, | |
68 int addrMode3, int operandType3) { | |
69 this(name, addrMode1, operandType1, addrMode2, operandType2); | |
70 this.addrMode3 = addrMode3; | |
71 this.operandType3 = operandType3; | |
72 } | |
73 // "operand1" | |
74 protected Operand getOperand1(byte[] bytesArray, boolean operandSize, boolean addrSize) { | |
75 if( (addrMode1 != INVALID_ADDRMODE) && (operandType1 != INVALID_OPERANDTYPE) ) | |
76 return getOperand(bytesArray, addrMode1, operandType1, operandSize, addrSize); | |
77 else | |
78 return null; | |
79 } | |
80 | |
81 // "operand2" | |
82 protected Operand getOperand2(byte[] bytesArray, boolean operandSize, boolean addrSize) { | |
83 if( (addrMode2 != INVALID_ADDRMODE) && (operandType2 != INVALID_OPERANDTYPE) ) | |
84 return getOperand(bytesArray, addrMode2, operandType2, operandSize, addrSize); | |
85 else | |
86 return null; | |
87 } | |
88 | |
89 // "operand3" | |
90 protected Operand getOperand3(byte[] bytesArray, boolean operandSize, boolean addrSize) { | |
91 if( (addrMode3 != INVALID_ADDRMODE) && (operandType3 != INVALID_OPERANDTYPE) ) | |
92 return getOperand(bytesArray, addrMode3, operandType3, operandSize, addrSize); | |
93 else | |
94 return null; | |
95 } | |
96 | |
97 static int readInt32(byte[] bytesArray, int index) { | |
98 int ret = 0; | |
99 ret = readByte(bytesArray, index); | |
100 ret |= readByte(bytesArray, index+1) << 8; | |
101 ret |= readByte(bytesArray, index+2) << 16; | |
102 ret |= readByte(bytesArray, index+3) << 24; | |
103 return ret; | |
104 } | |
105 static int readInt16(byte[] bytesArray, int index) { | |
106 int ret = 0; | |
107 ret = readByte(bytesArray, index); | |
108 ret |= readByte(bytesArray, index+1) << 8; | |
109 return ret; | |
110 } | |
111 static int readByte(byte[] bytesArray, int index) { | |
112 int ret = 0; | |
113 if (index < bytesArray.length) { | |
114 ret = (int)bytesArray[index]; | |
115 ret = ret & 0xff; | |
116 } | |
117 return ret; | |
118 } | |
119 private boolean isModRMPresent(int addrMode) { | |
120 if( (addrMode == ADDR_E) || (addrMode == ADDR_G) || (addrMode == ADDR_FPREG) || (addrMode == ADDR_Q) || (addrMode == ADDR_W) ) | |
121 return true; | |
122 else | |
123 return false; | |
124 } | |
125 public int getCurrentIndex() { | |
126 return byteIndex; | |
127 } | |
128 | |
129 public Instruction decode(byte[] bytesArray, int index, int instrStartIndex, int segmentOverride, int prefixes, X86InstructionFactory factory) { | |
130 this.byteIndex = index; | |
131 this.instrStartIndex = instrStartIndex; | |
132 this.prefixes = prefixes; | |
133 boolean operandSize; //operand-size prefix | |
134 boolean addrSize; //address-size prefix | |
135 if ( ( (prefixes & PREFIX_DATA) ^ segmentOverride ) == 1) | |
136 operandSize = true; | |
137 else | |
138 operandSize = false; | |
139 if ( ((prefixes & PREFIX_ADR) ^ segmentOverride) == 1) | |
140 addrSize = true; | |
141 else | |
142 addrSize = false; | |
143 this.name = getCorrectOpcodeName(name, prefixes, operandSize, addrSize); | |
144 | |
145 //Fetch the mod/reg/rm byte only if it is present. | |
146 if( isModRMPresent(addrMode1) || isModRMPresent(addrMode2) || isModRMPresent(addrMode3) ) { | |
147 | |
148 int ModRM = readByte(bytesArray, byteIndex); | |
149 byteIndex++; | |
150 mod = (ModRM >> 6) & 3; | |
151 regOrOpcode = (ModRM >> 3) & 7; | |
152 rm = ModRM & 7; | |
153 } | |
154 return decodeInstruction(bytesArray, operandSize, addrSize, factory); | |
155 } | |
156 | |
157 protected Instruction decodeInstruction(byte[] bytesArray, boolean operandSize, boolean addrSize, X86InstructionFactory factory) { | |
158 Operand op1 = getOperand1(bytesArray, operandSize, addrSize); | |
159 Operand op2 = getOperand2(bytesArray, operandSize, addrSize); | |
160 Operand op3 = getOperand3(bytesArray, operandSize, addrSize); | |
161 int size = byteIndex - instrStartIndex; | |
162 return factory.newGeneralInstruction(name, op1, op2, op3, size, prefixes); | |
163 } | |
164 | |
165 // capital letters in template are macros | |
166 private String getCorrectOpcodeName(String oldName, int prefixes, boolean operandSize, boolean addrSize) { | |
167 StringBuffer newName = new StringBuffer(oldName); | |
168 int index = 0; | |
169 for(index=0; index<oldName.length(); index++) { | |
170 switch (oldName.charAt(index)) { | |
171 case 'C': /* For jcxz/jecxz */ | |
172 if (addrSize) | |
173 newName.setCharAt(index, 'e'); | |
174 index++; | |
175 break; | |
176 case 'N': | |
177 if ((prefixes & PREFIX_FWAIT) == 0) | |
178 newName.setCharAt(index, 'n'); | |
179 index++; | |
180 break; | |
181 case 'S': | |
182 /* operand size flag */ | |
183 if (operandSize == true) | |
184 newName.setCharAt(index, 'l'); | |
185 else | |
186 newName.setCharAt(index, 'w'); | |
187 index++; | |
188 break; | |
189 default: | |
190 break; | |
191 } | |
192 } | |
193 return newName.toString(); | |
194 } | |
195 | |
196 //IA-32 Intel Architecture Software Developer's Manual Volume 2 | |
197 //Refer to Chapter 2 - Instruction Format | |
198 | |
199 //Get the Operand object from the address type and the operand type | |
200 private Operand getOperand(byte[] bytesArray, int addrMode, int operandType, boolean operandSize, boolean addrSize) { | |
201 Operand op = null; | |
202 switch(addrMode) { | |
203 case ADDR_E: | |
204 case ADDR_W: //SSE: ModR/M byte specifies either 128 bit XMM register or memory | |
205 case ADDR_Q: //SSE: ModR/M byte specifies either 128 bit MMX register or memory | |
206 X86SegmentRegister segReg = getSegmentRegisterFromPrefix(prefixes); | |
207 | |
208 if (mod == 3) { //Register operand, no SIB follows | |
209 if (addrMode == ADDR_E) { | |
210 switch (operandType) { | |
211 case b_mode: | |
212 op = X86Registers.getRegister8(rm); | |
213 break; | |
214 case w_mode: | |
215 op = X86Registers.getRegister16(rm); | |
216 break; | |
217 case v_mode: | |
218 if (operandSize == true) //Operand size prefix is present | |
219 op = X86Registers.getRegister32(rm); | |
220 else | |
221 op = X86Registers.getRegister16(rm); | |
222 break; | |
223 case p_mode: | |
224 X86Register reg; | |
225 if (operandSize == true) //Operand size prefix is present | |
226 reg = X86Registers.getRegister32(rm); | |
227 else | |
228 reg = X86Registers.getRegister16(rm); | |
229 | |
230 op = new X86RegisterIndirectAddress(segReg, reg, null, 0); | |
231 break; | |
232 default: | |
233 break; | |
234 } | |
235 } else if (addrMode == ADDR_W) { | |
236 op = X86XMMRegisters.getRegister(rm); | |
237 } else if (addrMode == ADDR_Q) { | |
238 op = X86MMXRegisters.getRegister(rm); | |
239 } | |
240 | |
241 } else { //mod != 3 | |
242 //SIB follows for (rm==4), SIB gives scale, index and base in this case | |
243 //disp32 is present for (mod==0 && rm==5) || (mod==2) | |
244 //disp8 is present for (mod==1) | |
245 //for (rm!=4) base is register at rm. | |
246 int scale = 0; | |
247 int index = 0; | |
248 int base = 0; | |
249 long disp = 0; | |
250 if(rm == 4) { | |
251 int sib = readByte(bytesArray, byteIndex); | |
252 byteIndex++; | |
253 scale = (sib >> 6) & 3; | |
254 index = (sib >> 3) & 7; | |
255 base = sib & 7; | |
256 } | |
257 | |
258 switch (mod) { | |
259 case 0: | |
260 switch(rm) { | |
261 case 4: | |
262 if(base == 5) { | |
263 disp = readInt32(bytesArray, byteIndex); | |
264 byteIndex += 4; | |
265 if (index != 4) { | |
266 op = new X86RegisterIndirectAddress(segReg, null, X86Registers.getRegister32(index), disp, scale); | |
267 } else { | |
268 op = new X86RegisterIndirectAddress(segReg, null, null, disp, scale); | |
269 } | |
270 } | |
271 else { | |
272 if (index != 4) { | |
273 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), 0, scale); | |
274 } else { | |
275 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0, scale); | |
276 } | |
277 } | |
278 break; | |
279 case 5: | |
280 disp = readInt32(bytesArray, byteIndex); | |
281 byteIndex += 4; | |
282 //Create an Address object only with displacement | |
283 op = new X86RegisterIndirectAddress(segReg, null, null, disp); | |
284 break; | |
285 default: | |
286 base = rm; | |
287 //Create an Address object only with base | |
288 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0); | |
289 break; | |
290 } | |
291 break; | |
292 case 1: | |
293 disp = (byte)readByte(bytesArray, byteIndex); | |
294 byteIndex++; | |
295 if (rm !=4) { | |
296 base = rm; | |
297 //Address with base and disp only | |
298 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp); | |
299 } else { | |
300 if (index != 4) { | |
301 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale); | |
302 } else { | |
303 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale); | |
304 } | |
305 } | |
306 break; | |
307 case 2: | |
308 disp = readInt32(bytesArray, byteIndex); | |
309 byteIndex += 4; | |
310 if (rm !=4) { | |
311 base = rm; | |
312 //Address with base and disp | |
313 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp); | |
314 } else if (index != 4) { | |
315 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale); | |
316 } else { | |
317 op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale); | |
318 } | |
319 break; | |
320 } | |
321 } | |
322 break; | |
323 | |
324 case ADDR_I: | |
325 switch (operandType) { | |
326 case b_mode: | |
327 op = new Immediate(new Integer(readByte(bytesArray, byteIndex))); | |
328 byteIndex++; | |
329 break; | |
330 case w_mode: | |
331 op = new Immediate(new Integer(readInt16(bytesArray, byteIndex))); | |
332 byteIndex += 2; | |
333 break; | |
334 case v_mode: | |
335 if (operandSize == true) { //Operand size prefix is present | |
336 op = new Immediate(new Integer(readInt32(bytesArray, byteIndex))); | |
337 byteIndex += 4; | |
338 } else { | |
339 op = new Immediate(new Integer(readInt16(bytesArray, byteIndex))); | |
340 byteIndex += 2; | |
341 } | |
342 break; | |
343 default: | |
344 break; | |
345 } | |
346 break; | |
347 case ADDR_REG: //registers | |
348 switch(operandType) { | |
349 case EAX: | |
350 case ECX: | |
351 case EDX: | |
352 case EBX: | |
353 case ESP: | |
354 case EBP: | |
355 case ESI: | |
356 case EDI: | |
357 if(operandSize == true) { | |
358 op = X86Registers.getRegister32(operandType - EAX); | |
359 } | |
360 else { | |
361 op = X86Registers.getRegister16(operandType - EAX); | |
362 } | |
363 break; | |
364 case AX: | |
365 case CX: | |
366 case DX: | |
367 case BX: | |
368 case SP: | |
369 case BP: | |
370 case SI: | |
371 case DI: | |
372 op = X86Registers.getRegister16(operandType - AX); | |
373 break; | |
374 case AL: | |
375 case CL: | |
376 case DL: | |
377 case BL: | |
378 case AH: | |
379 case CH: | |
380 case DH: | |
381 case BH: | |
382 op = X86Registers.getRegister8(operandType - AL); | |
383 break; | |
384 case ES: //ES, CS, SS, DS, FS, GS | |
385 case CS: | |
386 case SS: | |
387 case DS: | |
388 case FS: | |
389 case GS: | |
390 op = X86SegmentRegisters.getSegmentRegister(operandType - ES); | |
391 break; | |
392 } | |
393 break; | |
394 case ADDR_DIR: //segment and offset | |
395 long segment = 0; | |
396 long offset = 0; | |
397 switch (operandType) { | |
398 case p_mode: | |
399 if (addrSize == true) { | |
400 offset = readInt32(bytesArray, byteIndex); | |
401 byteIndex += 4; | |
402 segment = readInt16(bytesArray, byteIndex); | |
403 byteIndex += 2; | |
404 } else { | |
405 offset = readInt16(bytesArray, byteIndex); | |
406 byteIndex += 2; | |
407 segment = readInt16(bytesArray, byteIndex); | |
408 byteIndex += 2; | |
409 } | |
410 op = new X86DirectAddress(segment, offset); //with offset | |
411 break; | |
412 case v_mode: | |
413 if (addrSize == true) { | |
414 offset = readInt32(bytesArray, byteIndex); | |
415 byteIndex += 4; | |
416 } else { | |
417 offset = readInt16(bytesArray, byteIndex); | |
418 byteIndex += 2; | |
419 } | |
420 op = new X86DirectAddress(offset); //with offset | |
421 break; | |
422 default: | |
423 break; | |
424 } | |
425 break; | |
426 case ADDR_G: | |
427 switch (operandType) { | |
428 case b_mode: | |
429 op = X86Registers.getRegister8(regOrOpcode); | |
430 break; | |
431 case w_mode: | |
432 op = X86Registers.getRegister16(regOrOpcode); | |
433 break; | |
434 case d_mode: | |
435 op = X86Registers.getRegister32(regOrOpcode); | |
436 break; | |
437 case v_mode: | |
438 if (operandSize == true) | |
439 op = X86Registers.getRegister32(regOrOpcode); | |
440 else | |
441 op = X86Registers.getRegister16(regOrOpcode); | |
442 break; | |
443 default: | |
444 break; | |
445 } | |
446 break; | |
447 case ADDR_SEG: | |
448 op = X86SegmentRegisters.getSegmentRegister(regOrOpcode); | |
449 break; | |
450 case ADDR_OFF: | |
451 int off = 0; | |
452 if (addrSize == true) { | |
453 off = readInt32(bytesArray, byteIndex); | |
454 byteIndex += 4; | |
455 } | |
456 else { | |
457 off = readInt16(bytesArray, byteIndex); | |
458 byteIndex += 2; | |
459 } | |
460 op = new X86DirectAddress((long)off); | |
461 break; | |
462 case ADDR_J: | |
463 long disp = 0; | |
464 //The effective address is Instruction pointer + relative offset | |
465 switch(operandType) { | |
466 case b_mode: | |
467 disp = (byte)readByte(bytesArray, byteIndex); | |
468 byteIndex++; | |
469 break; | |
470 case v_mode: | |
471 if (operandSize == true) { | |
472 disp = readInt32(bytesArray, byteIndex); | |
473 byteIndex += 4; | |
474 } | |
475 else { | |
476 disp = readInt16(bytesArray, byteIndex); | |
477 byteIndex += 2; | |
478 } | |
479 //disp = disp + (byteIndex-instrStartIndex); | |
480 break; | |
481 } | |
482 op = new X86PCRelativeAddress(disp); | |
483 break; | |
484 case ADDR_ESDI: | |
485 op = new X86SegmentRegisterAddress(X86SegmentRegisters.ES, X86Registers.DI); | |
486 break; | |
487 case ADDR_DSSI: | |
488 op = new X86SegmentRegisterAddress(X86SegmentRegisters.DS, X86Registers.SI); | |
489 break; | |
490 case ADDR_R: | |
491 switch (operandType) { | |
492 case b_mode: | |
493 op = X86Registers.getRegister8(mod); | |
494 break; | |
495 case w_mode: | |
496 op = X86Registers.getRegister16(mod); | |
497 break; | |
498 case d_mode: | |
499 op = X86Registers.getRegister32(mod); | |
500 break; | |
501 case v_mode: | |
502 if (operandSize == true) | |
503 op = X86Registers.getRegister32(mod); | |
504 else | |
505 op = X86Registers.getRegister16(mod); | |
506 break; | |
507 default: | |
508 break; | |
509 } | |
510 break; | |
511 case ADDR_FPREG: | |
512 switch (operandType) { | |
513 case 0: | |
514 op = X86FloatRegisters.getRegister(0); | |
515 break; | |
516 case 1: | |
517 op = X86FloatRegisters.getRegister(rm); | |
518 break; | |
519 } | |
520 break; | |
521 | |
522 //SSE: reg field of ModR/M byte selects a 128-bit XMM register | |
523 case ADDR_V: | |
524 op = X86XMMRegisters.getRegister(regOrOpcode); | |
525 break; | |
526 | |
527 //SSE: reg field of ModR/M byte selects a 64-bit MMX register | |
528 case ADDR_P: | |
529 op = X86MMXRegisters.getRegister(regOrOpcode); | |
530 break; | |
531 } | |
532 return op; | |
533 } | |
534 | |
535 private X86SegmentRegister getSegmentRegisterFromPrefix(int prefixes) { | |
536 X86SegmentRegister segRegister = null; | |
537 | |
538 if ( (prefixes & PREFIX_CS) != 0) | |
539 segRegister = X86SegmentRegisters.CS; | |
540 if ( (prefixes & PREFIX_DS) != 0) | |
541 segRegister = X86SegmentRegisters.DS; | |
542 if ( (prefixes & PREFIX_ES) != 0) | |
543 segRegister = X86SegmentRegisters.ES; | |
544 if ( (prefixes & PREFIX_FS) != 0) | |
545 segRegister = X86SegmentRegisters.FS; | |
546 if ( (prefixes & PREFIX_SS) != 0) | |
547 segRegister = X86SegmentRegisters.SS; | |
548 if ( (prefixes & PREFIX_GS) != 0) | |
549 segRegister = X86SegmentRegisters.GS; | |
550 | |
551 return segRegister; | |
552 } | |
553 | |
554 } |