📄 intel86jitcodegen.java
字号:
an += 2; } else { /* Copy over a single word */ code.PUSH (new MemoryRef (new Immediate (code.peekEStackOffs (an)), R_ebp)); naw--; an++; } } /* Update the estack pointer based on what we pushed */ code.tossES (an);// System.out.println ("Set " + an + " arg words from " + sig); /* Return the number of bytes we pushed. */ return 4*an; } private void emitBackJumpCall (Instr ci) { long bjfn; int boffs; /* Get the address of the function we call on back edges. If there * is none, just return. */ bjfn = FA_backjumpfn; if (0 == bjfn) { return; } /* If we're running with scout thread preemption, see if the * time slice is over. */ boffs = -1; if (useScoutThreadPreemption) { code.MOV (FMA_timeSliceEnd, R_eax); code.CMP (R_eax, FMA_timeNow); code.Jccn (Intel86.CND_b, IMM_0); boffs = code.nextByteOffs (); } code.reserveCode (CodeBlock.brACALL, ci, null, bjfn); if (0 <= boffs) { code.PatchNearJump (boffs, code.nextByteOffs () - boffs); } } /** If the source is past the destination, this is a backedge, and we * insert a call to some routine that needs to be called regularly. * E.g., a thread yield function on a non-preemptive thread system. * NB: This may trash registers %eax, %ecx, and flags. */ private void checkBackJump (Instr ci, // Current instruction int src, // Where we are now (label, addr, ??) int dst) // Where we're jumping to (label, addr, ??) { if (src > dst) { emitBackJumpCall (ci); } return; } /** Pull object off stack and make sure it's not a null pointer. * After this, the object reference is in the specified register. * @param i how far back down stack to look, zero is top elt * @param treg what register to put object reference into * @param npeCode indicate what NullPointerException argument to throw */ private void checkObjectRef (int i, Register treg, Instr ins) { /* Load the value from the JVM stack */ code.peekES (i, treg); /* Compare it to zero */ code.OR (treg, treg); /* If not zero, jump next few instructions */ code.Jccn (Intel86.CND_nz, IMM_0); int boffs = code.nextByteOffs (); /* Call throwNullPointerException (0) */ code.PUSH (IMM_0); code.reserveCode (CodeBlock.brACALL, ins, null, FA_throwNPE); /* No need to pop args; we never return here. */ code.UNIMP (0); // sure about that? /* Here's where we end up if we were nz */ code.PatchNearJump (boffs, code.nextByteOffs() - boffs); return; } /** Emit code for an if_cmp/ifcond instruction, including the jumps. * @param i the instruction we're executing code for. * @param m the method i belongs to, for looking up target addresses */ private void EmitIfCmp (Instr i, // Instruction to codegen Method m) // Method info { int boffs; /* Operands are either one or two words. Pop what's necessary, * and set the condition codes to represent the status of the * condition variable. */ if (Opcode.IFZRO == i.opcode.kind) { code.popES (R_eax); code.OR (R_eax, R_eax); } else { // Better be IFCMP code.popES (R_ebx); code.popES (R_eax); // Subtracts source from dest code.CMP (R_ebx, R_eax); } /* Because we're jumping to a JVM offset, which may be in code * we haven't built yet, we need to generate a brJUMP-style * backpatch. Rather than make a backpatch type for each condition, * we invert the test result and jump around an unconditional * jump if the test failed. */ switch (i.opcode.code) { case Opcode.IF_ICMPEQ: case Opcode.IF_ACMPEQ: case Opcode.IFNULL: case Opcode.IFEQ: // Equality test: skip jump if not equal code.Jccn (Intel86.CND_ne, IMM_0); break; case Opcode.IF_ICMPNE: case Opcode.IF_ACMPNE: case Opcode.IFNE: case Opcode.IFNONNULL: // Inquality test: skip jump if equal code.Jccn (Intel86.CND_e, IMM_0); break; case Opcode.IF_ICMPLT: case Opcode.IFLT: code.Jccn (Intel86.CND_ge, IMM_0); break; case Opcode.IF_ICMPGT: case Opcode.IFGT: code.Jccn (Intel86.CND_le, IMM_0); break; case Opcode.IF_ICMPLE: case Opcode.IFLE: code.Jccn (Intel86.CND_g, IMM_0); break; case Opcode.IF_ICMPGE: case Opcode.IFGE: code.Jccn (Intel86.CND_l, IMM_0); break; } boffs = code.nextByteOffs ();// System.out.println ("Jump to pc " + i.val + " is label " + m.instrs[m.pcmap [i.val]].label); checkBackJump (i, i.pc, i.val); code.reserveCode (CodeBlock.brJUMP, i, null, m.instrs[m.pcmap [i.val]].label); code.PatchNearJump (boffs, (code.nextByteOffs () - boffs)); /* Continues here if OK */ } /** Emit code for a unary operation * @param i instruction for codegen */ private void EmitUnOp (Instr i) { String opdtype; // Type of operands of instruction boolean donestore; int boffs; int boffs2; opdtype = i.opcode.push; /* Load the operand into its registers. Boy it'd be cool if the * operand input type was available, but all we have is the * output type, and there be cast operations here. */ switch (i.opcode.code) { case Opcode.INEG: case Opcode.I2L: case Opcode.I2F: case Opcode.I2D: case Opcode.INT2BYTE: case Opcode.INT2CHAR: case Opcode.INT2SHORT: /* stack: op1 -> %eax */ code.popES (R_eax); break; case Opcode.FNEG: case Opcode.F2D: case Opcode.F2I: case Opcode.F2L: /* stack: op1 -> %ST(0) */ code.FpopES (); break; case Opcode.LNEG: case Opcode.L2I: case Opcode.L2F: case Opcode.L2D: /* stack: op1.w1 op1.w2 -> %l2 */ code.LpopES (R_edx, R_eax); break; case Opcode.DNEG: case Opcode.D2F: case Opcode.D2I: case Opcode.D2L: /* stack: op1.w1 op1.w2 -> ST(0) */ code.DpopES (); break;; default: throw new InternalError ("Bad opcode in unop." + i); } /* Emit the code to operate on the results */ donestore = false; switch (i.opcode.code) { /* int operands: %eax -> %eax */ case Opcode.INEG: code.NEG (R_eax); break; case Opcode.I2L: code.CWD (); break; case Opcode.I2F: case Opcode.I2D: code.SUB (IMM_8, R_esp); code.MOV (R_eax, MR_esp); code.FILD (MR_esp); code.ADD (IMM_8, R_esp); break; case Opcode.INT2BYTE: code.AND (new Immediate (0xFF, 1, false), R_eax); // Now, sign-extend back to an int code.PrefixOPSIZE (); code.CBW (); code.CBW (); break; case Opcode.INT2CHAR: code.AND (new Immediate (0xFFFF), R_eax); // Don't sign extend this: char is unsigned break; case Opcode.INT2SHORT: code.AND (new Immediate (0xFFFF), R_eax); // Now, sign-extend back to an int code.CBW (); break; /* long operands: %edx:%eax -> %edx:%eax */ case Opcode.LNEG: code.NEG (R_eax); code.ADC (IMM_0, R_edx); code.NEG (R_edx); break; case Opcode.L2I: // Don't have to do anything break; case Opcode.L2F: case Opcode.L2D: code.PUSH (R_edx); code.PUSH (R_eax); code.FILD (new MemoryRef (R_esp).setRefSize (8)); code.ADD (IMM_8, R_esp); break; /* Float operands: %f2 -> %f0 */ case Opcode.FNEG: code.FCHS (); break; case Opcode.D2I: case Opcode.F2I: case Opcode.D2L: case Opcode.F2L://NaNsup /* First, let's go hunting for special cases. See whether//NaNsup * the value is NaN. *///NaNsup code.FTST ();//NaNsup code.FNSTSW ();//NaNsup code.SHR (IMM_8, R_eax);//NaNsup code.AND (new Immediate (0x45), "%al");//NaNsup code.CMP (new Immediate (0x45), "%al");//NaNsup code.Jccn (Intel86.CND_ne, IMM_0);//NaNsup boffs = code.nextByteOffs ();//NaNsup /* Is a NaN. Result is should be zero. *///NaNsup code.XOR (R_eax, R_eax);//NaNsup if ((Opcode.D2L == i.opcode.code) ||//NaNsup (Opcode.F2L == i.opcode.code)) {//NaNsup code.XOR (R_edx, R_edx);//NaNsup }//NaNsup code.JMPn (IMM_0);//NaNsup boffs2 = code.nextByteOffs ();//NaNsup code.PatchNearJump (boffs, (boffs2 - boffs)); /* Yes, we really do reset the FPU control word every time * we do a cast. So do gcc-generated casts to ints. */ code.SUB (new Immediate (12), R_esp); code.FNSTCW (new MemoryRef (IMM_8, R_esp).setRefSize (2)); code.MOV (new MemoryRef (IMM_8, R_esp), R_edx); /* Bits 12 and 11 of the 16-bit control word are the rounding * control field. Normally 00 (round-to-nearest), we want * it to be 11 (round-to-zero). GCC wipes out the other * flags in that byte, so we'll presume that's OK to do. */ /* Note that, for foo-to-int, we allocate one more word * of stack space than necessary; that eliminates the * need to duplicate this sequence. */ code.MOV (new Immediate (0x0C), R_dh); code.MOV (R_edx, MR_esp); code.FLDCW (new MemoryRef (R_esp).setRefSize (2)); /* This generates the wrong answer for NaN and values above * MAX_VALUE; for those, it stores the integer indefinite * value which is MIN_VALUE. We'd have to special-case to * fix that. */ if ((Opcode.F2L == i.opcode.code) || (Opcode.D2L == i.opcode.code)) { code.FISTP (new MemoryRef (R_esp).setRefSize (8)); } else { code.FISTP (new MemoryRef (R_esp).setRefSize (4)); } code.FLDCW (new MemoryRef (IMM_8, R_esp).setRefSize (2)); code.POP (R_eax); // lsw code.POP (R_edx); // msw, if long code.POP (R_ebx); // throwaway//NaNsup // End up here after special-case handling *///NaNsup code.PatchNearJump (boffs2, (code.nextByteOffs () - boffs2));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -