View Javadoc

1   // x86ReferenceCompiler.java, created Mon Feb  5 23:23:21 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
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          // we are using x86, so initialize the register state factory.
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 /*final*/ boolean ALWAYS_TRACE = false;
85      public static /*final*/ boolean TRACE_STUBS = false;
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;   // Assembler to output to.
129     private int n_paramwords;   // number of words used by incoming parameters.
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()); // hi
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()); // lo
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()); // lo
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()); // hi
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         // return generated code
234         return asm.getCodeBuffer().allocateCodeBlock(null, null, null, null, 0, code_relocs, data_relocs);
235     }
236     
237     // Generate code for the given method.
238     public final jq_CompiledCode compile() {
239         if (TRACE) System.out.println("x86 Reference Compiler: compiling "+method);
240         
241         // temporary kludge: no switching a thread during compilation.
242         if (jq.RunningNative)
243             Unsafe.getThreadBlock().disableThreadSwitch();
244         
245         try {
246             // initialize stuff
247             asm = new x86Assembler(bcs.length, bcs.length*8, 5, DEFAULT_ALIGNMENT);
248             asm.skip(5); // space for jump point
249             asm.setEntrypoint();
250             n_paramwords = method.getParamWords();
251             int n_localwords = method.getMaxLocals();
252             Assert._assert(n_paramwords <= n_localwords);
253             
254             // stack frame before prolog:
255             // b0: FP->| caller's saved FP  |
256             // ac:     | caller's locals    |
257             //         |        ...         |
258             // 94:     | caller's opstack   |
259             //         |        ...         |
260             // 80:     | pushed params      |
261             //         |        ...         |
262             // 74: SP->| ret addr in caller |
263             
264             // emit prolog
265             asm.emitShort_Reg(x86.PUSH_r, EBP);         // push old FP
266             asm.emit2_Reg_Reg(x86.MOV_r_r32, EBP, ESP); // set new FP
267             if (n_paramwords != n_localwords)
268                 asm.emit2_Reg_Mem(x86.LEA, ESP, (n_paramwords-n_localwords)<<2, ESP);
269             
270             // stack frame after prolog:
271             // b0:     | caller's saved FP  |
272             // ac:     | caller's locals    |
273             //         |        ...         |
274             // 94:     | caller's opstack   |
275             //         |        ...         |
276             // 80:     | pushed params      |
277             //         |        ...         |
278             // 74:     | ret addr in caller |
279             // 70: FP->| callee's FP (b0)   |
280             // 6c:     | callee's locals    |
281             //     SP->|        ...         |
282             // 50:     | callee's opstack   |
283             //         |        ...         |
284     
285             // print a debug message
286             if (TraceMethods) {
287                 emitPushAddressOf(SystemInterface.toCString("Entering: "+method));
288                 emitCallMemory(SystemInterface._debugwriteln);
289             }
290             /*
291             if (TraceArguments) {
292                 for (int i=0,j=0; i<params.length; ++i,++j) {
293                     emitPushAddressOf(SystemInterface.toCString("Arg"+i+" type "+params[i]+": "));
294                     emitCallMemory(SystemInterface._debugwriteln);
295                     asm.emit2_Mem(x86.PUSH_m, getLocalOffset(j), EBP);
296                     if (params[i] == jq_Primitive.LONG) {
297                         asm.emit2_Mem(x86.PUSH_m, getLocalOffset(++j), EBP);
298                         emitCallRelative(jq._hex16);
299                     } else if (params[i] == jq_Primitive.DOUBLE) {
300                         asm.emit2_Mem(x86.PUSH_m, getLocalOffset(++j), EBP);
301                         emitCallRelative(Strings._hex16);
302                     } else {
303                         emitCallRelative(Strings._hex8);
304                     }
305                 }
306             }
307              */
308             
309             // add a sentinel value to the bottom of the opstack
310             asm.emitPUSH_i(0x0000d00d);
311             
312             // add monitorenter for synchronized methods.
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                     // lock the java.lang.Class object
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                     // lock the this pointer
329                     asm.emit2_Mem(x86.PUSH_m, getLocalOffset(0), EBP);
330                 }
331                 emitCallRelative(Monitor._monitorenter);
332             }
333             
334             // generate code for each bytecode in order
335             this.forwardTraversal();
336     
337             // record the end of the code as a branch target --- it may
338             // be referenced by an exception handler.
339             Integer loc = new Integer(bcs.length);
340             asm.recordBranchTarget(loc);
341     
342             // generate exception table
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             // generate bytecode map
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             // return generated code
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             // temporary kludge: no switching a thread during compilation.
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         // do dispatch
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)); // hi
429         asm.emitPUSH_i((int)c);       // lo
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)); // hi
447         asm.emitPUSH_i((int)v);       // lo
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);   // hi
464         asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i+1), EBP); // lo
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);   // hi
481         asm.emit2_Mem(x86.PUSH_m, getLocalOffset(i+1), EBP); // lo
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); // lo
506         asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);   // hi
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); // lo
523         asm.emit2_Mem(x86.POP_m, getLocalOffset(i), EBP);   // hi
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);   // array index
535         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // array index
542         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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); // hi
546         asm.emit2_Mem(x86.PUSH_m, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET  ); // lo
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);   // array index
595         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // array index
608         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // array index
621         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // value
629         asm.emitShort_Reg(x86.POP_r, EBX);   // array index
630         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // value
638         asm.emitShort_Reg(x86.POP_r, EBX);   // array index
639         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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);   // lo value
646         asm.emitShort_Reg(x86.POP_r, EDX);   // hi value
647         asm.emitShort_Reg(x86.POP_r, EBX);   // array index
648         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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  ); // lo
652         asm.emit2_Reg_Mem(x86.MOV_m_r32, EDX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4); // hi
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         // call arraystorecheck
693         asm.emit2_Mem(x86.PUSH_m, 0, ESP);  // push value
694         asm.emit2_Mem(x86.PUSH_m, 12, ESP);  // push arrayref
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);   // value
705         asm.emitShort_Reg(x86.POP_r, EBX);   // array index
706         asm.emitShort_Reg(x86.POP_r, EAX);   // array ref
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); // a-b
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); // lo
892                 asm.emitShort_Reg(x86.POP_r, EBX); // hi
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); // lo
898                 asm.emitShort_Reg(x86.POP_r, EBX); // hi
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); // lo1
904                 asm.emitShort_Reg(x86.POP_r, ECX); // hi1
905                 asm.emitShort_Reg(x86.POP_r, ESI); // lo2
906                 asm.emitShort_Reg(x86.POP_r, EDI); // hi2
907                 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI); // hi2
908                 asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, ECX); // hi1 | hi2
909                 asm.emitCJUMP_Short(x86.JNE, (byte)0);
910                 int cloc = asm.getCurrentOffset();
911                 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI); // lo2
912                 asm.emit2_Reg(x86.MUL_rda_r32, EBX); // lo1*lo2
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); // lo2
917                 asm.emit2_Reg(x86.MUL_rda_r32, ECX); // hi1*lo2
918                 asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EAX); // hi1*lo2
919                 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI); // hi2
920                 asm.emit2_Reg(x86.MUL_rda_r32, EBX); // hi2*lo1
921                 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, ECX, EAX); // hi2*lo1 + hi1*lo2
922                 asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI); // lo2
923                 asm.emit2_Reg(x86.MUL_rda_r32, EBX); // lo1*lo2
924                 asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EDX, ECX); // hi2*lo1 + hi1*lo2 + hi(lo1*lo2)
925                 asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
926                 asm.emitShort_Reg(x86.PUSH_r, EDX); // res_hi
927                 asm.emitShort_Reg(x86.PUSH_r, EAX); // res_lo
928                 break;
929             case BINOP_DIV:
930                 emitCallRelative(MathSupport._ldiv);
931                 asm.emitShort_Reg(x86.PUSH_r, EDX); // hi
932                 asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
933                 break;
934             case BINOP_REM:
935                 emitCallRelative(MathSupport._lrem);
936                 asm.emitShort_Reg(x86.PUSH_r, EDX); // hi
937                 asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
938                 break;
939             case BINOP_AND:
940                 asm.emitShort_Reg(x86.POP_r, EAX); // lo
941                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // lo
947                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // lo
953                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // reverse because pushing on fp stack
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);  // hi
1064         asm.emit2_Mem(x86.NEG_m32, 0, ESP);  // lo
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); // lo
1121                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // hi
1136                 asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
1137                 break;
1138             }
1139             case SHIFT_RIGHT: {
1140                 asm.emitShort_Reg(x86.POP_r, ECX);
1141                 asm.emitShort_Reg(x86.POP_r, EAX); // lo
1142                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // hi
1157                 asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
1158                 break;
1159             }
1160             case SHIFT_URIGHT: {
1161                 asm.emitShort_Reg(x86.POP_r, ECX);
1162                 asm.emitShort_Reg(x86.POP_r, EAX); // lo
1163                 asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // hi
1178                 asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
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); // lo
1200         asm.emit1(x86.CWD);
1201         asm.emitShort_Reg(x86.PUSH_r, EDX); // hi
1202         asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
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); // lo
1230         asm.emitShort_Reg(x86.POP_r, ECX); // hi
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         // check for NaN
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         // check for >=MAX_INT
1259         asm.emitCJUMP_Short(x86.JBE, (byte)0);
1260         int cloc2 = asm.getCurrentOffset();
1261         // check for <=MIN_INT
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         // default case
1267         asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1268         {   // set rounding mode to round-towards-zero
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             // restore fpu control word
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         // NaN -> 0
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         // >=MAX_INT -> MAX_INT
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         // <=MIN_INT -> MIN_INT
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         // check for NaN
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         // check for >=MAX_LONG
1309         asm.emitCJUMP_Short(x86.JBE, (byte)0);
1310         int cloc2 = asm.getCurrentOffset();
1311         // check for <=MIN_LONG
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         // default case
1317         asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1318         {   // set rounding mode to round-towards-zero
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             // restore fpu control word
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         // NaN -> 0
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         // >=MAX_LONG -> MAX_LONG
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         // <=MIN_LONG -> MIN_LONG
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); // lo
1450         asm.emitShort_Reg(x86.POP_r, ECX); // hi
1451         asm.emitShort_Reg(x86.POP_r, EAX); // lo
1452         asm.emitShort_Reg(x86.POP_r, EDX); // hi
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); // reverse order
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); // reverse order
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         // val from table + abs position in table
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             // lock the java.lang.Class object
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             // lock the this pointer
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         // epilogue
1711         asm.emitShort_Reg(x86.POP_r, EAX); // store return value
1712         asm.emit1(x86.LEAVE);              // esp<-ebp, pop ebp
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         // epilogue
1722         asm.emitShort_Reg(x86.POP_r, EAX); // return value lo
1723         asm.emitShort_Reg(x86.POP_r, EDX); // return value hi
1724         asm.emit1(x86.LEAVE);              // esp<-ebp, pop ebp
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);              // esp<-ebp, pop ebp
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             // generate a runtime call, which will be backpatched.
1790             asm.startDynamicPatch(10); // 6
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         // todo: register backpatched reference
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             // generate a runtime call, which will be backpatched.
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         // todo: register backpatched reference
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             // generate a runtime call, which will be backpatched.
1885             asm.startDynamicPatch(10); // 6
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         // todo: register backpatched reference
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             // generate a runtime call, which will be backpatched.
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         // todo: register backpatched reference
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             // generate a runtime call, which will be backpatched.
1976             if (TraceBytecodes) {
1977                 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD1 "+f+" (dynpatch)"));
1978                 emitCallMemory(SystemInterface._debugwriteln);
1979             }
1980             asm.startDynamicPatch(10); // 9
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); // obj ref
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             // generate a runtime call, which will be backpatched.
2007             if (TraceBytecodes) {
2008                 emitPushAddressOf(SystemInterface.toCString(i_start+": GETFIELD4 "+f+" (dynpatch)"));
2009                 emitCallMemory(SystemInterface._debugwriteln);
2010             }
2011             asm.startDynamicPatch(10); // 7
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); // obj ref
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             // generate a runtime call, which will be backpatched.
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); // obj ref
2050             asm.emit2_Mem(x86.PUSH_m, f.getOffset()+4, EAX); // hi
2051             asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);   // lo
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             // generate a runtime call, which will be backpatched.
2096             asm.startDynamicPatch(10); // 9
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); // obj ref
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             // generate a runtime call, which will be backpatched.
2128             asm.startDynamicPatch(10); // 9
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); // obj ref
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             // generate a runtime call, which will be backpatched.
2163             asm.startDynamicPatch(10); // 8
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             // field has already been resolved.
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             // generate a runtime call, which will be backpatched.
2194             asm.startDynamicPatch(10); // 9
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             // field has already been resolved.
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             // generate a runtime call, which will be backpatched.
2226             asm.startDynamicPatch(10); // 8
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             // field has already been resolved.
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             // generate a runtime call, which will be backpatched.
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             // field has already been resolved.
2267             asm.emitShort_Reg(x86.POP_r, EBX); // lo
2268             asm.emitShort_Reg(x86.POP_r, EAX); // hi
2269             asm.emitShort_Reg(x86.POP_r, EDX);
2270             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset()  , EDX); // lo
2271             asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, f.getOffset()+4, EDX); // hi
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; // 5
2329                 dpatchentry = x86ReferenceLinker._invokestatic;
2330                 break;
2331             case INVOKE_SPECIAL:
2332                 dpatchsize = 11; // 5
2333                 dpatchentry = x86ReferenceLinker._invokespecial;
2334                 break;
2335             case INVOKE_INTERFACE:
2336                 // fallthrough
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         // generate a runtime call, which will be backpatched.
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); // 7
2379                 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, ObjectLayout.VTABLE_OFFSET, EAX); // 3
2380                 asm.emit2_Mem(x86.CALL_m, m_off, EBX); // 6
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                 //jq.Assert(!jq.RunningNative || f.getDeclaringClass().isInterface());
2392                 emitPushAddressOf(f);
2393                 emitCallRelative(x86ReferenceLinker._invokeinterface);
2394                 // need to pop args ourselves.
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                 // fallthrough
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); // hi
2452         asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
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); // hi
2479         asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
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         // initialize type now, to avoid backpatch.
2527         // TODO: maybe we want to support delaying initialization.
2528         if (!jq.RunningNative) {
2529             //jq.Assert(jq.boot_types.contains(f), f.toString());
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         // pop dim args, because the callee doesn't do it.
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); // address
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); // address
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); // address
2663             asm.emit2_Mem(x86.PUSH_m, 0, EAX);
2664         } else if (f.getName() == peek8) {
2665             asm.emitShort_Reg(x86.POP_r, EAX); // address
2666             asm.emit2_Mem(x86.PUSH_m, 4, EAX); // hi
2667             asm.emit2_Mem(x86.PUSH_m, 0, EAX); // lo
2668         } else if (f.getName() == poke1) {
2669             asm.emitShort_Reg(x86.POP_r, EBX); // value
2670             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // value
2674             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // value
2679             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // lo
2683             asm.emitShort_Reg(x86.POP_r, ECX); // hi
2684             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // shift
2692             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // a-b
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); // value
2743             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // value
2748             asm.emitShort_Reg(x86.POP_r, EAX); // address
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); // after
2753             asm.emitShort_Reg(x86.POP_r, EAX); // before
2754             asm.emitShort_Reg(x86.POP_r, ECX); // address
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             // untested.
2760             asm.emitShort_Reg(x86.POP_r, EBX); // lo after
2761             asm.emitShort_Reg(x86.POP_r, ECX); // hi after
2762             asm.emitShort_Reg(x86.POP_r, EAX); // lo before
2763             asm.emitShort_Reg(x86.POP_r, EDX); // hi before
2764             asm.emitShort_Reg(x86.POP_r, EDI); // address
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); // hi result
2768             asm.emitShort_Reg(x86.PUSH_r, EAX); // lo result
2769         } else if (f.getName() == atomicAnd) {
2770             asm.emitShort_Reg(x86.POP_r, EBX); // value
2771             asm.emitShort_Reg(x86.POP_r, EAX); // address
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         } else if (f == Unsafe._getTypeOf) {
2791             asm.emitShort_Reg(x86.POP_r, EAX);
2792             asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, VTABLE_OFFSET, EAX);
2793             asm.emit2_Mem(x86.PUSH_m, 0, EBX);
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); // hi
2815             asm.emitShort_Reg(x86.PUSH_r, EAX); // lo
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); // lo
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); // eax
2828             asm.emitShort_Reg(x86.POP_r, EBX); // sp
2829             asm.emitShort_Reg(x86.POP_r, EBP); // fp
2830             asm.emitShort_Reg(x86.POP_r, ECX); // ip
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 }