1 /* |
|
2 * Copyright (c) 2002, 2003, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * 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 } |
|