1
2
3
4 package joeq.Compiler.Reference.x86;
5
6 import java.util.ArrayList;
7 import java.util.HashSet;
8 import java.util.Iterator;
9 import java.util.LinkedList;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import joeq.Allocator.DefaultHeapAllocator;
14 import joeq.Allocator.HeapAllocator;
15 import joeq.Allocator.ObjectLayout;
16 import joeq.Assembler.Code2HeapReference;
17 import joeq.Assembler.DirectBindCall;
18 import joeq.Assembler.x86.x86;
19 import joeq.Assembler.x86.x86Assembler;
20 import joeq.Assembler.x86.x86Constants;
21 import joeq.Class.PrimordialClassLoader;
22 import joeq.Class.jq_Array;
23 import joeq.Class.jq_BytecodeMap;
24 import joeq.Class.jq_Class;
25 import joeq.Class.jq_ClassFileConstants;
26 import joeq.Class.jq_CompiledCode;
27 import joeq.Class.jq_InstanceField;
28 import joeq.Class.jq_InstanceMethod;
29 import joeq.Class.jq_Method;
30 import joeq.Class.jq_StaticField;
31 import joeq.Class.jq_StaticMethod;
32 import joeq.Class.jq_TryCatch;
33 import joeq.Class.jq_TryCatchBC;
34 import joeq.Class.jq_Type;
35 import joeq.Compiler.CompilationState;
36 import joeq.Compiler.CompilerInterface;
37 import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
38 import joeq.Main.jq;
39 import joeq.Memory.CodeAddress;
40 import joeq.Memory.HeapAddress;
41 import joeq.Runtime.ExceptionDeliverer;
42 import joeq.Runtime.MathSupport;
43 import joeq.Runtime.Monitor;
44 import joeq.Runtime.Reflection;
45 import joeq.Runtime.SystemInterface;
46 import joeq.Runtime.TypeCheck;
47 import joeq.Runtime.Unsafe;
48 import joeq.Scheduler.jq_x86RegisterState;
49 import joeq.UTF.Utf8;
50 import jwutil.strings.Strings;
51 import jwutil.util.Assert;
52
53 /***
54 * @author John Whaley <jwhaley@alum.mit.edu>
55 * @version $Id: x86ReferenceCompiler.java 2070 2004-12-10 10:52:36Z joewhaley $
56 */
57 public class x86ReferenceCompiler extends BytecodeVisitor implements x86Constants, jq_ClassFileConstants {
58
59 static {
60
61 jq_x86RegisterState.initFactory();
62 }
63
64 public static class Factory implements CompilerInterface {
65 public static final Factory INSTANCE = new Factory();
66 public Factory() {}
67 public jq_CompiledCode compile(jq_Method m) {
68 return new x86ReferenceCompiler(m).compile();
69 }
70 public jq_CompiledCode generate_compile_stub(jq_Method m) {
71 return x86ReferenceCompiler.generate_compile_stub(m);
72 }
73 public jq_StaticMethod getInvokestaticLinkMethod() {
74 return x86ReferenceLinker._invokestatic;
75 }
76 public jq_StaticMethod getInvokespecialLinkMethod() {
77 return x86ReferenceLinker._invokespecial;
78 }
79 public jq_StaticMethod getInvokeinterfaceLinkMethod() {
80 return x86ReferenceLinker._invokeinterface;
81 }
82 }
83
84 public static
85 public static
86
87 public static final Set TraceMethod_MethodNames = new HashSet();
88 public static final Set TraceMethod_ClassNames = new HashSet();
89 public static final Set TraceBytecode_MethodNames = new HashSet();
90 public static final Set TraceBytecode_ClassNames = new HashSet();
91
92 public final boolean TraceBytecodes;
93 public final boolean TraceMethods;
94 public final boolean TraceArguments;
95
96 public static final int DEFAULT_ALIGNMENT = 32;
97
98 public x86ReferenceCompiler(jq_Method method) {
99 super(CompilationState.DEFAULT, method);
100 TRACE = ALWAYS_TRACE;
101 if (TraceBytecode_MethodNames.contains(method.getName().toString())) {
102 TraceBytecodes = true;
103 TraceMethods = true;
104 } else if (TraceBytecode_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
105 TraceBytecodes = true;
106 TraceMethods = true;
107 } else if (TraceMethod_MethodNames.contains(method.getName().toString())) {
108 TraceBytecodes = false;
109 TraceMethods = true;
110 } else if (TraceMethod_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
111 TraceBytecodes = false;
112 TraceMethods = true;
113 } else {
114 TraceBytecodes = false;
115 TraceMethods = false;
116 }
117 TraceArguments = false;
118 }
119
120 public void init(jq_Method method) {
121 Assert._assert(method == this.method);
122 }
123
124 public String toString() {
125 return "x86RC/"+Strings.left(method.getName().toString(), 10);
126 }
127
128 private x86Assembler asm;
129 private int n_paramwords;
130
131 private int getLocalOffset(int local) {
132 if (local < n_paramwords) {
133 return (n_paramwords-local+1)<<2;
134 } else {
135 return (n_paramwords-local-1)<<2;
136 }
137 }
138
139 private List code_relocs = new LinkedList();
140 private List data_relocs = new LinkedList();
141
142 public final void emitCallRelative(jq_Method target) { emitCallRelative(target, asm, code_relocs); }
143 public static final void emitCallRelative(jq_Method target, x86Assembler asm, List code_relocs) {
144 asm.emitCALL_rel32(x86.CALL_rel32, 0);
145 DirectBindCall r = new DirectBindCall((CodeAddress) asm.getCurrentAddress().offset(-4), target);
146 code_relocs.add(r);
147 if (ALWAYS_TRACE) System.out.println("Direct bind call: "+r);
148 }
149 public final void emitPushAddressOf(Object o) { emitPushAddressOf(o, asm, data_relocs); }
150 public static final void emitPushAddressOf(Object o, x86Assembler asm, List data_relocs) {
151 if (o != null) {
152 HeapAddress addr = HeapAddress.addressOf(o);
153 asm.emit1_Imm32(x86.PUSH_i32, addr.to32BitValue());
154 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
155 data_relocs.add(r);
156 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
157 } else {
158 asm.emit1_Imm8(x86.PUSH_i8, (byte)0);
159 }
160 }
161 public final void emitPushMemory(jq_StaticField f) { emitPushMemory(f, asm, data_relocs); }
162 public static final void emitPushMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
163 HeapAddress addr = f.getAddress();
164 asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue());
165 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
166 data_relocs.add(r);
167 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
168 }
169 public final void emitPushMemory8(jq_StaticField f) { emitPushMemory8(f, asm, data_relocs); }
170 public static final void emitPushMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
171 HeapAddress addr = f.getAddress();
172 asm.emit2_Mem(x86.PUSH_m, addr.offset(4).to32BitValue());
173 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
174 data_relocs.add(r);
175 asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue());
176 r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
177 data_relocs.add(r);
178 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
179 }
180 public final void emitPopMemory(jq_StaticField f) { emitPopMemory(f, asm, data_relocs); }
181 public static final void emitPopMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
182 HeapAddress addr = f.getAddress();
183 asm.emit2_Mem(x86.POP_m, addr.to32BitValue());
184 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
185 data_relocs.add(r);
186 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
187 }
188 public final void emitPopMemory8(jq_StaticField f) { emitPopMemory8(f, asm, data_relocs); }
189 public static final void emitPopMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
190 HeapAddress addr = f.getAddress();
191 asm.emit2_Mem(x86.POP_m, addr.to32BitValue());
192 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
193 data_relocs.add(r);
194 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
195 asm.emit2_Mem(x86.POP_m, addr.offset(4).to32BitValue());
196 r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
197 data_relocs.add(r);
198 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
199 }
200 public final void emitCallMemory(jq_StaticField f) { emitCallMemory(f, asm, data_relocs); }
201 public static final void emitCallMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
202 HeapAddress addr = f.getAddress();
203 asm.emit2_Mem(x86.CALL_m, addr.to32BitValue());
204 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
205 data_relocs.add(r);
206 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
207 }
208 public final void emitFLD64(jq_StaticField f) { emitFLD64(f, asm, data_relocs); }
209 public static final void emitFLD64(jq_StaticField f, x86Assembler asm, List data_relocs) {
210 HeapAddress addr = f.getAddress();
211 asm.emit2_Mem(x86.FLD_m64, addr.to32BitValue());
212 Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
213 data_relocs.add(r);
214 if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
215 }
216
217 public final List getCodeRelocs() { return code_relocs; }
218 public final List getDataRelocs() { return data_relocs; }
219
220 public static final jq_CompiledCode generate_compile_stub(jq_Method method) {
221 if (TRACE_STUBS) System.out.println("x86 Reference Compiler: generating compile stub for "+method);
222 x86Assembler asm = new x86Assembler(0, 24, 0, DEFAULT_ALIGNMENT);
223 asm.setEntrypoint();
224 List code_relocs = new LinkedList();
225 List data_relocs = new LinkedList();
226 if (TRACE_STUBS) {
227 emitPushAddressOf(SystemInterface.toCString("Stub compile: "+method), asm, data_relocs);
228 emitCallMemory(SystemInterface._debugwriteln, asm, data_relocs);
229 }
230 emitPushAddressOf(method, asm, data_relocs);
231 emitCallRelative(jq_Method._compile, asm, code_relocs);
232 asm.emit2_Mem(x86.JMP_m, jq_CompiledCode._entrypoint.getOffset(), EAX);
233
234 return asm.getCodeBuffer().allocateCodeBlock(null, null, null, null, 0, code_relocs, data_relocs);
235 }
236
237
238 public final jq_CompiledCode compile() {
239 if (TRACE) System.out.println("x86 Reference Compiler: compiling "+method);
240
241
242 if (jq.RunningNative)
243 Unsafe.getThreadBlock().disableThreadSwitch();
244
245 try {
246
247 asm = new x86Assembler(bcs.length, bcs.length*8, 5, DEFAULT_ALIGNMENT);
248 asm.skip(5);
249 asm.setEntrypoint();
250 n_paramwords = method.getParamWords();
251 int n_localwords = method.getMaxLocals();
252 Assert._assert(n_paramwords <= n_localwords);
253
254
255
256
257
258
259
260
261
262
263
264
265 asm.emitShort_Reg(x86.PUSH_r, EBP);
266 asm.emit2_Reg_Reg(x86.MOV_r_r32, EBP, ESP);
267 if (n_paramwords != n_localwords)
268 asm.emit2_Reg_Mem(x86.LEA, ESP, (n_paramwords-n_localwords)<<2, ESP);
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 if (TraceMethods) {
287 emitPushAddressOf(SystemInterface.toCString("Entering: "+method));
288 emitCallMemory(SystemInterface._debugwriteln);
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310 asm.emitPUSH_i(0x0000d00d);
311
312
313 if (method.isSynchronized()) {
314 if (method.isStatic()) {
315 if (TraceBytecodes) {
316 emitPushAddressOf(SystemInterface.toCString("entry: STATIC SYNCH ENTER"));
317 emitCallMemory(SystemInterface._debugwriteln);
318 }
319
320 Class c = Reflection.getJDKType(method.getDeclaringClass());
321 Assert._assert(c != null);
322 emitPushAddressOf(c);
323 } else {
324 if (TraceBytecodes) {
325 emitPushAddressOf(SystemInterface.toCString("entry: INSTANCE SYNCH ENTER"));
326 emitCallMemory(SystemInterface._debugwriteln);
327 }
328
329 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(0), EBP);
330 }
331 emitCallRelative(Monitor._monitorenter);
332 }
333
334
335 this.forwardTraversal();
336
337
338
339 Integer loc = new Integer(bcs.length);
340 asm.recordBranchTarget(loc);
341
342
343 jq_TryCatchBC[] tcs_bc = method.getExceptionTable();
344 jq_TryCatch[] tcs = new jq_TryCatch[tcs_bc.length];
345 for (int i=0; i<tcs_bc.length; ++i) {
346 jq_TryCatchBC tc_bc = tcs_bc[i];
347 Integer start = new Integer(tc_bc.getStartPC());
348 Integer end = new Integer(tc_bc.getEndPC());
349 Integer handler = new Integer(tc_bc.getHandlerPC());
350 jq_Class extype = tc_bc.getExceptionType();
351 int offset = ((n_paramwords-n_localwords)<<2) - 4;
352 tcs[i] = new jq_TryCatch(asm.getBranchTarget(start), asm.getBranchTarget(end),
353 asm.getBranchTarget(handler), extype, offset);
354 }
355
356
357 Map m = asm.getBranchTargetMap();
358 int numOfBC = m.size();
359 int[] offsets = new int[numOfBC];
360 int[] bcs = new int[numOfBC];
361 ArrayList keySet = new ArrayList(m.keySet());
362 java.util.Collections.sort(keySet);
363 Iterator it = keySet.iterator();
364 for (int i=0; i<numOfBC; ++i) {
365 Integer bc = (Integer)it.next();
366 bcs[i] = bc.intValue();
367 offsets[i] = ((Integer)m.get(bc)).intValue();
368 }
369 jq_BytecodeMap bcm = new jq_BytecodeMap(offsets, bcs);
370
371
372 jq_CompiledCode code;
373 code = asm.getCodeBuffer().allocateCodeBlock(method, tcs, bcm,
374 x86ReferenceExceptionDeliverer.INSTANCE,
375 (n_paramwords-n_localwords)<<2,
376 code_relocs, data_relocs);
377
378 if (jq.RunningNative)
379 Unsafe.getThreadBlock().enableThreadSwitch();
380 return code;
381 } catch (RuntimeException x) {
382 SystemInterface.debugwriteln("Exception occurred while compiling: "+method);
383 SystemInterface.debugwriteln("Exception: "+x);
384 x.printStackTrace();
385 SystemInterface.die(-1);
386 return null;
387 }
388 }
389
390 public void visitBytecode() throws VerifyError {
391 Integer loc = new Integer(i_start);
392 asm.recordBranchTarget(loc);
393 asm.resolveForwardBranches(loc);
394
395 super.visitBytecode();
396 }
397
398 public void visitNOP() {
399 super.visitNOP();
400 if (TraceBytecodes) {
401 emitPushAddressOf(SystemInterface.toCString(i_start+": NOP"));
402 emitCallMemory(SystemInterface._debugwriteln);
403 }
404 asm.emit1(x86.NOP);
405 }
406 public void visitACONST(Object s) {
407 super.visitACONST(s);
408 if (TraceBytecodes) {
409 emitPushAddressOf(SystemInterface.toCString(i_start+": ACONST"));
410 emitCallMemory(SystemInterface._debugwriteln);
411 }
412 emitPushAddressOf(s);
413 }
414 public void visitICONST(int c) {
415 super.visitICONST(c);
416 if (TraceBytecodes) {
417 emitPushAddressOf(SystemInterface.toCString(i_start+": ICONST "+c));
418 emitCallMemory(SystemInterface._debugwriteln);
419 }
420 asm.emitPUSH_i(c);
421 }
422 public void visitLCONST(long c) {
423 super.visitLCONST(c);
424 if (TraceBytecodes) {
425 emitPushAddressOf(SystemInterface.toCString(i_start+": LCONST "+c));
426 emitCallMemory(SystemInterface._debugwriteln);
427 }
428 asm.emitPUSH_i((int)(c>>32));
429 asm.emitPUSH_i((int)c);
430 }
431 public void visitFCONST(float c) {
432 super.visitFCONST(c);
433 if (TraceBytecodes) {
434 emitPushAddressOf(SystemInterface.toCString(i_start+": FCONST "+c));
435 emitCallMemory(SystemInterface._debugwriteln);
436 }
437 asm.emitPUSH_i(Float.floatToRawIntBits(c));
438 }
439 public void visitDCONST(double c) {
440 super.visitDCONST(c);
441 if (TraceBytecodes) {
442 emitPushAddressOf(SystemInterface.toCString(i_start+": DCONST "+c));
443 emitCallMemory(SystemInterface._debugwriteln);
444 }
445 long v = Double.doubleToRawLongBits(c);
446 asm.emitPUSH_i((int)(v>>32));
447 asm.emitPUSH_i((int)v);
448 }
449 public void visitILOAD(int i) {
450 super.visitILOAD(i);
451 if (TraceBytecodes) {
452 emitPushAddressOf(SystemInterface.toCString(i_start+": ILOAD "+i));
453 emitCallMemory(SystemInterface._debugwriteln);
454 }
455 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i), EBP);
456 }
457 public void visitLLOAD(int i) {
458 super.visitLLOAD(i);
459 if (TraceBytecodes) {
460 emitPushAddressOf(SystemInterface.toCString(i_start+": LLOAD "+i));
461 emitCallMemory(SystemInterface._debugwriteln);
462 }
463 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i), EBP);
464 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i+1), EBP);
465 }
466 public void visitFLOAD(int i) {
467 super.visitFLOAD(i);
468 if (TraceBytecodes) {
469 emitPushAddressOf(SystemInterface.toCString(i_start+": FLOAD "+i));
470 emitCallMemory(SystemInterface._debugwriteln);
471 }
472 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i), EBP);
473 }
474 public void visitDLOAD(int i) {
475 super.visitDLOAD(i);
476 if (TraceBytecodes) {
477 emitPushAddressOf(SystemInterface.toCString(i_start+": DLOAD "+i));
478 emitCallMemory(SystemInterface._debugwriteln);
479 }
480 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i), EBP);
481 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i+1), EBP);
482 }
483 public void visitALOAD(int i) {
484 super.visitALOAD(i);
485 if (TraceBytecodes) {
486 emitPushAddressOf(SystemInterface.toCString(i_start+": ALOAD "+i));
487 emitCallMemory(SystemInterface._debugwriteln);
488 }
489 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i), EBP);
490 }
491 public void visitISTORE(int i) {
492 super.visitISTORE(i);
493 if (TraceBytecodes) {
494 emitPushAddressOf(SystemInterface.toCString(i_start+": ISTORE "+i));
495 emitCallMemory(SystemInterface._debugwriteln);
496 }
497 asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);
498 }
499 public void visitLSTORE(int i) {
500 super.visitLSTORE(i);
501 if (TraceBytecodes) {
502 emitPushAddressOf(SystemInterface.toCString(i_start+": LSTORE "+i));
503 emitCallMemory(SystemInterface._debugwriteln);
504 }
505 asm.emit2_Mem(x86.POP_m, getLocalOffset(i+1), EBP);
506 asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);
507 }
508 public void visitFSTORE(int i) {
509 super.visitFSTORE(i);
510 if (TraceBytecodes) {
511 emitPushAddressOf(SystemInterface.toCString(i_start+": FSTORE "+i));
512 emitCallMemory(SystemInterface._debugwriteln);
513 }
514 asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);
515 }
516 public void visitDSTORE(int i) {
517 super.visitDSTORE(i);
518 if (TraceBytecodes) {
519 emitPushAddressOf(SystemInterface.toCString(i_start+": DSTORE "+i));
520 emitCallMemory(SystemInterface._debugwriteln);
521 }
522 asm.emit2_Mem(x86.POP_m, getLocalOffset(i+1), EBP);
523 asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);
524 }
525 public void visitASTORE(int i) {
526 super.visitASTORE(i);
527 if (TraceBytecodes) {
528 emitPushAddressOf(SystemInterface.toCString(i_start+": ASTORE "+i));
529 emitCallMemory(SystemInterface._debugwriteln);
530 }
531 asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);
532 }
533 private void ALOAD4helper() {
534 asm.emitShort_Reg(x86.POP_r, EBX);
535 asm.emitShort_Reg(x86.POP_r, EAX);
536 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
537 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
538 asm.emit2_Mem(x86.PUSH_m, EAX, EBX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
539 }
540 private void ALOAD8helper() {
541 asm.emitShort_Reg(x86.POP_r, EBX);
542 asm.emitShort_Reg(x86.POP_r, EAX);
543 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
544 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
545 asm.emit2_Mem(x86.PUSH_m, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4);
546 asm.emit2_Mem(x86.PUSH_m, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET );
547 }
548 public void visitIALOAD() {
549 super.visitIALOAD();
550 if (TraceBytecodes) {
551 emitPushAddressOf(SystemInterface.toCString(i_start+": IALOAD"));
552 emitCallMemory(SystemInterface._debugwriteln);
553 }
554 ALOAD4helper();
555 }
556 public void visitLALOAD() {
557 super.visitLALOAD();
558 if (TraceBytecodes) {
559 emitPushAddressOf(SystemInterface.toCString(i_start+": LALOAD"));
560 emitCallMemory(SystemInterface._debugwriteln);
561 }
562 ALOAD8helper();
563 }
564 public void visitFALOAD() {
565 super.visitFALOAD();
566 if (TraceBytecodes) {
567 emitPushAddressOf(SystemInterface.toCString(i_start+": FALOAD"));
568 emitCallMemory(SystemInterface._debugwriteln);
569 }
570 ALOAD4helper();
571 }
572 public void visitDALOAD() {
573 super.visitDALOAD();
574 if (TraceBytecodes) {
575 emitPushAddressOf(SystemInterface.toCString(i_start+": DALOAD"));
576 emitCallMemory(SystemInterface._debugwriteln);
577 }
578 ALOAD8helper();
579 }
580 public void visitAALOAD() {
581 super.visitAALOAD();
582 if (TraceBytecodes) {
583 emitPushAddressOf(SystemInterface.toCString(i_start+": AALOAD"));
584 emitCallMemory(SystemInterface._debugwriteln);
585 }
586 ALOAD4helper();
587 }
588 public void visitBALOAD() {
589 super.visitBALOAD();
590 if (TraceBytecodes) {
591 emitPushAddressOf(SystemInterface.toCString(i_start+": BALOAD"));
592 emitCallMemory(SystemInterface._debugwriteln);
593 }
594 asm.emitShort_Reg(x86.POP_r, EBX);
595 asm.emitShort_Reg(x86.POP_r, EAX);
596 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
597 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
598 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, EAX, EBX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
599 asm.emitShort_Reg(x86.PUSH_r, ECX);
600 }
601 public void visitCALOAD() {
602 super.visitCALOAD();
603 if (TraceBytecodes) {
604 emitPushAddressOf(SystemInterface.toCString(i_start+": CALOAD"));
605 emitCallMemory(SystemInterface._debugwriteln);
606 }
607 asm.emitShort_Reg(x86.POP_r, EBX);
608 asm.emitShort_Reg(x86.POP_r, EAX);
609 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
610 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
611 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
612 asm.emitShort_Reg(x86.PUSH_r, ECX);
613 }
614 public void visitSALOAD() {
615 super.visitSALOAD();
616 if (TraceBytecodes) {
617 emitPushAddressOf(SystemInterface.toCString(i_start+": SALOAD"));
618 emitCallMemory(SystemInterface._debugwriteln);
619 }
620 asm.emitShort_Reg(x86.POP_r, EBX);
621 asm.emitShort_Reg(x86.POP_r, EAX);
622 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
623 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
624 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
625 asm.emitShort_Reg(x86.PUSH_r, ECX);
626 }
627 private void ASTORE2helper() {
628 asm.emitShort_Reg(x86.POP_r, ECX);
629 asm.emitShort_Reg(x86.POP_r, EBX);
630 asm.emitShort_Reg(x86.POP_r, EAX);
631 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
632 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
633 asm.emitprefix(x86.PREFIX_16BIT);
634 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
635 }
636 private void ASTORE4helper() {
637 asm.emitShort_Reg(x86.POP_r, ECX);
638 asm.emitShort_Reg(x86.POP_r, EBX);
639 asm.emitShort_Reg(x86.POP_r, EAX);
640 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
641 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
642 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EBX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
643 }
644 private void ASTORE8helper() {
645 asm.emitShort_Reg(x86.POP_r, ECX);
646 asm.emitShort_Reg(x86.POP_r, EDX);
647 asm.emitShort_Reg(x86.POP_r, EBX);
648 asm.emitShort_Reg(x86.POP_r, EAX);
649 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
650 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
651 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET );
652 asm.emit2_Reg_Mem(x86.MOV_m_r32, EDX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4);
653 }
654 public void visitIASTORE() {
655 super.visitIASTORE();
656 if (TraceBytecodes) {
657 emitPushAddressOf(SystemInterface.toCString(i_start+": IASTORE"));
658 emitCallMemory(SystemInterface._debugwriteln);
659 }
660 ASTORE4helper();
661 }
662 public void visitLASTORE() {
663 super.visitLASTORE();
664 if (TraceBytecodes) {
665 emitPushAddressOf(SystemInterface.toCString(i_start+": LASTORE"));
666 emitCallMemory(SystemInterface._debugwriteln);
667 }
668 ASTORE8helper();
669 }
670 public void visitFASTORE() {
671 super.visitFASTORE();
672 if (TraceBytecodes) {
673 emitPushAddressOf(SystemInterface.toCString(i_start+": FASTORE"));
674 emitCallMemory(SystemInterface._debugwriteln);
675 }
676 ASTORE4helper();
677 }
678 public void visitDASTORE() {
679 super.visitDASTORE();
680 if (TraceBytecodes) {
681 emitPushAddressOf(SystemInterface.toCString(i_start+": DASTORE"));
682 emitCallMemory(SystemInterface._debugwriteln);
683 }
684 ASTORE8helper();
685 }
686 public void visitAASTORE() {
687 super.visitAASTORE();
688 if (TraceBytecodes) {
689 emitPushAddressOf(SystemInterface.toCString(i_start+": AASTORE"));
690 emitCallMemory(SystemInterface._debugwriteln);
691 }
692
693 asm.emit2_Mem(x86.PUSH_m, 0, ESP);
694 asm.emit2_Mem(x86.PUSH_m, 12, ESP);
695 emitCallRelative(TypeCheck._arrayStoreCheck);
696 ASTORE4helper();
697 }
698 public void visitBASTORE() {
699 super.visitBASTORE();
700 if (TraceBytecodes) {
701 emitPushAddressOf(SystemInterface.toCString(i_start+": BASTORE"));
702 emitCallMemory(SystemInterface._debugwriteln);
703 }
704 asm.emitShort_Reg(x86.POP_r, ECX);
705 asm.emitShort_Reg(x86.POP_r, EBX);
706 asm.emitShort_Reg(x86.POP_r, EAX);
707 asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
708 asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
709 asm.emit2_Reg_Mem(x86.MOV_m_r8, ECX, EAX, EBX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
710 }
711 public void visitCASTORE() {
712 super.visitCASTORE();
713 if (TraceBytecodes) {
714 emitPushAddressOf(SystemInterface.toCString(i_start+": CASTORE"));
715 emitCallMemory(SystemInterface._debugwriteln);
716 }
717 ASTORE2helper();
718 }
719 public void visitSASTORE() {
720 super.visitSASTORE();
721 if (TraceBytecodes) {
722 emitPushAddressOf(SystemInterface.toCString(i_start+": SASTORE"));
723 emitCallMemory(SystemInterface._debugwriteln);
724 }
725 ASTORE2helper();
726 }
727 public void visitPOP() {
728 super.visitPOP();
729 if (TraceBytecodes) {
730 emitPushAddressOf(SystemInterface.toCString(i_start+": POP"));
731 emitCallMemory(SystemInterface._debugwriteln);
732 }
733 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
734 }
735 public void visitPOP2() {
736 super.visitPOP2();
737 if (TraceBytecodes) {
738 emitPushAddressOf(SystemInterface.toCString(i_start+": POP2"));
739 emitCallMemory(SystemInterface._debugwriteln);
740 }
741 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
742 }
743 public void visitDUP() {
744 super.visitDUP();
745 if (TraceBytecodes) {
746 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP"));
747 emitCallMemory(SystemInterface._debugwriteln);
748 }
749 asm.emit2_Mem(x86.PUSH_m, 0, ESP);
750 }
751 public void visitDUP_x1() {
752 super.visitDUP_x1();
753 if (TraceBytecodes) {
754 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP_x1"));
755 emitCallMemory(SystemInterface._debugwriteln);
756 }
757 asm.emitShort_Reg(x86.POP_r, EAX);
758 asm.emitShort_Reg(x86.POP_r, EBX);
759 asm.emitShort_Reg(x86.PUSH_r, EAX);
760 asm.emitShort_Reg(x86.PUSH_r, EBX);
761 asm.emitShort_Reg(x86.PUSH_r, EAX);
762 }
763 public void visitDUP_x2() {
764 super.visitDUP_x2();
765 if (TraceBytecodes) {
766 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP_x2"));
767 emitCallMemory(SystemInterface._debugwriteln);
768 }
769 asm.emitShort_Reg(x86.POP_r, EAX);
770 asm.emitShort_Reg(x86.POP_r, EBX);
771 asm.emitShort_Reg(x86.POP_r, ECX);
772 asm.emitShort_Reg(x86.PUSH_r, EAX);
773 asm.emitShort_Reg(x86.PUSH_r, ECX);
774 asm.emitShort_Reg(x86.PUSH_r, EBX);
775 asm.emitShort_Reg(x86.PUSH_r, EAX);
776 }
777 public void visitDUP2() {
778 super.visitDUP2();
779 if (TraceBytecodes) {
780 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP2"));
781 emitCallMemory(SystemInterface._debugwriteln);
782 }
783 asm.emitShort_Reg(x86.POP_r, EAX);
784 asm.emitShort_Reg(x86.POP_r, EBX);
785 asm.emitShort_Reg(x86.PUSH_r, EBX);
786 asm.emitShort_Reg(x86.PUSH_r, EAX);
787 asm.emitShort_Reg(x86.PUSH_r, EBX);
788 asm.emitShort_Reg(x86.PUSH_r, EAX);
789 }
790 public void visitDUP2_x1() {
791 super.visitDUP2_x1();
792 if (TraceBytecodes) {
793 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP2_x1"));
794 emitCallMemory(SystemInterface._debugwriteln);
795 }
796 asm.emitShort_Reg(x86.POP_r, EAX);
797 asm.emitShort_Reg(x86.POP_r, EBX);
798 asm.emitShort_Reg(x86.POP_r, ECX);
799 asm.emitShort_Reg(x86.PUSH_r, EBX);
800 asm.emitShort_Reg(x86.PUSH_r, EAX);
801 asm.emitShort_Reg(x86.PUSH_r, ECX);
802 asm.emitShort_Reg(x86.PUSH_r, EBX);
803 asm.emitShort_Reg(x86.PUSH_r, EAX);
804 }
805 public void visitDUP2_x2() {
806 super.visitDUP2_x2();
807 if (TraceBytecodes) {
808 emitPushAddressOf(SystemInterface.toCString(i_start+": DUP2_x2"));
809 emitCallMemory(SystemInterface._debugwriteln);
810 }
811 asm.emitShort_Reg(x86.POP_r, EAX);
812 asm.emitShort_Reg(x86.POP_r, EBX);
813 asm.emitShort_Reg(x86.POP_r, ECX);
814 asm.emitShort_Reg(x86.POP_r, EDX);
815 asm.emitShort_Reg(x86.PUSH_r, EBX);
816 asm.emitShort_Reg(x86.PUSH_r, EAX);
817 asm.emitShort_Reg(x86.PUSH_r, EDX);
818 asm.emitShort_Reg(x86.PUSH_r, ECX);
819 asm.emitShort_Reg(x86.PUSH_r, EBX);
820 asm.emitShort_Reg(x86.PUSH_r, EAX);
821 }
822 public void visitSWAP() {
823 super.visitSWAP();
824 if (TraceBytecodes) {
825 emitPushAddressOf(SystemInterface.toCString(i_start+": SWAP"));
826 emitCallMemory(SystemInterface._debugwriteln);
827 }
828 asm.emitShort_Reg(x86.POP_r, EAX);
829 asm.emitShort_Reg(x86.POP_r, EBX);
830 asm.emitShort_Reg(x86.PUSH_r, EAX);
831 asm.emitShort_Reg(x86.PUSH_r, EBX);
832 }
833 public void visitIBINOP(byte op) {
834 super.visitIBINOP(op);
835 if (TraceBytecodes) {
836 emitPushAddressOf(SystemInterface.toCString(i_start+": IBINOP "+op));
837 emitCallMemory(SystemInterface._debugwriteln);
838 }
839 switch(op) {
840 case BINOP_ADD:
841 asm.emitShort_Reg(x86.POP_r, EAX);
842 asm.emitARITH_Reg_Mem(x86.ADD_m_r32, EAX, 0, ESP);
843 break;
844 case BINOP_SUB:
845 asm.emitShort_Reg(x86.POP_r, EAX);
846 asm.emitARITH_Reg_Mem(x86.SUB_m_r32, EAX, 0, ESP);
847 break;
848 case BINOP_MUL:
849 asm.emitShort_Reg(x86.POP_r, EAX);
850 asm.emit2_Mem(x86.IMUL_rda_m32, 0, ESP);
851 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, 0, ESP);
852 break;
853 case BINOP_DIV:
854 asm.emitShort_Reg(x86.POP_r, ECX);
855 asm.emitShort_Reg(x86.POP_r, EAX);
856 asm.emit1(x86.CWD);
857 asm.emit2_Reg(x86.IDIV_r32, ECX);
858 asm.emitShort_Reg(x86.PUSH_r, EAX);
859 break;
860 case BINOP_REM:
861 asm.emitShort_Reg(x86.POP_r, ECX);
862 asm.emitShort_Reg(x86.POP_r, EAX);
863 asm.emit1(x86.CWD);
864 asm.emit2_Reg(x86.IDIV_r32, ECX);
865 asm.emitShort_Reg(x86.PUSH_r, EDX);
866 break;
867 case BINOP_AND:
868 asm.emitShort_Reg(x86.POP_r, EAX);
869 asm.emit2_Reg_Mem(x86.AND_m_r32, EAX, 0, ESP);
870 break;
871 case BINOP_OR:
872 asm.emitShort_Reg(x86.POP_r, EAX);
873 asm.emit2_Reg_Mem(x86.OR_m_r32, EAX, 0, ESP);
874 break;
875 case BINOP_XOR:
876 asm.emitShort_Reg(x86.POP_r, EAX);
877 asm.emit2_Reg_Mem(x86.XOR_m_r32, EAX, 0, ESP);
878 break;
879 default:
880 Assert.UNREACHABLE();
881 }
882 }
883 public void visitLBINOP(byte op) {
884 super.visitLBINOP(op);
885 if (TraceBytecodes) {
886 emitPushAddressOf(SystemInterface.toCString(i_start+": LBINOP "+op));
887 emitCallMemory(SystemInterface._debugwriteln);
888 }
889 switch(op) {
890 case BINOP_ADD:
891 asm.emitShort_Reg(x86.POP_r, EAX);
892 asm.emitShort_Reg(x86.POP_r, EBX);
893 asm.emit2_Reg_Mem(x86.ADD_m_r32, EAX, 0, ESP);
894 asm.emit2_Reg_Mem(x86.ADC_m_r32, EBX, 4, ESP);
895 break;
896 case BINOP_SUB:
897 asm.emitShort_Reg(x86.POP_r, EAX);
898 asm.emitShort_Reg(x86.POP_r, EBX);
899 asm.emit2_Reg_Mem(x86.SUB_m_r32, EAX, 0, ESP);
900 asm.emit2_Reg_Mem(x86.SBB_m_r32, EBX, 4, ESP);
901 break;
902 case BINOP_MUL:
903 asm.emitShort_Reg(x86.POP_r, EBX);
904 asm.emitShort_Reg(x86.POP_r, ECX);
905 asm.emitShort_Reg(x86.POP_r, ESI);
906 asm.emitShort_Reg(x86.POP_r, EDI);
907 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI);
908 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, ECX);
909 asm.emitCJUMP_Short(x86.JNE, (byte)0);
910 int cloc = asm.getCurrentOffset();
911 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI);
912 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
913 asm.emitJUMP_Short(x86.JMP, (byte)0);
914 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
915 cloc = asm.getCurrentOffset();
916 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI);
917 asm.emit2_Reg(x86.MUL_rda_r32, ECX);
918 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EAX);
919 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI);
920 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
921 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, ECX, EAX);
922 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI);
923 asm.emit2_Reg(x86.MUL_rda_r32, EBX);
924 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EDX, ECX);
925 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
926 asm.emitShort_Reg(x86.PUSH_r, EDX);
927 asm.emitShort_Reg(x86.PUSH_r, EAX);
928 break;
929 case BINOP_DIV:
930 emitCallRelative(MathSupport._ldiv);
931 asm.emitShort_Reg(x86.PUSH_r, EDX);
932 asm.emitShort_Reg(x86.PUSH_r, EAX);
933 break;
934 case BINOP_REM:
935 emitCallRelative(MathSupport._lrem);
936 asm.emitShort_Reg(x86.PUSH_r, EDX);
937 asm.emitShort_Reg(x86.PUSH_r, EAX);
938 break;
939 case BINOP_AND:
940 asm.emitShort_Reg(x86.POP_r, EAX);
941 asm.emitShort_Reg(x86.POP_r, EDX);
942 asm.emit2_Reg_Mem(x86.AND_m_r32, EAX, 0, ESP);
943 asm.emit2_Reg_Mem(x86.AND_m_r32, EDX, 4, ESP);
944 break;
945 case BINOP_OR:
946 asm.emitShort_Reg(x86.POP_r, EAX);
947 asm.emitShort_Reg(x86.POP_r, EDX);
948 asm.emit2_Reg_Mem(x86.OR_m_r32, EAX, 0, ESP);
949 asm.emit2_Reg_Mem(x86.OR_m_r32, EDX, 4, ESP);
950 break;
951 case BINOP_XOR:
952 asm.emitShort_Reg(x86.POP_r, EAX);
953 asm.emitShort_Reg(x86.POP_r, EDX);
954 asm.emit2_Reg_Mem(x86.XOR_m_r32, EAX, 0, ESP);
955 asm.emit2_Reg_Mem(x86.XOR_m_r32, EDX, 4, ESP);
956 break;
957 default:
958 Assert.UNREACHABLE();
959 }
960 }
961 public void visitFBINOP(byte op) {
962 super.visitFBINOP(op);
963 if (TraceBytecodes) {
964 emitPushAddressOf(SystemInterface.toCString(i_start+": FBINOP "+op));
965 emitCallMemory(SystemInterface._debugwriteln);
966 }
967 switch(op) {
968 case BINOP_ADD:
969 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
970 asm.emit2_Mem(x86.FADD_m32, 0, ESP);
971 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
972 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
973 break;
974 case BINOP_SUB:
975 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
976 asm.emit2_Mem(x86.FSUB_m32, 0, ESP);
977 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
978 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
979 break;
980 case BINOP_MUL:
981 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
982 asm.emit2_Mem(x86.FMUL_m32, 0, ESP);
983 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
984 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
985 break;
986 case BINOP_DIV:
987 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
988 asm.emit2_Mem(x86.FDIV_m32, 0, ESP);
989 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
990 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
991 break;
992 case BINOP_REM:
993 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
994 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
995 asm.emit2(x86.FPREM);
996 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
997 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
998 asm.emit2_FPReg(x86.FFREE, 0);
999 break;
1000 default:
1001 Assert.UNREACHABLE();
1002 }
1003 }
1004 public void visitDBINOP(byte op) {
1005 super.visitDBINOP(op);
1006 if (TraceBytecodes) {
1007 emitPushAddressOf(SystemInterface.toCString(i_start+": DBINOP "+op));
1008 emitCallMemory(SystemInterface._debugwriteln);
1009 }
1010 switch(op) {
1011 case BINOP_ADD:
1012 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1013 asm.emit2_Mem(x86.FADD_m64, 0, ESP);
1014 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1015 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1016 break;
1017 case BINOP_SUB:
1018 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1019 asm.emit2_Mem(x86.FSUB_m64, 0, ESP);
1020 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1021 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1022 break;
1023 case BINOP_MUL:
1024 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1025 asm.emit2_Mem(x86.FMUL_m64, 0, ESP);
1026 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1027 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1028 break;
1029 case BINOP_DIV:
1030 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1031 asm.emit2_Mem(x86.FDIV_m64, 0, ESP);
1032 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1033 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1034 break;
1035 case BINOP_REM:
1036 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1037 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1038 asm.emit2(x86.FPREM);
1039 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1040 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1041 asm.emit2_FPReg(x86.FFREE, 0);
1042 break;
1043 default:
1044 Assert.UNREACHABLE();
1045 }
1046 }
1047 public void visitIUNOP(byte op) {
1048 super.visitIUNOP(op);
1049 if (TraceBytecodes) {
1050 emitPushAddressOf(SystemInterface.toCString(i_start+": IUNOP "+op));
1051 emitCallMemory(SystemInterface._debugwriteln);
1052 }
1053 Assert._assert(op == UNOP_NEG);
1054 asm.emit2_Mem(x86.NEG_m32, 0, ESP);
1055 }
1056 public void visitLUNOP(byte op) {
1057 super.visitLUNOP(op);
1058 if (TraceBytecodes) {
1059 emitPushAddressOf(SystemInterface.toCString(i_start+": LUNOP "+op));
1060 emitCallMemory(SystemInterface._debugwriteln);
1061 }
1062 Assert._assert(op == UNOP_NEG);
1063 asm.emit2_Mem(x86.NEG_m32, 4, ESP);
1064 asm.emit2_Mem(x86.NEG_m32, 0, ESP);
1065 asm.emitARITH_Mem_Imm(x86.SBB_m_i32, 4, ESP, 0);
1066 }
1067 public void visitFUNOP(byte op) {
1068 super.visitFUNOP(op);
1069 if (TraceBytecodes) {
1070 emitPushAddressOf(SystemInterface.toCString(i_start+": FUNOP "+op));
1071 emitCallMemory(SystemInterface._debugwriteln);
1072 }
1073 Assert._assert(op == UNOP_NEG);
1074 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1075 asm.emit2(x86.FCHS);
1076 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1077 }
1078 public void visitDUNOP(byte op) {
1079 super.visitDUNOP(op);
1080 if (TraceBytecodes) {
1081 emitPushAddressOf(SystemInterface.toCString(i_start+": DUNOP "+op));
1082 emitCallMemory(SystemInterface._debugwriteln);
1083 }
1084 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1085 asm.emit2(x86.FCHS);
1086 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1087 }
1088 public void visitISHIFT(byte op) {
1089 super.visitISHIFT(op);
1090 if (TraceBytecodes) {
1091 emitPushAddressOf(SystemInterface.toCString(i_start+": ISHIFT "+op));
1092 emitCallMemory(SystemInterface._debugwriteln);
1093 }
1094 switch(op) {
1095 case SHIFT_LEFT:
1096 asm.emitShort_Reg(x86.POP_r, ECX);
1097 asm.emit2_Mem(x86.SHL_m32_rc, 0, ESP);
1098 break;
1099 case SHIFT_RIGHT:
1100 asm.emitShort_Reg(x86.POP_r, ECX);
1101 asm.emit2_Mem(x86.SAR_m32_rc, 0, ESP);
1102 break;
1103 case SHIFT_URIGHT:
1104 asm.emitShort_Reg(x86.POP_r, ECX);
1105 asm.emit2_Mem(x86.SHR_m32_rc, 0, ESP);
1106 break;
1107 default:
1108 Assert.UNREACHABLE();
1109 }
1110 }
1111 public void visitLSHIFT(byte op) {
1112 super.visitLSHIFT(op);
1113 if (TraceBytecodes) {
1114 emitPushAddressOf(SystemInterface.toCString(i_start+": LSHIFT"+op));
1115 emitCallMemory(SystemInterface._debugwriteln);
1116 }
1117 switch(op) {
1118 case SHIFT_LEFT: {
1119 asm.emitShort_Reg(x86.POP_r, ECX);
1120 asm.emitShort_Reg(x86.POP_r, EAX);
1121 asm.emitShort_Reg(x86.POP_r, EDX);
1122 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
1123 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
1124 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1125 int cloc = asm.getCurrentOffset();
1126 asm.emitSHLD_r_r_rc(EDX, EAX);
1127 asm.emit2_Reg(x86.SHL_r32_rc, EAX);
1128 asm.emitJUMP_Short(x86.JMP, (byte)0);
1129 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1130 cloc = asm.getCurrentOffset();
1131 asm.emit2_Reg_Reg(x86.MOV_r_r32, EDX, EAX);
1132 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EAX);
1133 asm.emit2_Reg(x86.SHL_r32_rc, EDX);
1134 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1135 asm.emitShort_Reg(x86.PUSH_r, EDX);
1136 asm.emitShort_Reg(x86.PUSH_r, EAX);
1137 break;
1138 }
1139 case SHIFT_RIGHT: {
1140 asm.emitShort_Reg(x86.POP_r, ECX);
1141 asm.emitShort_Reg(x86.POP_r, EAX);
1142 asm.emitShort_Reg(x86.POP_r, EDX);
1143 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
1144 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
1145 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1146 int cloc = asm.getCurrentOffset();
1147 asm.emitSHRD_r_r_rc(EAX, EDX);
1148 asm.emit2_Reg(x86.SAR_r32_rc, EDX);
1149 asm.emitJUMP_Short(x86.JMP, (byte)0);
1150 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1151 cloc = asm.getCurrentOffset();
1152 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
1153 asm.emit2_SHIFT_Reg_Imm8(x86.SAR_r32_i, EDX, (byte)31);
1154 asm.emit2_Reg(x86.SAR_r32_rc, EAX);
1155 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1156 asm.emitShort_Reg(x86.PUSH_r, EDX);
1157 asm.emitShort_Reg(x86.PUSH_r, EAX);
1158 break;
1159 }
1160 case SHIFT_URIGHT: {
1161 asm.emitShort_Reg(x86.POP_r, ECX);
1162 asm.emitShort_Reg(x86.POP_r, EAX);
1163 asm.emitShort_Reg(x86.POP_r, EDX);
1164 asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
1165 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
1166 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1167 int cloc = asm.getCurrentOffset();
1168 asm.emitSHRD_r_r_rc(EAX, EDX);
1169 asm.emit2_Reg(x86.SHR_r32_rc, EDX);
1170 asm.emitJUMP_Short(x86.JMP, (byte)0);
1171 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1172 cloc = asm.getCurrentOffset();
1173 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
1174 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, EDX);
1175 asm.emit2_Reg(x86.SHR_r32_rc, EAX);
1176 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1177 asm.emitShort_Reg(x86.PUSH_r, EDX);
1178 asm.emitShort_Reg(x86.PUSH_r, EAX);
1179 break;
1180 }
1181 default:
1182 Assert.UNREACHABLE();
1183 }
1184 }
1185 public void visitIINC(int i, int v) {
1186 super.visitIINC(i, v);
1187 if (TraceBytecodes) {
1188 emitPushAddressOf(SystemInterface.toCString(i_start+": IINC "+i+" "+v));
1189 emitCallMemory(SystemInterface._debugwriteln);
1190 }
1191 asm.emitARITH_Mem_Imm(x86.ADD_m_i32, getLocalOffset(i), EBP, v);
1192 }
1193 public void visitI2L() {
1194 super.visitI2L();
1195 if (TraceBytecodes) {
1196 emitPushAddressOf(SystemInterface.toCString(i_start+": I2L"));
1197 emitCallMemory(SystemInterface._debugwriteln);
1198 }
1199 asm.emitShort_Reg(x86.POP_r, EAX);
1200 asm.emit1(x86.CWD);
1201 asm.emitShort_Reg(x86.PUSH_r, EDX);
1202 asm.emitShort_Reg(x86.PUSH_r, EAX);
1203 }
1204 public void visitI2F() {
1205 super.visitI2F();
1206 if (TraceBytecodes) {
1207 emitPushAddressOf(SystemInterface.toCString(i_start+": I2F"));
1208 emitCallMemory(SystemInterface._debugwriteln);
1209 }
1210 asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1211 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1212 }
1213 public void visitI2D() {
1214 super.visitI2D();
1215 if (TraceBytecodes) {
1216 emitPushAddressOf(SystemInterface.toCString(i_start+": I2D"));
1217 emitCallMemory(SystemInterface._debugwriteln);
1218 }
1219 asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1220 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1221 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1222 }
1223 public void visitL2I() {
1224 super.visitL2I();
1225 if (TraceBytecodes) {
1226 emitPushAddressOf(SystemInterface.toCString(i_start+": L2I"));
1227 emitCallMemory(SystemInterface._debugwriteln);
1228 }
1229 asm.emitShort_Reg(x86.POP_r, EAX);
1230 asm.emitShort_Reg(x86.POP_r, ECX);
1231 asm.emitShort_Reg(x86.PUSH_r, EAX);
1232 }
1233 public void visitL2F() {
1234 super.visitL2F();
1235 if (TraceBytecodes) {
1236 emitPushAddressOf(SystemInterface.toCString(i_start+": L2F"));
1237 emitCallMemory(SystemInterface._debugwriteln);
1238 }
1239 asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1240 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1241 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1242 }
1243 public void visitL2D() {
1244 super.visitL2D();
1245 if (TraceBytecodes) {
1246 emitPushAddressOf(SystemInterface.toCString(i_start+": L2D"));
1247 emitCallMemory(SystemInterface._debugwriteln);
1248 }
1249 asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1250 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1251 }
1252 private void toIntHelper() {
1253
1254 emitFLD64(MathSupport._maxint);
1255 asm.emit2_FPReg(x86.FUCOMIP, 1);
1256 asm.emitCJUMP_Short(x86.JP, (byte)0);
1257 int cloc1 = asm.getCurrentOffset();
1258
1259 asm.emitCJUMP_Short(x86.JBE, (byte)0);
1260 int cloc2 = asm.getCurrentOffset();
1261
1262 emitFLD64(MathSupport._minint);
1263 asm.emit2_FPReg(x86.FUCOMIP, 1);
1264 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1265 int cloc3 = asm.getCurrentOffset();
1266
1267 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1268 {
1269 asm.emit2_Mem(x86.FNSTCW, 4, ESP);
1270 asm.emit2_Mem(x86.FNSTCW, 0, ESP);
1271 asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
1272 asm.emit2(x86.FNCLEX);
1273 asm.emit2_Mem(x86.FLDCW, 4, ESP);
1274 }
1275 asm.emit2_Mem(x86.FISTP_m32, 8, ESP);
1276 {
1277
1278 asm.emit2(x86.FNCLEX);
1279 asm.emit2_Mem(x86.FLDCW, 0, ESP);
1280 }
1281 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1282 asm.emitJUMP_Short(x86.JMP, (byte)0);
1283 int cloc4 = asm.getCurrentOffset();
1284 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1285
1286 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
1287 asm.emitJUMP_Short(x86.JMP, (byte)0);
1288 int cloc5 = asm.getCurrentOffset();
1289 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1290
1291 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MAX_VALUE);
1292 asm.emitJUMP_Short(x86.JMP, (byte)0);
1293 int cloc6 = asm.getCurrentOffset();
1294 asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
1295
1296 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MIN_VALUE);
1297 asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
1298 asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
1299 asm.emit2_FPReg(x86.FFREE, 0);
1300 asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
1301 }
1302 private void toLongHelper() {
1303
1304 emitFLD64(MathSupport._maxlong);
1305 asm.emit2_FPReg(x86.FUCOMIP, 1);
1306 asm.emitCJUMP_Short(x86.JP, (byte)0);
1307 int cloc1 = asm.getCurrentOffset();
1308
1309 asm.emitCJUMP_Short(x86.JBE, (byte)0);
1310 int cloc2 = asm.getCurrentOffset();
1311
1312 emitFLD64(MathSupport._minlong);
1313 asm.emit2_FPReg(x86.FUCOMIP, 1);
1314 asm.emitCJUMP_Short(x86.JAE, (byte)0);
1315 int cloc3 = asm.getCurrentOffset();
1316
1317 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1318 {
1319 asm.emit2_Mem(x86.FNSTCW, 4, ESP);
1320 asm.emit2_Mem(x86.FNSTCW, 0, ESP);
1321 asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
1322 asm.emit2(x86.FNCLEX);
1323 asm.emit2_Mem(x86.FLDCW, 4, ESP);
1324 }
1325 asm.emit2_Mem(x86.FISTP_m64, 8, ESP);
1326 {
1327
1328 asm.emit2(x86.FNCLEX);
1329 asm.emit2_Mem(x86.FLDCW, 0, ESP);
1330 }
1331 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1332 asm.emitJUMP_Short(x86.JMP, (byte)0);
1333 int cloc4 = asm.getCurrentOffset();
1334 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1335
1336 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
1337 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, 0);
1338 asm.emitJUMP_Short(x86.JMP, (byte)0);
1339 int cloc5 = asm.getCurrentOffset();
1340 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1341
1342 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MAX_VALUE);
1343 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MAX_VALUE>>32));
1344 asm.emitJUMP_Short(x86.JMP, (byte)0);
1345 int cloc6 = asm.getCurrentOffset();
1346 asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
1347
1348 asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MIN_VALUE);
1349 asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MIN_VALUE>>32));
1350 asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
1351 asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
1352 asm.emit2_FPReg(x86.FFREE, 0);
1353 asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
1354 }
1355 public void visitF2I() {
1356 super.visitF2I();
1357 if (TraceBytecodes) {
1358 emitPushAddressOf(SystemInterface.toCString(i_start+": F2I"));
1359 emitCallMemory(SystemInterface._debugwriteln);
1360 }
1361 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1362 toIntHelper();
1363 }
1364 public void visitF2L() {
1365 super.visitF2L();
1366 if (TraceBytecodes) {
1367 emitPushAddressOf(SystemInterface.toCString(i_start+": F2L"));
1368 emitCallMemory(SystemInterface._debugwriteln);
1369 }
1370 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1371 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1372 toLongHelper();
1373 }
1374 public void visitF2D() {
1375 super.visitF2D();
1376 if (TraceBytecodes) {
1377 emitPushAddressOf(SystemInterface.toCString(i_start+": F2D"));
1378 emitCallMemory(SystemInterface._debugwriteln);
1379 }
1380 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1381 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1382 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1383 }
1384 public void visitD2I() {
1385 super.visitD2I();
1386 if (TraceBytecodes) {
1387 emitPushAddressOf(SystemInterface.toCString(i_start+": D2I"));
1388 emitCallMemory(SystemInterface._debugwriteln);
1389 }
1390 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1391 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1392 toIntHelper();
1393 }
1394 public void visitD2L() {
1395 super.visitD2L();
1396 if (TraceBytecodes) {
1397 emitPushAddressOf(SystemInterface.toCString(i_start+": D2L"));
1398 emitCallMemory(SystemInterface._debugwriteln);
1399 }
1400 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1401 toLongHelper();
1402 }
1403 public void visitD2F() {
1404 super.visitD2F();
1405 if (TraceBytecodes) {
1406 emitPushAddressOf(SystemInterface.toCString(i_start+": D2F"));
1407 emitCallMemory(SystemInterface._debugwriteln);
1408 }
1409 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1410 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1411 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1412 }
1413 public void visitI2B() {
1414 super.visitI2B();
1415 if (TraceBytecodes) {
1416 emitPushAddressOf(SystemInterface.toCString(i_start+": I2B"));
1417 emitCallMemory(SystemInterface._debugwriteln);
1418 }
1419 asm.emitShort_Reg(x86.POP_r, EAX);
1420 asm.emit3_Reg_Reg(x86.MOVSX_r_r8, EAX, AL);
1421 asm.emitShort_Reg(x86.PUSH_r, EAX);
1422 }
1423 public void visitI2C() {
1424 super.visitI2C();
1425 if (TraceBytecodes) {
1426 emitPushAddressOf(SystemInterface.toCString(i_start+": I2C"));
1427 emitCallMemory(SystemInterface._debugwriteln);
1428 }
1429 asm.emitShort_Reg(x86.POP_r, EAX);
1430 asm.emit3_Reg_Reg(x86.MOVZX_r_r16, EAX, AX);
1431 asm.emitShort_Reg(x86.PUSH_r, EAX);
1432 }
1433 public void visitI2S() {
1434 super.visitI2S();
1435 if (TraceBytecodes) {
1436 emitPushAddressOf(SystemInterface.toCString(i_start+": I2S"));
1437 emitCallMemory(SystemInterface._debugwriteln);
1438 }
1439 asm.emitShort_Reg(x86.POP_r, EAX);
1440 asm.emit3_Reg_Reg(x86.MOVSX_r_r16, EAX, AX);
1441 asm.emitShort_Reg(x86.PUSH_r, EAX);
1442 }
1443 public void visitLCMP2() {
1444 super.visitLCMP2();
1445 if (TraceBytecodes) {
1446 emitPushAddressOf(SystemInterface.toCString(i_start+": LCMP2"));
1447 emitCallMemory(SystemInterface._debugwriteln);
1448 }
1449 asm.emitShort_Reg(x86.POP_r, EBX);
1450 asm.emitShort_Reg(x86.POP_r, ECX);
1451 asm.emitShort_Reg(x86.POP_r, EAX);
1452 asm.emitShort_Reg(x86.POP_r, EDX);
1453 asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
1454 asm.emitARITH_Reg_Reg(x86.SBB_r_r32, EDX, ECX);
1455 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
1456 asm.emitCJUMP_Short(x86.JL, (byte)0);
1457 int cloc1 = asm.getCurrentOffset();
1458 asm.emitARITH_Reg_Reg(x86.XOR_r_r32, ECX, ECX);
1459 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EDX);
1460 asm.emitCJUMP_Short(x86.JE, (byte)0);
1461 int cloc2 = asm.getCurrentOffset();
1462 asm.emitShort_Reg(x86.INC_r32, ECX);
1463 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1464 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1465 asm.emitShort_Reg(x86.PUSH_r, ECX);
1466 }
1467 public void visitFCMP2(byte op) {
1468 super.visitFCMP2(op);
1469 if (TraceBytecodes) {
1470 emitPushAddressOf(SystemInterface.toCString(i_start+": FCMP2 "+op));
1471 emitCallMemory(SystemInterface._debugwriteln);
1472 }
1473 if (op == CMP_L) {
1474 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1475 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
1476 } else {
1477 asm.emit2_Mem(x86.FLD_m32, 4, ESP);
1478 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1479 }
1480 asm.emit2(x86.FUCOMPP);
1481 asm.emit2(x86.FNSTSW_ax);
1482 asm.emit1(x86.SAHF);
1483 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1484 if (op == CMP_L) {
1485 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
1486 } else {
1487 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
1488 }
1489 asm.emitCJUMP_Short(x86.JB, (byte)0);
1490 int cloc1 = asm.getCurrentOffset();
1491 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1492 asm.emitCJUMP_Short(x86.JE, (byte)0);
1493 int cloc2 = asm.getCurrentOffset();
1494 if (op == CMP_L) {
1495 asm.emitShort_Reg(x86.INC_r32, ECX);
1496 } else {
1497 asm.emitShort_Reg(x86.DEC_r32, ECX);
1498 }
1499 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1500 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1501 asm.emitShort_Reg(x86.PUSH_r, ECX);
1502 }
1503 public void visitDCMP2(byte op) {
1504 super.visitDCMP2(op);
1505 if (TraceBytecodes) {
1506 emitPushAddressOf(SystemInterface.toCString(i_start+": DCMP2 "+op));
1507 emitCallMemory(SystemInterface._debugwriteln);
1508 }
1509 if (op == CMP_L) {
1510 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1511 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1512 } else {
1513 asm.emit2_Mem(x86.FLD_m64, 8, ESP);
1514 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1515 }
1516 asm.emit2(x86.FUCOMPP);
1517 asm.emit2(x86.FNSTSW_ax);
1518 asm.emit1(x86.SAHF);
1519 asm.emit2_Reg_Mem(x86.LEA, ESP, 16, ESP);
1520 if (op == CMP_L) {
1521 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
1522 } else {
1523 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
1524 }
1525 asm.emitCJUMP_Short(x86.JB, (byte)0);
1526 int cloc1 = asm.getCurrentOffset();
1527 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1528 asm.emitCJUMP_Short(x86.JE, (byte)0);
1529 int cloc2 = asm.getCurrentOffset();
1530 if (op == CMP_L) {
1531 asm.emitShort_Reg(x86.INC_r32, ECX);
1532 } else {
1533 asm.emitShort_Reg(x86.DEC_r32, ECX);
1534 }
1535 asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1536 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1537 asm.emitShort_Reg(x86.PUSH_r, ECX);
1538 }
1539 private void branchHelper(byte op, int target) {
1540 Integer t = new Integer(target);
1541 if (op == CMP_UNCOND) {
1542 if (target <= i_start)
1543 asm.emitJUMP_Back(x86.JMP, t);
1544 else
1545 asm.emitJUMP_Forw(x86.JMP, t);
1546 } else {
1547 x86 opc = null;
1548 switch(op) {
1549 case CMP_EQ: opc = x86.JE; break;
1550 case CMP_NE: opc = x86.JNE; break;
1551 case CMP_LT: opc = x86.JL; break;
1552 case CMP_GE: opc = x86.JGE; break;
1553 case CMP_LE: opc = x86.JLE; break;
1554 case CMP_GT: opc = x86.JG; break;
1555 case CMP_AE: opc = x86.JAE; break;
1556 default: Assert.UNREACHABLE();
1557 }
1558 if (target <= i_start)
1559 asm.emitCJUMP_Back(opc, t);
1560 else
1561 asm.emitCJUMP_Forw(opc, t);
1562 }
1563 }
1564 public void visitIF(byte op, int target) {
1565 super.visitIF(op, target);
1566 if (TraceBytecodes) {
1567 emitPushAddressOf(SystemInterface.toCString(i_start+": IF "+op+" "+target));
1568 emitCallMemory(SystemInterface._debugwriteln);
1569 }
1570 asm.emitShort_Reg(x86.POP_r, EAX);
1571 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, 0);
1572 branchHelper(op, target);
1573 }
1574 public void visitIFREF(byte op, int target) {
1575 super.visitIFREF(op, target);
1576 if (TraceBytecodes) {
1577 emitPushAddressOf(SystemInterface.toCString(i_start+": IFREF "+op+" "+target));
1578 emitCallMemory(SystemInterface._debugwriteln);
1579 }
1580 asm.emitShort_Reg(x86.POP_r, EAX);
1581 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, 0);
1582 branchHelper(op, target);
1583 }
1584 public void visitIFCMP(byte op, int target) {
1585 super.visitIFCMP(op, target);
1586 if (TraceBytecodes) {
1587 emitPushAddressOf(SystemInterface.toCString(i_start+": IFCMP "+op+" "+target));
1588 emitCallMemory(SystemInterface._debugwriteln);
1589 }
1590 asm.emitShort_Reg(x86.POP_r, ECX);
1591 asm.emitShort_Reg(x86.POP_r, EAX);
1592 asm.emitARITH_Reg_Reg(x86.CMP_r_r32, EAX, ECX);
1593 branchHelper(op, target);
1594 }
1595 public void visitIFREFCMP(byte op, int target) {
1596 super.visitIFREFCMP(op, target);
1597 if (TraceBytecodes) {
1598 emitPushAddressOf(SystemInterface.toCString(i_start+": IFREFCMP "+op+" "+target));
1599 emitCallMemory(SystemInterface._debugwriteln);
1600 }
1601 asm.emitShort_Reg(x86.POP_r, ECX);
1602 asm.emitShort_Reg(x86.POP_r, EAX);
1603 asm.emitARITH_Reg_Reg(x86.CMP_r_r32, EAX, ECX);
1604 branchHelper(op, target);
1605 }
1606 public void visitGOTO(int target) {
1607 super.visitGOTO(target);
1608 if (TraceBytecodes) {
1609 emitPushAddressOf(SystemInterface.toCString(i_start+": GOTO "+target));
1610 emitCallMemory(SystemInterface._debugwriteln);
1611 }
1612 branchHelper(CMP_UNCOND, target);
1613 }
1614 public void visitJSR(int target) {
1615 super.visitJSR(target);
1616 if (TraceBytecodes) {
1617 emitPushAddressOf(SystemInterface.toCString(i_start+": JSR "+target));
1618 emitCallMemory(SystemInterface._debugwriteln);
1619 }
1620 Integer t = new Integer(target);
1621 if (target <= i_start) {
1622 asm.emitCALL_Back(x86.CALL_rel32, t);
1623 } else {
1624 asm.emitCALL_Forw(x86.CALL_rel32, t);
1625 }
1626 }
1627 public void visitRET(int i) {
1628 super.visitRET(i);
1629 if (TraceBytecodes) {
1630 emitPushAddressOf(SystemInterface.toCString(i_start+": RET "+i));
1631 emitCallMemory(SystemInterface._debugwriteln);
1632 }
1633 asm.emit2_Mem(x86.JMP_m, getLocalOffset(i), EBP);
1634 }
1635 public void visitTABLESWITCH(int default_target, int low, int high, int[] targets) {
1636 super.visitTABLESWITCH(default_target, low, high, targets);
1637 if (TraceBytecodes) {
1638 emitPushAddressOf(SystemInterface.toCString(i_start+": TABLESWITCH "+default_target+" "+low+" "+high));
1639 emitCallMemory(SystemInterface._debugwriteln);
1640 }
1641 int count = high-low+1;
1642 Assert._assert(count == targets.length);
1643 asm.emitShort_Reg(x86.POP_r, EAX);
1644 if (low != 0)
1645 asm.emitARITH_Reg_Imm(x86.SUB_r_i32, EAX, low);
1646 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, count);
1647 branchHelper(CMP_AE, default_target);
1648 asm.emitCALL_rel32(x86.CALL_rel32, 0);
1649 int cloc = asm.getCurrentOffset();
1650 asm.emitShort_Reg(x86.POP_r, ECX);
1651
1652 asm.emit2_Reg_Mem(x86.LEA, EDX, ECX, EAX, SCALE_4, 127);
1653 int cloc2 = asm.getCurrentOffset();
1654 asm.emitARITH_Reg_Mem(x86.ADD_r_m32, EDX, -4, EDX);
1655 asm.emit2_Reg(x86.JMP_r, EDX);
1656 asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc+4));
1657 for (int i=0; i<count; ++i) {
1658 int target = targets[i];
1659 Integer t = new Integer(target);
1660 if (target <= i_start) {
1661 int offset = asm.getBranchTarget(t) - asm.getCurrentOffset() + 4;
1662 asm.emitDATA(offset);
1663 } else {
1664 asm.emitDATA(0x77777777);
1665 asm.recordForwardBranch(4, t);
1666 }
1667 }
1668 }
1669 public void visitLOOKUPSWITCH(int default_target, int[] values, int[] targets) {
1670 super.visitLOOKUPSWITCH(default_target, values, targets);
1671 if (TraceBytecodes) {
1672 emitPushAddressOf(SystemInterface.toCString(i_start+": LOOKUPSWITCH "+default_target));
1673 emitCallMemory(SystemInterface._debugwriteln);
1674 }
1675 asm.emitShort_Reg(x86.POP_r, EAX);
1676 for (int i=0; i<values.length; ++i) {
1677 int match = values[i];
1678 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, match);
1679 int target = targets[i];
1680 branchHelper(CMP_EQ, target);
1681 }
1682 branchHelper(CMP_UNCOND, default_target);
1683 }
1684 private void SYNCHEXIThelper() {
1685 if (method.isStatic()) {
1686 if (TraceBytecodes) {
1687 emitPushAddressOf(SystemInterface.toCString("exit: STATIC SYNCH EXIT"));
1688 emitCallMemory(SystemInterface._debugwriteln);
1689 }
1690
1691 Class c = Reflection.getJDKType(method.getDeclaringClass());
1692 Assert._assert(c != null);
1693 emitPushAddressOf(c);
1694 } else {
1695 if (TraceBytecodes) {
1696 emitPushAddressOf(SystemInterface.toCString("exit: INSTANCE SYNCH EXIT"));
1697 emitCallMemory(SystemInterface._debugwriteln);
1698 }
1699
1700 asm.emit2_Mem(x86.PUSH_m, getLocalOffset(0), EBP);
1701 }
1702 emitCallRelative(Monitor._monitorexit);
1703 }
1704 private void RETURN4helper() {
1705 if (method.isSynchronized()) SYNCHEXIThelper();
1706 if (TraceMethods) {
1707 emitPushAddressOf(SystemInterface.toCString("Leaving: "+method));
1708 emitCallMemory(SystemInterface._debugwriteln);
1709 }
1710
1711 asm.emitShort_Reg(x86.POP_r, EAX);
1712 asm.emit1(x86.LEAVE);
1713 asm.emit1_Imm16(x86.RET_i, (char)(n_paramwords<<2));
1714 }
1715 private void RETURN8helper() {
1716 if (method.isSynchronized()) SYNCHEXIThelper();
1717 if (TraceMethods) {
1718 emitPushAddressOf(SystemInterface.toCString("Leaving: "+method));
1719 emitCallMemory(SystemInterface._debugwriteln);
1720 }
1721
1722 asm.emitShort_Reg(x86.POP_r, EAX);
1723 asm.emitShort_Reg(x86.POP_r, EDX);
1724 asm.emit1(x86.LEAVE);
1725 asm.emit1_Imm16(x86.RET_i, (char)(n_paramwords<<2));
1726 }
1727 public void visitIRETURN() {
1728 super.visitIRETURN();
1729 if (TraceBytecodes) {
1730 emitPushAddressOf(SystemInterface.toCString(i_start+": IRETURN"));
1731 emitCallMemory(SystemInterface._debugwriteln);
1732 }
1733 RETURN4helper();
1734 }
1735 public void visitLRETURN() {
1736 super.visitLRETURN();
1737 if (TraceBytecodes) {
1738 emitPushAddressOf(SystemInterface.toCString(i_start+": LRETURN"));
1739 emitCallMemory(SystemInterface._debugwriteln);
1740 }
1741 RETURN8helper();
1742 }
1743 public void visitFRETURN() {
1744 super.visitFRETURN();
1745 if (TraceBytecodes) {
1746 emitPushAddressOf(SystemInterface.toCString(i_start+": FRETURN"));
1747 emitCallMemory(SystemInterface._debugwriteln);
1748 }
1749 RETURN4helper();
1750 }
1751 public void visitDRETURN() {
1752 super.visitDRETURN();
1753 if (TraceBytecodes) {
1754 emitPushAddressOf(SystemInterface.toCString(i_start+": DRETURN"));
1755 emitCallMemory(SystemInterface._debugwriteln);
1756 }
1757 RETURN8helper();
1758 }
1759 public void visitARETURN() {
1760 super.visitARETURN();
1761 if (TraceBytecodes) {
1762 emitPushAddressOf(SystemInterface.toCString(i_start+": ARETURN"));
1763 emitCallMemory(SystemInterface._debugwriteln);
1764 }
1765 RETURN4helper();
1766 }
1767 public void visitVRETURN() {
1768 super.visitVRETURN();
1769 if (method.isSynchronized()) SYNCHEXIThelper();
1770 if (TraceBytecodes) {
1771 emitPushAddressOf(SystemInterface.toCString(i_start+": VRETURN"));
1772 emitCallMemory(SystemInterface._debugwriteln);
1773 }
1774 if (TraceMethods) {
1775 emitPushAddressOf(SystemInterface.toCString("Leaving: "+method));
1776 emitCallMemory(SystemInterface._debugwriteln);
1777 }
1778 asm.emit1(x86.LEAVE);
1779 asm.emit1_Imm16(x86.RET_i, (char)(n_paramwords<<2));
1780 }
1781 public void GETSTATIC4helper(jq_StaticField f) {
1782 f = tryResolve(f);
1783 boolean dynlink = state.needsDynamicLink(method, f);
1784 if (dynlink) {
1785 if (TraceBytecodes) {
1786 emitPushAddressOf(SystemInterface.toCString(i_start+": GETSTATIC4 "+f+" (dynpatch)"));
1787 emitCallMemory(SystemInterface._debugwriteln);
1788 }
1789
1790 asm.startDynamicPatch(10);
1791 emitPushAddressOf(f);
1792 emitCallRelative(x86ReferenceLinker._getstatic4);
1793 asm.endDynamicPatch();
1794 } else {
1795 if (TraceBytecodes) {
1796 emitPushAddressOf(SystemInterface.toCString(i_start+": GETSTATIC4 "+f));
1797 emitCallMemory(SystemInterface._debugwriteln);
1798 }
1799 emitPushMemory(f);
1800 }
1801 }
1802 static int patch_getstatic4(CodeAddress retloc, jq_StaticField f) {
1803
1804 retloc.offset(-10).poke2((short)0xFFEB);
1805 retloc.offset(-8 ).poke4(0x35FF9090);
1806 retloc.offset(-4 ).poke(f.getAddress());
1807 retloc.offset(-10).poke2((short)0x9090);
1808 return 6;
1809 }
1810 public void GETSTATIC8helper(jq_StaticField f) {
1811 f = tryResolve(f);
1812 boolean dynlink = state.needsDynamicLink(method, f);
1813 if (dynlink) {
1814 if (TraceBytecodes) {
1815 emitPushAddressOf(SystemInterface.toCString(i_start+": GETSTATIC8 "+f+" (dynpatch)"));
1816 emitCallMemory(SystemInterface._debugwriteln);
1817 }
1818
1819 asm.startDynamicPatch(12);
1820 emitPushAddressOf(f);
1821 emitCallRelative(x86ReferenceLinker._getstatic8);
1822 asm.endDynamicPatch();
1823 } else {
1824 if (TraceBytecodes) {
1825 emitPushAddressOf(SystemInterface.toCString(i_start+": GETSTATIC8 "+f));
1826 emitCallMemory(SystemInterface._debugwriteln);
1827 }
1828 emitPushMemory8(f);
1829 }
1830 }
1831 static int patch_getstatic8(CodeAddress retloc, jq_StaticField f) {
1832
1833 retloc.offset(-10).poke2((short)0xFFEB);
1834 retloc.offset(-8 ).poke(f.getAddress().offset(4));
1835 retloc.offset(-4 ).poke2((short)0x35FF);
1836 retloc.offset(-2 ).poke(f.getAddress());
1837 retloc.offset(-10).poke2((short)0x35FF);
1838 return 10;
1839 }
1840 public void visitIGETSTATIC(jq_StaticField f) {
1841 super.visitIGETSTATIC(f);
1842 GETSTATIC4helper(f);
1843 }
1844 public void visitLGETSTATIC(jq_StaticField f) {
1845 super.visitLGETSTATIC(f);
1846 GETSTATIC8helper(f);
1847 }
1848 public void visitFGETSTATIC(jq_StaticField f) {
1849 super.visitFGETSTATIC(f);
1850 GETSTATIC4helper(f);
1851 }
1852 public void visitDGETSTATIC(jq_StaticField f) {
1853 super.visitDGETSTATIC(f);
1854 GETSTATIC8helper(f);
1855 }
1856 public void visitAGETSTATIC(jq_StaticField f) {
1857 super.visitAGETSTATIC(f);
1858 GETSTATIC4helper(f);
1859 }
1860 public void visitZGETSTATIC(jq_StaticField f) {
1861 super.visitZGETSTATIC(f);
1862 GETSTATIC4helper(f);
1863 }
1864 public void visitBGETSTATIC(jq_StaticField f) {
1865 super.visitBGETSTATIC(f);
1866 GETSTATIC4helper(f);
1867 }
1868 public void visitCGETSTATIC(jq_StaticField f) {
1869 super.visitCGETSTATIC(f);
1870 GETSTATIC4helper(f);
1871 }
1872 public void visitSGETSTATIC(jq_StaticField f) {
1873 super.visitSGETSTATIC(f);
1874 GETSTATIC4helper(f);
1875 }
1876 public void PUTSTATIC4helper(jq_StaticField f) {
1877 f = tryResolve(f);
1878 boolean dynlink = state.needsDynamicLink(method, f);
1879 if (dynlink) {
1880 if (TraceBytecodes) {
1881 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTSTATIC4 "+f+" (dynpatch)"));
1882 emitCallMemory(SystemInterface._debugwriteln);
1883 }
1884
1885 asm.startDynamicPatch(10);
1886 emitPushAddressOf(f);
1887 emitCallRelative(x86ReferenceLinker._putstatic4);
1888 asm.endDynamicPatch();
1889 } else {
1890 if (TraceBytecodes) {
1891 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTSTATIC4 "+f));
1892 emitCallMemory(SystemInterface._debugwriteln);
1893 }
1894 emitPopMemory(f);
1895 }
1896 }
1897 static int patch_putstatic4(CodeAddress retloc, jq_StaticField f) {
1898
1899 retloc.offset(-10).poke2((short)0xFFEB);
1900 retloc.offset(-8 ).poke4(0x058F9090);
1901 retloc.offset(-4 ).poke(f.getAddress());
1902 retloc.offset(-10).poke2((short)0x9090);
1903 return 6;
1904 }
1905 public void PUTSTATIC8helper(jq_StaticField f) {
1906 f = tryResolve(f);
1907 boolean dynlink = state.needsDynamicLink(method, f);
1908 if (dynlink) {
1909
1910 if (TraceBytecodes) {
1911 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTSTATIC8 "+f+" (dynpatch)"));
1912 emitCallMemory(SystemInterface._debugwriteln);
1913 }
1914 asm.startDynamicPatch(12);
1915 emitPushAddressOf(f);
1916 emitCallRelative(x86ReferenceLinker._putstatic8);
1917 asm.endDynamicPatch();
1918 } else {
1919 if (TraceBytecodes) {
1920 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTSTATIC8 "+f));
1921 emitCallMemory(SystemInterface._debugwriteln);
1922 }
1923 emitPopMemory8(f);
1924 }
1925 }
1926 static int patch_putstatic8(CodeAddress retloc, jq_StaticField f) {
1927
1928 retloc.offset(-10).poke2((short)0xFFEB);
1929 retloc.offset(-8 ).poke(f.getAddress().offset(4));
1930 retloc.offset(-4 ).poke2((short)0x058F);
1931 retloc.offset(-2 ).poke(f.getAddress());
1932 retloc.offset(-10).poke2((short)0x058F);
1933 return 10;
1934 }
1935 public void visitIPUTSTATIC(jq_StaticField f) {
1936 super.visitIPUTSTATIC(f);
1937 PUTSTATIC4helper(f);
1938 }
1939 public void visitLPUTSTATIC(jq_StaticField f) {
1940 super.visitLPUTSTATIC(f);
1941 PUTSTATIC8helper(f);
1942 }
1943 public void visitFPUTSTATIC(jq_StaticField f) {
1944 super.visitFPUTSTATIC(f);
1945 PUTSTATIC4helper(f);
1946 }
1947 public void visitDPUTSTATIC(jq_StaticField f) {
1948 super.visitDPUTSTATIC(f);
1949 PUTSTATIC8helper(f);
1950 }
1951 public void visitAPUTSTATIC(jq_StaticField f) {
1952 super.visitAPUTSTATIC(f);
1953 PUTSTATIC4helper(f);
1954 }
1955 public void visitZPUTSTATIC(jq_StaticField f) {
1956 super.visitZPUTSTATIC(f);
1957 PUTSTATIC4helper(f);
1958 }
1959 public void visitBPUTSTATIC(jq_StaticField f) {
1960 super.visitBPUTSTATIC(f);
1961 PUTSTATIC4helper(f);
1962 }
1963 public void visitCPUTSTATIC(jq_StaticField f) {
1964 super.visitCPUTSTATIC(f);
1965 PUTSTATIC4helper(f);
1966 }
1967 public void visitSPUTSTATIC(jq_StaticField f) {
1968 super.visitSPUTSTATIC(f);
1969 PUTSTATIC4helper(f);
1970 }
1971 public void GETFIELD1helper(jq_InstanceField f) {
1972 f = tryResolve(f);
1973 boolean dynlink = state.needsDynamicLink(method, f);
1974 if (dynlink) {
1975
1976 if (TraceBytecodes) {
1977 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD1 "+f+" (dynpatch)"));
1978 emitCallMemory(SystemInterface._debugwriteln);
1979 }
1980 asm.startDynamicPatch(10);
1981 emitPushAddressOf(f);
1982 emitCallRelative(x86ReferenceLinker._getfield1);
1983 asm.endDynamicPatch();
1984 } else {
1985 if (TraceBytecodes) {
1986 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD1 "+f));
1987 emitCallMemory(SystemInterface._debugwriteln);
1988 }
1989 asm.emitShort_Reg(x86.POP_r, EAX);
1990 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, EBX, f.getOffset(), EAX);
1991 asm.emitShort_Reg(x86.PUSH_r, EBX);
1992 }
1993 }
1994 static int patch_getfield1(CodeAddress retloc, jq_InstanceField f) {
1995 retloc.offset(-10).poke2((short)0xFFEB);
1996 retloc.offset(-8 ).poke4(0x0098BE0F);
1997 retloc.offset(-5 ).poke4(f.getOffset());
1998 retloc.offset(-1 ).poke1((byte)0x53);
1999 retloc.offset(-10).poke2((short)0x5890);
2000 return 9;
2001 }
2002 public void GETFIELD4helper(jq_InstanceField f) {
2003 f = tryResolve(f);
2004 boolean dynlink = state.needsDynamicLink(method, f);
2005 if (dynlink) {
2006
2007 if (TraceBytecodes) {
2008 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD4 "+f+" (dynpatch)"));
2009 emitCallMemory(SystemInterface._debugwriteln);
2010 }
2011 asm.startDynamicPatch(10);
2012 emitPushAddressOf(f);
2013 emitCallRelative(x86ReferenceLinker._getfield4);
2014 asm.endDynamicPatch();
2015 } else {
2016 if (TraceBytecodes) {
2017 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD4 "+f));
2018 emitCallMemory(SystemInterface._debugwriteln);
2019 }
2020 asm.emitShort_Reg(x86.POP_r, EAX);
2021 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);
2022 }
2023 }
2024 static int patch_getfield4(CodeAddress retloc, jq_InstanceField f) {
2025 retloc.offset(-10).poke2((short)0xFFEB);
2026 retloc.offset(-8 ).poke4(0xB0FF5890);
2027 retloc.offset(-4 ).poke4(f.getOffset());
2028 retloc.offset(-10).poke2((short)0x9090);
2029 return 7;
2030 }
2031 public void GETFIELD8helper(jq_InstanceField f) {
2032 f = tryResolve(f);
2033 boolean dynlink = state.needsDynamicLink(method, f);
2034 if (dynlink) {
2035 if (TraceBytecodes) {
2036 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD8 "+f+" (dynpatch)"));
2037 emitCallMemory(SystemInterface._debugwriteln);
2038 }
2039
2040 asm.startDynamicPatch(13);
2041 emitPushAddressOf(f);
2042 emitCallRelative(x86ReferenceLinker._getfield8);
2043 asm.endDynamicPatch();
2044 } else {
2045 if (TraceBytecodes) {
2046 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD8 "+f));
2047 emitCallMemory(SystemInterface._debugwriteln);
2048 }
2049 asm.emitShort_Reg(x86.POP_r, EAX);
2050 asm.emit2_Mem(x86.PUSH_m, f.getOffset()+4, EAX);
2051 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);
2052 }
2053 }
2054 static int patch_getfield8(CodeAddress retloc, jq_InstanceField f) {
2055 retloc.offset(-10).poke4(0x00B0FFEB);
2056 retloc.offset(-7 ).poke4(f.getOffset()+4);
2057 retloc.offset(-3 ).poke2((short)0xB0FF);
2058 retloc.offset(-1 ).poke4(f.getOffset());
2059 retloc.offset(-10).poke1((byte)0x58);
2060 return 10;
2061 }
2062 public void visitIGETFIELD(jq_InstanceField f) {
2063 super.visitIGETFIELD(f);
2064 GETFIELD4helper(f);
2065 }
2066 public void visitLGETFIELD(jq_InstanceField f) {
2067 super.visitLGETFIELD(f);
2068 GETFIELD8helper(f);
2069 }
2070 public void visitFGETFIELD(jq_InstanceField f) {
2071 super.visitFGETFIELD(f);
2072 GETFIELD4helper(f);
2073 }
2074 public void visitDGETFIELD(jq_InstanceField f) {
2075 super.visitDGETFIELD(f);
2076 GETFIELD8helper(f);
2077 }
2078 public void visitAGETFIELD(jq_InstanceField f) {
2079 super.visitAGETFIELD(f);
2080 GETFIELD4helper(f);
2081 }
2082 public void visitBGETFIELD(jq_InstanceField f) {
2083 super.visitBGETFIELD(f);
2084 GETFIELD1helper(f);
2085 }
2086 public void visitCGETFIELD(jq_InstanceField f) {
2087 super.visitCGETFIELD(f);
2088 f = tryResolve(f);
2089 boolean dynlink = state.needsDynamicLink(method, f);
2090 if (dynlink) {
2091 if (TraceBytecodes) {
2092 emitPushAddressOf(SystemInterface.toCString(i_start+": CGETFIELD "+f+" (dynpatch)"));
2093 emitCallMemory(SystemInterface._debugwriteln);
2094 }
2095
2096 asm.startDynamicPatch(10);
2097 emitPushAddressOf(f);
2098 emitCallRelative(x86ReferenceLinker._cgetfield);
2099 asm.endDynamicPatch();
2100 } else {
2101 if (TraceBytecodes) {
2102 emitPushAddressOf(SystemInterface.toCString(i_start+": CGETFIELD "+f));
2103 emitCallMemory(SystemInterface._debugwriteln);
2104 }
2105 asm.emitShort_Reg(x86.POP_r, EAX);
2106 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, EBX, f.getOffset(), EAX);
2107 asm.emitShort_Reg(x86.PUSH_r, EBX);
2108 }
2109 }
2110 static int patch_cgetfield(CodeAddress retloc, jq_InstanceField f) {
2111 retloc.offset(-10).poke2((short)0xFFEB);
2112 retloc.offset(-8 ).poke4(0x0098B70F);
2113 retloc.offset(-5 ).poke4(f.getOffset());
2114 retloc.offset(-1 ).poke1((byte)0x53);
2115 retloc.offset(-10).poke2((short)0x5890);
2116 return 9;
2117 }
2118 public void visitSGETFIELD(jq_InstanceField f) {
2119 super.visitSGETFIELD(f);
2120 f = tryResolve(f);
2121 boolean dynlink = state.needsDynamicLink(method, f);
2122 if (dynlink) {
2123 if (TraceBytecodes) {
2124 emitPushAddressOf(SystemInterface.toCString(i_start+": SGETFIELD "+f+" (dynpatch)"));
2125 emitCallMemory(SystemInterface._debugwriteln);
2126 }
2127
2128 asm.startDynamicPatch(10);
2129 emitPushAddressOf(f);
2130 emitCallRelative(x86ReferenceLinker._sgetfield);
2131 asm.endDynamicPatch();
2132 } else {
2133 if (TraceBytecodes) {
2134 emitPushAddressOf(SystemInterface.toCString(i_start+": SGETFIELD "+f));
2135 emitCallMemory(SystemInterface._debugwriteln);
2136 }
2137 asm.emitShort_Reg(x86.POP_r, EAX);
2138 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, EBX, f.getOffset(), EAX);
2139 asm.emitShort_Reg(x86.PUSH_r, EBX);
2140 }
2141 }
2142 static int patch_sgetfield(CodeAddress retloc, jq_InstanceField f) {
2143 retloc.offset(-10).poke2((short)0xFFEB);
2144 retloc.offset(-8 ).poke4(0x0098BF0F);
2145 retloc.offset(-5 ).poke4(f.getOffset());
2146 retloc.offset(-1 ).poke1((byte)0x53);
2147 retloc.offset(-10).poke2((short)0x5890);
2148 return 9;
2149 }
2150 public void visitZGETFIELD(jq_InstanceField f) {
2151 super.visitZGETFIELD(f);
2152 GETFIELD1helper(f);
2153 }
2154 public void PUTFIELD1helper(jq_InstanceField f) {
2155 f = tryResolve(f);
2156 boolean dynlink = state.needsDynamicLink(method, f);
2157 if (dynlink) {
2158 if (TraceBytecodes) {
2159 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD1 "+f+" (dynpatch)"));
2160 emitCallMemory(SystemInterface._debugwriteln);
2161 }
2162
2163 asm.startDynamicPatch(10);
2164 emitPushAddressOf(f);
2165 emitCallRelative(x86ReferenceLinker._putfield1);
2166 asm.endDynamicPatch();
2167 } else {
2168 if (TraceBytecodes) {
2169 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD1 "+f));
2170 emitCallMemory(SystemInterface._debugwriteln);
2171 }
2172
2173 asm.emitShort_Reg(x86.POP_r, EBX);
2174 asm.emitShort_Reg(x86.POP_r, EAX);
2175 asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, f.getOffset(), EAX);
2176 }
2177 }
2178 static int patch_putfield1(CodeAddress retloc, jq_InstanceField f) {
2179 retloc.offset(-10).poke2((short)0xFFEB);
2180 retloc.offset(-8 ).poke4(0x9888585B);
2181 retloc.offset(-4 ).poke4(f.getOffset());
2182 retloc.offset(-10).poke2((short)0x9090);
2183 return 8;
2184 }
2185 public void PUTFIELD2helper(jq_InstanceField f) {
2186 f = tryResolve(f);
2187 boolean dynlink = state.needsDynamicLink(method, f);
2188 if (dynlink) {
2189 if (TraceBytecodes) {
2190 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD2 "+f+" (dynpatch)"));
2191 emitCallMemory(SystemInterface._debugwriteln);
2192 }
2193
2194 asm.startDynamicPatch(10);
2195 emitPushAddressOf(f);
2196 emitCallRelative(x86ReferenceLinker._putfield2);
2197 asm.endDynamicPatch();
2198 } else {
2199 if (TraceBytecodes) {
2200 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD2 "+f));
2201 emitCallMemory(SystemInterface._debugwriteln);
2202 }
2203
2204 asm.emitShort_Reg(x86.POP_r, EBX);
2205 asm.emitShort_Reg(x86.POP_r, EAX);
2206 asm.emitprefix(x86.PREFIX_16BIT);
2207 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
2208 }
2209 }
2210 static int patch_putfield2(CodeAddress retloc, jq_InstanceField f) {
2211 retloc.offset(-10).poke4(0x6658FFEB);
2212 retloc.offset(-6 ).poke2((short)0x9889);
2213 retloc.offset(-4 ).poke4(f.getOffset());
2214 retloc.offset(-10).poke2((short)0x5B90);
2215 return 9;
2216 }
2217 public void PUTFIELD4helper(jq_InstanceField f) {
2218 f = tryResolve(f);
2219 boolean dynlink = state.needsDynamicLink(method, f);
2220 if (dynlink) {
2221 if (TraceBytecodes) {
2222 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD4 "+f+" (dynpatch)"));
2223 emitCallMemory(SystemInterface._debugwriteln);
2224 }
2225
2226 asm.startDynamicPatch(10);
2227 emitPushAddressOf(f);
2228 emitCallRelative(x86ReferenceLinker._putfield4);
2229 asm.endDynamicPatch();
2230 } else {
2231 if (TraceBytecodes) {
2232 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD4 "+f));
2233 emitCallMemory(SystemInterface._debugwriteln);
2234 }
2235
2236 asm.emitShort_Reg(x86.POP_r, EBX);
2237 asm.emitShort_Reg(x86.POP_r, EAX);
2238 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
2239 }
2240 }
2241 static int patch_putfield4(CodeAddress retloc, jq_InstanceField f) {
2242 retloc.offset(-10).poke2((short)0xFFEB);
2243 retloc.offset(-8 ).poke4(0x9889585B);
2244 retloc.offset(-4 ).poke4(f.getOffset());
2245 retloc.offset(-10).poke2((short)0x9090);
2246 return 8;
2247 }
2248 public void PUTFIELD8helper(jq_InstanceField f) {
2249 f = tryResolve(f);
2250 boolean dynlink = state.needsDynamicLink(method, f);
2251 if (dynlink) {
2252 if (TraceBytecodes) {
2253 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD8 "+f+" (dynpatch)"));
2254 emitCallMemory(SystemInterface._debugwriteln);
2255 }
2256
2257 asm.startDynamicPatch(15);
2258 emitPushAddressOf(f);
2259 emitCallRelative(x86ReferenceLinker._putfield8);
2260 asm.endDynamicPatch();
2261 } else {
2262 if (TraceBytecodes) {
2263 emitPushAddressOf(SystemInterface.toCString(i_start+": PUTFIELD8 "+f));
2264 emitCallMemory(SystemInterface._debugwriteln);
2265 }
2266
2267 asm.emitShort_Reg(x86.POP_r, EBX);
2268 asm.emitShort_Reg(x86.POP_r, EAX);
2269 asm.emitShort_Reg(x86.POP_r, EDX);
2270 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset() , EDX);
2271 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, f.getOffset()+4, EDX);
2272 }
2273 }
2274 static int patch_putfield8(CodeAddress retloc, jq_InstanceField f) {
2275 retloc.offset(-10).poke4(0x895AFFEB);
2276 retloc.offset(-6 ).poke1((byte)0x9A);
2277 retloc.offset(-5 ).poke4(f.getOffset());
2278 retloc.offset(-1 ).poke2((short)0x8289);
2279 retloc.offset( 1 ).poke4(f.getOffset()+4);
2280 retloc.offset(-10).poke2((short)0x585B);
2281 return 10;
2282 }
2283 public void visitIPUTFIELD(jq_InstanceField f) {
2284 super.visitIPUTFIELD(f);
2285 PUTFIELD4helper(f);
2286 }
2287 public void visitLPUTFIELD(jq_InstanceField f) {
2288 super.visitLPUTFIELD(f);
2289 PUTFIELD8helper(f);
2290 }
2291 public void visitFPUTFIELD(jq_InstanceField f) {
2292 super.visitFPUTFIELD(f);
2293 PUTFIELD4helper(f);
2294 }
2295 public void visitDPUTFIELD(jq_InstanceField f) {
2296 super.visitDPUTFIELD(f);
2297 PUTFIELD8helper(f);
2298 }
2299 public void visitAPUTFIELD(jq_InstanceField f) {
2300 super.visitAPUTFIELD(f);
2301 PUTFIELD4helper(f);
2302 }
2303 public void visitBPUTFIELD(jq_InstanceField f) {
2304 super.visitBPUTFIELD(f);
2305 PUTFIELD1helper(f);
2306 }
2307 public void visitCPUTFIELD(jq_InstanceField f) {
2308 super.visitCPUTFIELD(f);
2309 PUTFIELD2helper(f);
2310 }
2311 public void visitSPUTFIELD(jq_InstanceField f) {
2312 super.visitSPUTFIELD(f);
2313 PUTFIELD2helper(f);
2314 }
2315 public void visitZPUTFIELD(jq_InstanceField f) {
2316 super.visitZPUTFIELD(f);
2317 PUTFIELD1helper(f);
2318 }
2319 private void INVOKEDPATCHhelper(byte op, jq_Method f) {
2320 int dpatchsize;
2321 jq_StaticMethod dpatchentry;
2322 switch (op) {
2323 case INVOKE_VIRTUAL:
2324 dpatchsize = 16;
2325 dpatchentry = x86ReferenceLinker._invokevirtual;
2326 break;
2327 case INVOKE_STATIC:
2328 dpatchsize = 11;
2329 dpatchentry = x86ReferenceLinker._invokestatic;
2330 break;
2331 case INVOKE_SPECIAL:
2332 dpatchsize = 11;
2333 dpatchentry = x86ReferenceLinker._invokespecial;
2334 break;
2335 case INVOKE_INTERFACE:
2336
2337 default:
2338 throw new InternalError();
2339 }
2340 if (TraceBytecodes) {
2341 emitPushAddressOf(SystemInterface.toCString(i_start+": INVOKE "+op+" "+f+" (dynpatch)"));
2342 emitCallMemory(SystemInterface._debugwriteln);
2343 }
2344
2345 asm.startDynamicPatch(dpatchsize);
2346 emitPushAddressOf(f);
2347 emitCallRelative(dpatchentry);
2348 asm.endDynamicPatch();
2349 }
2350 static int patch_invokevirtual(CodeAddress retloc, jq_InstanceMethod f) {
2351 retloc.offset(-10).poke2((short)0xFFEB);
2352 retloc.offset(-8 ).poke1((byte)0x24);
2353 int objptroffset = (f.getParamWords() << 2) - 4;
2354 retloc.offset(-7 ).poke4(objptroffset);
2355 retloc.offset(-3 ).poke2((short)0x588B);
2356 retloc.offset(-1 ).poke1((byte)ObjectLayout.VTABLE_OFFSET);
2357 retloc. poke2((short)0x93FF);
2358 retloc.offset( 2 ).poke4(f.getOffset());
2359 retloc.offset(-10).poke2((short)0x848B);
2360 return 10;
2361 }
2362 static int patch_invokestatic(CodeAddress retloc, jq_Method f) {
2363 retloc.offset(-10).poke4(0x9090FFEB);
2364 retloc.offset(-6 ).poke2((short)0xE890);
2365 retloc.offset(-4 ).poke4(f.getDefaultCompiledVersion().getEntrypoint().difference(retloc));
2366 retloc.offset(-10).poke2((short)0x9090);
2367 return 5;
2368 }
2369 private void INVOKENODPATCHhelper(byte op, jq_Method f) {
2370 if (TraceBytecodes) {
2371 emitPushAddressOf(SystemInterface.toCString(i_start+": INVOKE "+op+" "+f));
2372 emitCallMemory(SystemInterface._debugwriteln);
2373 }
2374 switch(op) {
2375 case INVOKE_VIRTUAL: {
2376 int objptroffset = (f.getParamWords() << 2) - 4;
2377 int m_off = ((jq_InstanceMethod)f).getOffset();
2378 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, objptroffset, ESP);
2379 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, ObjectLayout.VTABLE_OFFSET, EAX);
2380 asm.emit2_Mem(x86.CALL_m, m_off, EBX);
2381 break;
2382 }
2383 case INVOKE_SPECIAL:
2384 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
2385 emitCallRelative(f);
2386 break;
2387 case INVOKE_STATIC:
2388 emitCallRelative(f);
2389 break;
2390 case INVOKE_INTERFACE:
2391
2392 emitPushAddressOf(f);
2393 emitCallRelative(x86ReferenceLinker._invokeinterface);
2394
2395 asm.emit2_Reg_Mem(x86.LEA, ESP, f.getParamWords()<<2, ESP);
2396 break;
2397 default:
2398 Assert.UNREACHABLE();
2399 }
2400 }
2401 private void INVOKEhelper(byte op, jq_Method f) {
2402 f = (jq_Method) tryResolve(f);
2403 Assert._assert(!f.getDeclaringClass().getName().equals("joeq.Runtime.Unsafe"));
2404 boolean dynlink = state.needsDynamicLink(method, f);
2405 switch (op) {
2406 case INVOKE_VIRTUAL:
2407 if (dynlink)
2408 INVOKEDPATCHhelper(op, f);
2409 else
2410 INVOKENODPATCHhelper(op, f);
2411 break;
2412 case INVOKE_STATIC:
2413
2414 case INVOKE_SPECIAL:
2415 if (dynlink)
2416 INVOKEDPATCHhelper(op, f);
2417 else
2418 INVOKENODPATCHhelper(op, f);
2419 break;
2420 case INVOKE_INTERFACE:
2421 INVOKENODPATCHhelper(op, f);
2422 break;
2423 default:
2424 throw new InternalError();
2425 }
2426 }
2427 public void visitIINVOKE(byte op, jq_Method f) {
2428 super.visitIINVOKE(op, f);
2429 if (f.getDeclaringClass() == Unsafe._class) {
2430 gen_unsafe(f);
2431 return;
2432 }
2433 if (f.getDeclaringClass().isAddressType()) {
2434 genAddress(f);
2435 return;
2436 }
2437 INVOKEhelper(op, f);
2438 asm.emitShort_Reg(x86.PUSH_r, EAX);
2439 }
2440 public void visitLINVOKE(byte op, jq_Method f) {
2441 super.visitLINVOKE(op, f);
2442 if (f.getDeclaringClass() == Unsafe._class) {
2443 gen_unsafe(f);
2444 return;
2445 }
2446 if (f.getDeclaringClass().isAddressType()) {
2447 genAddress(f);
2448 return;
2449 }
2450 INVOKEhelper(op, f);
2451 asm.emitShort_Reg(x86.PUSH_r, EDX);
2452 asm.emitShort_Reg(x86.PUSH_r, EAX);
2453 }
2454 public void visitFINVOKE(byte op, jq_Method f) {
2455 super.visitFINVOKE(op, f);
2456 if (f.getDeclaringClass() == Unsafe._class) {
2457 gen_unsafe(f);
2458 return;
2459 }
2460 if (f.getDeclaringClass().isAddressType()) {
2461 genAddress(f);
2462 return;
2463 }
2464 INVOKEhelper(op, f);
2465 asm.emitShort_Reg(x86.PUSH_r, EAX);
2466 }
2467 public void visitDINVOKE(byte op, jq_Method f) {
2468 super.visitDINVOKE(op, f);
2469 if (f.getDeclaringClass() == Unsafe._class) {
2470 gen_unsafe(f);
2471 return;
2472 }
2473 if (f.getDeclaringClass().isAddressType()) {
2474 genAddress(f);
2475 return;
2476 }
2477 INVOKEhelper(op, f);
2478 asm.emitShort_Reg(x86.PUSH_r, EDX);
2479 asm.emitShort_Reg(x86.PUSH_r, EAX);
2480 }
2481 public void visitAINVOKE(byte op, jq_Method f) {
2482 super.visitAINVOKE(op, f);
2483 if (f.getDeclaringClass() == Unsafe._class) {
2484 gen_unsafe(f);
2485 return;
2486 }
2487 if (f.getDeclaringClass().isAddressType()) {
2488 genAddress(f);
2489 return;
2490 }
2491 INVOKEhelper(op, f);
2492 asm.emitShort_Reg(x86.PUSH_r, EAX);
2493 }
2494 public void visitVINVOKE(byte op, jq_Method f) {
2495 super.visitVINVOKE(op, f);
2496 if (f.getDeclaringClass() == Unsafe._class) {
2497 gen_unsafe(f);
2498 return;
2499 }
2500 if (f.getDeclaringClass().isAddressType()) {
2501 genAddress(f);
2502 return;
2503 }
2504 INVOKEhelper(op, f);
2505 }
2506 public void visitNEW(jq_Type f) {
2507 super.visitNEW(f);
2508 if (TraceBytecodes) {
2509 emitPushAddressOf(SystemInterface.toCString(i_start+": NEW "+f));
2510 emitCallMemory(SystemInterface._debugwriteln);
2511 }
2512 boolean dynlink = state.needsDynamicLink(method, f);
2513 if (f.isClassType() && !dynlink) {
2514 jq_Class k = (jq_Class)f;
2515 asm.emitPUSH_i(k.getInstanceSize());
2516 emitPushAddressOf(k.getVTable());
2517 emitCallRelative(DefaultHeapAllocator._allocateObject);
2518 } else {
2519 emitPushAddressOf(f);
2520 emitCallRelative(HeapAllocator._clsinitAndAllocateObject);
2521 }
2522 asm.emitShort_Reg(x86.PUSH_r, EAX);
2523 }
2524 public void visitNEWARRAY(jq_Array f) {
2525 super.visitNEWARRAY(f);
2526
2527
2528 if (!jq.RunningNative) {
2529
2530 } else {
2531 f.cls_initialize();
2532 }
2533 if (TraceBytecodes) {
2534 emitPushAddressOf(SystemInterface.toCString(i_start+": NEWARRAY "+f));
2535 emitCallMemory(SystemInterface._debugwriteln);
2536 }
2537 byte width = f.getLogElementSize();
2538 asm.emit2_Mem(x86.PUSH_m, 0, ESP);
2539 if (width != 0) asm.emit2_SHIFT_Mem_Imm8(x86.SHL_m32_i, 0, ESP, width);
2540 asm.emitARITH_Mem_Imm(x86.ADD_m_i32, 0, ESP, ObjectLayout.ARRAY_HEADER_SIZE);
2541 emitPushAddressOf(f.getVTable());
2542 emitCallRelative(DefaultHeapAllocator._allocateArray);
2543 asm.emitShort_Reg(x86.PUSH_r, EAX);
2544 }
2545 public void visitARRAYLENGTH() {
2546 super.visitARRAYLENGTH();
2547 if (TraceBytecodes) {
2548 emitPushAddressOf(SystemInterface.toCString(i_start+": ARRAYLENGTH"));
2549 emitCallMemory(SystemInterface._debugwriteln);
2550 }
2551 asm.emitShort_Reg(x86.POP_r, EAX);
2552 asm.emit2_Mem(x86.PUSH_m, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
2553 }
2554 public void visitATHROW() {
2555 super.visitATHROW();
2556 if (TraceBytecodes) {
2557 emitPushAddressOf(SystemInterface.toCString(i_start+": ATHROW"));
2558 emitCallMemory(SystemInterface._debugwriteln);
2559 }
2560 if (TraceMethods) {
2561 emitPushAddressOf(SystemInterface.toCString("Leaving: "+method+" (explicit athrow)"));
2562 emitCallMemory(SystemInterface._debugwriteln);
2563 }
2564 emitCallRelative(ExceptionDeliverer._athrow);
2565 }
2566 public void visitCHECKCAST(jq_Type f) {
2567 super.visitCHECKCAST(f);
2568 if (f.isAddressType()) return;
2569 if (TraceBytecodes) {
2570 emitPushAddressOf(SystemInterface.toCString(i_start+": CHECKCAST "+f));
2571 emitCallMemory(SystemInterface._debugwriteln);
2572 }
2573 emitPushAddressOf(f);
2574 emitCallRelative(TypeCheck._checkcast);
2575 asm.emitShort_Reg(x86.PUSH_r, EAX);
2576 }
2577 public void visitINSTANCEOF(jq_Type f) {
2578 super.visitINSTANCEOF(f);
2579 if (TraceBytecodes) {
2580 emitPushAddressOf(SystemInterface.toCString(i_start+": INSTANCEOF "+f));
2581 emitCallMemory(SystemInterface._debugwriteln);
2582 }
2583 emitPushAddressOf(f);
2584 emitCallRelative(TypeCheck._instance_of);
2585 asm.emitShort_Reg(x86.PUSH_r, EAX);
2586 }
2587 public void visitMONITOR(byte op) {
2588 super.visitMONITOR(op);
2589 if (TraceBytecodes) {
2590 emitPushAddressOf(SystemInterface.toCString(i_start+": MONITOR "+op));
2591 emitCallMemory(SystemInterface._debugwriteln);
2592 }
2593 jq_StaticMethod m = (op==MONITOR_ENTER)?Monitor._monitorenter:Monitor._monitorexit;
2594 emitCallRelative(m);
2595 }
2596 public void visitMULTINEWARRAY(jq_Type f, char dim) {
2597 super.visitMULTINEWARRAY(f, dim);
2598 if (TraceBytecodes) {
2599 emitPushAddressOf(SystemInterface.toCString(i_start+": MULTINEWARRAY "+f+" "+dim));
2600 emitCallMemory(SystemInterface._debugwriteln);
2601 }
2602 asm.emitPUSH_i(dim);
2603 emitPushAddressOf(f);
2604 emitCallRelative(joeq.Runtime.Arrays._multinewarray);
2605
2606 asm.emit2_Reg_Mem(x86.LEA, ESP, dim<<2, ESP);
2607 asm.emitShort_Reg(x86.PUSH_r, EAX);
2608 }
2609
2610 public static byte THREAD_BLOCK_PREFIX = x86.PREFIX_FS;
2611 public static int THREAD_BLOCK_OFFSET = 0x14;
2612
2613 public static final Utf8 peek = Utf8.get("peek");
2614 public static final Utf8 peek1 = Utf8.get("peek1");
2615 public static final Utf8 peek2 = Utf8.get("peek2");
2616 public static final Utf8 peek4 = Utf8.get("peek4");
2617 public static final Utf8 peek8 = Utf8.get("peek8");
2618 public static final Utf8 poke = Utf8.get("poke");
2619 public static final Utf8 poke1 = Utf8.get("poke1");
2620 public static final Utf8 poke2 = Utf8.get("poke2");
2621 public static final Utf8 poke4 = Utf8.get("poke4");
2622 public static final Utf8 poke8 = Utf8.get("poke8");
2623 public static final Utf8 offset = Utf8.get("offset");
2624 public static final Utf8 align = Utf8.get("align");
2625 public static final Utf8 difference = Utf8.get("difference");
2626 public static final Utf8 isNull = Utf8.get("isNull");
2627 public static final Utf8 addressOf = Utf8.get("addressOf");
2628 public static final Utf8 address32 = Utf8.get("address32");
2629 public static final Utf8 asObject = Utf8.get("asObject");
2630 public static final Utf8 asReferenceType = Utf8.get("asReferenceType");
2631 public static final Utf8 to32BitValue = Utf8.get("to32BitValue");
2632 public static final Utf8 stringRep = Utf8.get("stringRep");
2633 public static final Utf8 getNull = Utf8.get("getNull");
2634 public static final Utf8 size = Utf8.get("size");
2635 public static final Utf8 logSize = Utf8.get("logSize");
2636 public static final Utf8 pageAlign = Utf8.get("pageAlign");
2637 public static final Utf8 getBasePointer = Utf8.get("getBasePointer");
2638 public static final Utf8 getStackPointer = Utf8.get("getStackPointer");
2639 public static final Utf8 alloca = Utf8.get("alloca");
2640 public static final Utf8 atomicAdd = Utf8.get("atomicAdd");
2641 public static final Utf8 atomicSub = Utf8.get("atomicSub");
2642 public static final Utf8 atomicCas4 = Utf8.get("atomicCas4");
2643 public static final Utf8 atomicCas8 = Utf8.get("atomicCas8");
2644 public static final Utf8 atomicAnd = Utf8.get("atomicAnd");
2645 public static final Utf8 min = Utf8.get("min");
2646 public static final Utf8 max = Utf8.get("max");
2647
2648 private void genAddress(jq_Method f) {
2649 if (TraceBytecodes) {
2650 emitPushAddressOf(SystemInterface.toCString(i_start+": ADDRESS "+f));
2651 emitCallMemory(SystemInterface._debugwriteln);
2652 }
2653 if (f.getName() == peek1) {
2654 asm.emitShort_Reg(x86.POP_r, EAX);
2655 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, 0, EAX);
2656 asm.emitShort_Reg(x86.PUSH_r, ECX);
2657 } else if (f.getName() == peek2) {
2658 asm.emitShort_Reg(x86.POP_r, EAX);
2659 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, 0, EAX);
2660 asm.emitShort_Reg(x86.PUSH_r, ECX);
2661 } else if (f.getName() == peek4 || f.getName() == peek) {
2662 asm.emitShort_Reg(x86.POP_r, EAX);
2663 asm.emit2_Mem(x86.PUSH_m, 0, EAX);
2664 } else if (f.getName() == peek8) {
2665 asm.emitShort_Reg(x86.POP_r, EAX);
2666 asm.emit2_Mem(x86.PUSH_m, 4, EAX);
2667 asm.emit2_Mem(x86.PUSH_m, 0, EAX);
2668 } else if (f.getName() == poke1) {
2669 asm.emitShort_Reg(x86.POP_r, EBX);
2670 asm.emitShort_Reg(x86.POP_r, EAX);
2671 asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, 0, EAX);
2672 } else if (f.getName() == poke2) {
2673 asm.emitShort_Reg(x86.POP_r, EBX);
2674 asm.emitShort_Reg(x86.POP_r, EAX);
2675 asm.emitprefix(x86.PREFIX_16BIT);
2676 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
2677 } else if (f.getName() == poke4 || f.getName() == poke) {
2678 asm.emitShort_Reg(x86.POP_r, EBX);
2679 asm.emitShort_Reg(x86.POP_r, EAX);
2680 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
2681 } else if (f.getName() == poke8) {
2682 asm.emitShort_Reg(x86.POP_r, EBX);
2683 asm.emitShort_Reg(x86.POP_r, ECX);
2684 asm.emitShort_Reg(x86.POP_r, EAX);
2685 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
2686 asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, 4, EAX);
2687 } else if (f.getName() == offset) {
2688 asm.emitShort_Reg(x86.POP_r, EAX);
2689 asm.emitARITH_Reg_Mem(x86.ADD_m_r32, EAX, 0, ESP);
2690 } else if (f.getName() == align) {
2691 asm.emitShort_Reg(x86.POP_r, ECX);
2692 asm.emitShort_Reg(x86.POP_r, EAX);
2693 asm.emitShort_Reg_Imm(x86.MOV_r_i32, EBX, 1);
2694 asm.emit2_Reg(x86.SHL_r32_rc, EBX);
2695 asm.emitShort_Reg(x86.DEC_r32, EBX);
2696 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
2697 asm.emit2_Reg(x86.NOT_r32, EBX);
2698 asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
2699 asm.emitShort_Reg(x86.PUSH_r, EAX);
2700 } else if (f.getName() == difference) {
2701 asm.emitShort_Reg(x86.POP_r, EAX);
2702 asm.emitARITH_Reg_Mem(x86.SUB_m_r32, EAX, 0, ESP);
2703 } else if (f.getName() == isNull) {
2704 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
2705 asm.emitShort_Reg(x86.POP_r, EAX);
2706 asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, 0);
2707 asm.emitCJUMP_Short(x86.JNE, (byte)0);
2708 int cloc = asm.getCurrentOffset();
2709 asm.emitShort_Reg(x86.INC_r32, ECX);
2710 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
2711 asm.emitShort_Reg(x86.PUSH_r, ECX);
2712 } else if (f.getName() == addressOf || f.getName() == address32 ||
2713 f.getName() == asObject || f.getName() == asReferenceType ||
2714 f.getName() == to32BitValue) {
2715 asm.emit1(x86.NOP);
2716 } else if (f.getName() == stringRep) {
2717 jq_Class k = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("Ljwutil/strings/Strings;");
2718 jq_StaticMethod sm = k.getOrCreateStaticMethod("hex8", "(I)Ljava/lang/String;");
2719 emitCallRelative(sm);
2720 asm.emitShort_Reg(x86.PUSH_r, EAX);
2721 } else if (f.getName() == getNull || f.getName() == min) {
2722 asm.emitPUSH_i(0);
2723 } else if (f.getName() == max) {
2724 asm.emitPUSH_i(Integer.MAX_VALUE);
2725 } else if (f.getName() == size) {
2726 asm.emitPUSH_i(4);
2727 } else if (f.getName() == logSize) {
2728 asm.emitPUSH_i(2);
2729 } else if (f.getName() == pageAlign) {
2730 asm.emitPUSH_i(12);
2731 } else if (f.getName() == getBasePointer) {
2732 asm.emitShort_Reg(x86.PUSH_r, EBP);
2733 } else if (f.getName() == getStackPointer) {
2734 asm.emitShort_Reg(x86.PUSH_r, ESP);
2735 } else if (f.getName() == alloca) {
2736 asm.emit2_Mem(x86.NEG_m32, 0, ESP);
2737 asm.emitShort_Reg(x86.POP_r, EAX);
2738 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, ESP);
2739 asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EAX);
2740 asm.emitShort_Reg(x86.PUSH_r, EAX);
2741 } else if (f.getName() == atomicAdd) {
2742 asm.emitShort_Reg(x86.POP_r, EBX);
2743 asm.emitShort_Reg(x86.POP_r, EAX);
2744 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
2745 asm.emitARITH_Reg_Mem(x86.ADD_m_r32, EBX, 0, EAX);
2746 } else if (f.getName() == atomicSub) {
2747 asm.emitShort_Reg(x86.POP_r, EBX);
2748 asm.emitShort_Reg(x86.POP_r, EAX);
2749 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
2750 asm.emitARITH_Reg_Mem(x86.SUB_m_r32, EBX, 0, EAX);
2751 } else if (f.getName() == atomicCas4) {
2752 asm.emitShort_Reg(x86.POP_r, EBX);
2753 asm.emitShort_Reg(x86.POP_r, EAX);
2754 asm.emitShort_Reg(x86.POP_r, ECX);
2755 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
2756 asm.emit3_Reg_Mem(x86.CMPXCHG_32, EBX, 0, ECX);
2757 asm.emitShort_Reg(x86.PUSH_r, EAX);
2758 } else if (f.getName() == atomicCas8) {
2759
2760 asm.emitShort_Reg(x86.POP_r, EBX);
2761 asm.emitShort_Reg(x86.POP_r, ECX);
2762 asm.emitShort_Reg(x86.POP_r, EAX);
2763 asm.emitShort_Reg(x86.POP_r, EDX);
2764 asm.emitShort_Reg(x86.POP_r, EDI);
2765 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
2766 asm.emit3_Reg_Mem(x86.CMPXCHG8B, EAX, 0, EDI);
2767 asm.emitShort_Reg(x86.PUSH_r, EDX);
2768 asm.emitShort_Reg(x86.PUSH_r, EAX);
2769 } else if (f.getName() == atomicAnd) {
2770 asm.emitShort_Reg(x86.POP_r, EBX);
2771 asm.emitShort_Reg(x86.POP_r, EAX);
2772 if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
2773 asm.emitARITH_Reg_Mem(x86.AND_m_r32, EBX, 0, EAX);
2774 } else if (f.getName() == Utf8.get("<init>")) {
2775 INVOKEhelper(INVOKE_SPECIAL, f);
2776 } else {
2777 Assert.UNREACHABLE(f.toString());
2778 }
2779 }
2780
2781 private void gen_unsafe(jq_Method f) {
2782 if (TraceBytecodes) {
2783 emitPushAddressOf(SystemInterface.toCString(i_start+": UNSAFE "+f));
2784 emitCallMemory(SystemInterface._debugwriteln);
2785 }
2786 if ((f == Unsafe._floatToIntBits) || (f == Unsafe._intBitsToFloat) ||
2787 (f == Unsafe._doubleToLongBits) || (f == Unsafe._longBitsToDouble)) {
2788 asm.emit1(x86.NOP);
2789
2790
2791
2792
2793
2794
2795 } else if (f == Unsafe._popFP32) {
2796 asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
2797 asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
2798 } else if (f == Unsafe._popFP64) {
2799 asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
2800 asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
2801 } else if (f == Unsafe._pushFP32) {
2802 asm.emit2_Mem(x86.FLD_m32, 0, ESP);
2803 asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
2804 } else if (f == Unsafe._pushFP64) {
2805 asm.emit2_Mem(x86.FLD_m64, 0, ESP);
2806 asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
2807 } else if (f == Unsafe._EAX) {
2808 asm.emitShort_Reg(x86.PUSH_r, EAX);
2809 } else if ((f == Unsafe._pushArg) || (f == Unsafe._pushArgA)) {
2810 asm.emit1(x86.NOP);
2811 } else if (f == Unsafe._invoke) {
2812 asm.emitShort_Reg(x86.POP_r, EAX);
2813 asm.emit2_Reg(x86.CALL_r, EAX);
2814 asm.emitShort_Reg(x86.PUSH_r, EDX);
2815 asm.emitShort_Reg(x86.PUSH_r, EAX);
2816 } else if (f == Unsafe._invokeA) {
2817 asm.emitShort_Reg(x86.POP_r, EAX);
2818 asm.emit2_Reg(x86.CALL_r, EAX);
2819 asm.emitShort_Reg(x86.PUSH_r, EAX);
2820 } else if (f == Unsafe._getThreadBlock) {
2821 asm.emitprefix(THREAD_BLOCK_PREFIX);
2822 asm.emit2_Mem(x86.PUSH_m, THREAD_BLOCK_OFFSET);
2823 } else if (f == Unsafe._setThreadBlock) {
2824 asm.emitprefix(THREAD_BLOCK_PREFIX);
2825 asm.emit2_Mem(x86.POP_m, THREAD_BLOCK_OFFSET);
2826 } else if (f == Unsafe._longJump) {
2827 asm.emitShort_Reg(x86.POP_r, EAX);
2828 asm.emitShort_Reg(x86.POP_r, EBX);
2829 asm.emitShort_Reg(x86.POP_r, EBP);
2830 asm.emitShort_Reg(x86.POP_r, ECX);
2831 asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EBX);
2832 asm.emit2_Reg(x86.JMP_r, ECX);
2833 } else if (f == Unsafe._isEQ) {
2834 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
2835 asm.emitCJUMP_Short(x86.JNE, (byte)0);
2836 int cloc = asm.getCurrentOffset();
2837 asm.emitShort_Reg(x86.INC_r32, ECX);
2838 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
2839 asm.emitShort_Reg(x86.PUSH_r, ECX);
2840 } else if (f == Unsafe._isGE) {
2841 asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
2842 asm.emitCJUMP_Short(x86.JL, (byte)0);
2843 int cloc = asm.getCurrentOffset();
2844 asm.emitShort_Reg(x86.INC_r32, ECX);
2845 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
2846 asm.emitShort_Reg(x86.PUSH_r, ECX);
2847 } else {
2848 System.err.println(f.toString());
2849 Assert.UNREACHABLE();
2850 }
2851 }
2852
2853 }