📄 sparcjitcodegen.java
字号:
/* Sanity checks: frame size must be double-word aligned, and * must fit in a signed 13-bit immediate (for the version of * SAVE we're using) */ if (0 != (frame_size % 8)) { throw new InternalError ("frame size not multiple of 8"); } if (4096 <= frame_size) { throw new InternalError ("can't handle frame sizes exceeding 2^12-1"); } /* Create a new AR of the right size. */ code.SAVE ("%sp", -frame_size, "%sp"); /* Stuff the name of this function in the standard location. */ i = (int)getStringAddress (m.cl.name + "." + m.fl.name); code.SETHI (i, "%o0"); code.SetLo (i, "%o0"); code.ST ("%o0", "%fp", excOheadOffs [ARLV_methname]);// code.PUSH (excOheadAddr (ARLV_methname));// code.reserveCode (CodeBlock.brACALL, m.instrs[0], null, getFuncAddr (FID_puts));// code.ADD (new Immediate (2), R_esp); /* If we're creating a standard frame for executing Java code, then * store the arguments into the local variable arena. If not, * whoever's creating us should take responsibility for preserving * arguments. */ if (0 > ndata) { /* Figure out how many arguments we need to save. Add one * for the object reference of instance methods. */ aw = Instr.argwords (m.fl.signature); if (0 == (m.fl.access & ClassData.ACC_STATIC)) { aw++; } for (i = 0; i < aw; i++) { if (6 > i) { /* Already in %ii. */ code.ST ("%i" + i, "%fp", LVOffs (i)); } else { /* In caller's activation record. Copy from there into * local variables. */ code.LD ("%fp", SPARC.ARGPUSH + (i-6) * 4, "%o7"); code.ST ("%o7", "%fp", LVOffs (i)); } } /* Initialize the register we use for the evaluation stack pointer. * Not useful for non-standard frames. */ code.ADD ("%fp", LVOffs (m.max_locals), "%l7"); } return; } /** Generate code to initialize a class if necessary, leaving the class * reference in %o0. * @param i the instruction that induced the initialization requirement * @param or the reference to the object (FieldRef or ClassRef) that may need to be initialized */ private void emitClassInit (Instr i, Object or) { int boffs; /* Load the address of the native struct class object that is the * basis of the object referred to by fr. Put it into %o0 so * it's ready to be used as a parameter to the initializer. */ code.reserveCode (CodeBlock.brLOADNatCl, i, "%o0", or); /* The first word of the class object is the flag indicating * whether it needs to be initialized. If that's zero, the class * has been initialized, and we skip over the call to the * initializer.*/ code.LD ("%o0", 0, "%o7"); code.CMP ("%o7", 0); boffs = code.nextByteOffs (); code.BE (0); code.NOP (); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_initclass)); code.NOP (); code.PatchDisp22 (boffs, (code.nextByteOffs() - boffs) >>> 2); } /** Pop arguments off evaluation stack and put into outgoing SPARC registers. * @param na number of argument words to pop * @param abase start as if from the abase'th output argument */ private void setCallArgs (int na, int abase) { /* Don't do anything if there are no words to pop */ if (0 >= na) { return; } /* Copy the values off the evaluation stack into the proper location */ for (int a = 1; a <= na; a++) { int ai; /* Get which argument this is in the actual call. */ ai = abase + (a - 1); if (6 > ai) { /* First six values go into ALU output registers 0 through 5 */ code.peekES (na-a, "%o"+ai); } else { /* Remainder go into the outoing parameter dump area in this * function's AR */ code.peekES (na-a, "%o7"); code.ST ("%o7", "%sp", 4*(ai-6) + SPARC.ARGPUSH); } } /* Update the evaluation stack pointer to pop the arguments all * at once. */ code.tossES (na); return; } /** Pull elements off stack and prepare to use them as the first args to * a function call. * @param na number of elements to use as arguments */ private void setCallArgs (int na) { setCallArgs (na, 0); } /** 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. */ 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) { /* If this is a jump backwards, get the address of the function * we call on back edges, and call it if it exists. */ long bjfn = getFuncAddr (FID_backjumpfn); if (0 != bjfn) { code.reserveCode (CodeBlock.brACALL, ci, null, bjfn); } } return; } /** Pull object off stack and make sure it's not a null pointer. * After this, the object reference is in treg. * @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, String treg, Instr ins) { /* Load the value from the execution stack */ code.peekES (i, treg); /* Compare it to zero */ code.CMP (treg, 0); /* If nonzero, jump over the next two instructions */ int boffs = code.nextByteOffs (); code.BNE (0); code.NOP (); // fill delay slot /* Call throwNullPointerException (0) */ code.MOV (0, "%o0"); code.reserveCode (CodeBlock.brACALL, ins, "noreg", getFuncAddr (FID_throwNPE)); code.NOP (); // fill delay slot // Here's where we continue code.PatchDisp22 (boffs, (code.nextByteOffs() - boffs) >>> 2); 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 ("%l0"); code.CMP ("%l0", 0); } else { // Better be IFCMP code.popES ("%l1"); code.popES ("%l0"); code.CMP ("%l0", "%l1"); } /* 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. That's not supported for conditional jumps, so * for test X, we do "if !X goto afterjump; jump T; afterjump..." */ boffs = code.nextByteOffs (); 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.BNE (0); code.NOP (); break; case Opcode.IF_ICMPNE: case Opcode.IF_ACMPNE: case Opcode.IFNE: case Opcode.IFNONNULL: // Inquality test: skip jump if equal code.BE (0); code.NOP (); break; case Opcode.IF_ICMPLT: case Opcode.IFLT: code.BGE (0); code.NOP (); break; case Opcode.IF_ICMPGT: case Opcode.IFGT: code.BLE (0); code.NOP (); break; case Opcode.IF_ICMPLE: case Opcode.IFLE: code.BG (0); code.NOP (); break; case Opcode.IF_ICMPGE: case Opcode.IFGE: code.BL (0); code.NOP (); break; }// 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, "noreg", m.instrs[m.pcmap [i.val]].label); code.NOP (); // fill delay slot /* Continues here if OK */ code.PatchDisp22 (boffs, (code.nextByteOffs() - boffs) >>> 2); } /** 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; 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 -> %l0 */ code.popES ("%l0"); break; case Opcode.FNEG: case Opcode.F2D: case Opcode.F2I: case Opcode.F2L: /* stack: op1 -> %f2 */ code.FpopES ("%f2"); break; case Opcode.LNEG: case Opcode.L2I: case Opcode.L2F: case Opcode.L2D: /* stack: op1.w1 op1.w2 -> %l2 */ code.LpopES ("%l2"); break; case Opcode.DNEG: case Opcode.D2F: case Opcode.D2I: case Opcode.D2L: /* stack: op1.w1 op1.w2 -> %f2 */ code.DpopES ("%f2"); break;; default: throw new InternalError ("Bad opcode in binop." + i); } /* Emit the code to operate on the results */ donestore = false; switch (i.opcode.code) { /* int operands: %l0 -> %l0 */ case Opcode.INEG: code.SUB ("%g0", "%l0", "%l0"); break; case Opcode.I2L: code.MOV ("%l0", "%l1"); code.SRA ("%l0", 31, "%l0"); break; case Opcode.I2F: case Opcode.I2D: code.ST ("%l0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LDF ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%f2"); if (Opcode.I2F == i.opcode.code) { code.FiTOs ("%f2", "%f0"); } else { code.FiTOd ("%f2", "%f0"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -