📄 sparcjitcodegen.java
字号:
break; case Opcode.INT2BYTE: code.ST ("%l0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LDSB ("%fp", 3 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%l0"); break; case Opcode.INT2CHAR: code.ST ("%l0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LDUH ("%fp", 2 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%l0"); break; case Opcode.INT2SHORT: code.ST ("%l0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LDSH ("%fp", 2 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%l0"); break; /* long operands: %l2 -> %l0 */ case Opcode.LNEG: code.SUBcc ("%g0", "%l3", "%l1"); code.SUBX ("%g0", "%l2", "%l0"); break; case Opcode.L2I: code.MOV ("%l3", "%l0"); break; case Opcode.L2F: case Opcode.L2D: code.MOV ("%l2", "%o0"); code.MOV ("%l3", "%o1"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr ((Opcode.L2F == i.opcode.code) ? FID_long2f : FID_long2d)); code.NOP (); break; /* Float operands: %f2 -> %f0 */ case Opcode.FNEG: code.FNEGs ("%f2", "%f0"); break; case Opcode.F2I: code.FsTOi ("%f2", "%f0"); code.FpushES ("%f0"); donestore = true; break; case Opcode.F2L: code.FsTOd ("%f2", "%f0"); code.STDF ("%f0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o0"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o1"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_dtol)); code.NOP (); code.LpushES ("%o0"); donestore = true; break; case Opcode.F2D: code.FsTOd ("%f2", "%f0"); break; /* Double operands: %f2 -> %f0 */ case Opcode.DNEG: code.FNEGs ("%f2", "%f0"); code.FMOVs ("%f3", "%f1"); break; case Opcode.D2I: code.FdTOi ("%f2", "%f0"); code.FpushES ("%f0"); donestore = true; break; case Opcode.D2F: code.FdTOs ("%f2", "%f0"); break; case Opcode.D2L: code.STDF ("%f2", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o0"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o1"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_dtol)); code.NOP (); code.LpushES ("%o0"); donestore = true; break; default: throw new InternalError ("Unop code " + i.opcode + " not supported in JIT"); } /* Store the result back on the execution stack, unless we did it * already (e.g., for float-to-int conversions) */ if (! donestore) { if (opdtype.equals ("i")) { /* stack: %l0 -> val */ code.pushES ("%l0"); } else if (opdtype.equals ("f")) { /* stack: %f0 -> val */ code.FpushES ("%f0"); } else if (opdtype.equals ("xl")) { /* stack: %l0 -> val.w1 val.w2 */ code.LpushES ("%l0"); } else if (opdtype.equals ("xd")) { /* stack: %f0 -> val.w1 val.w2 */ code.DpushES ("%f0"); } else { throw new InternalError ("Bad type in binop."); } } return; } /** Emit code for a binary operation * @param i instruction for codegen */ private void EmitBinOp (Instr i) { String opdtype; // Type of operands of instruction opdtype = i.opcode.push; /* Load the operands into their registers. Fortunately, no * binary operators are cast operators, so the output and input * types are the same. Um, except for long shifts. */ if (opdtype.equals ("i")) { /* stack: op1 op2 -> %l0 %l1 */ code.popES ("%l1"); code.popES ("%l0"); } else if (opdtype.equals ("f")) { /* stack: op1 op2 -> %f2 %f3 */ code.FpopES ("%f3"); code.FpopES ("%f2"); } else if (opdtype.equals ("xl")) { if ((Opcode.LSHL == i.opcode.code) || (Opcode.LSHR == i.opcode.code) || (Opcode.LUSHR == i.opcode.code)) { /* stack: op1.w1 op1.w2 op2 -> %o0 %o2 */ /* We're going to call a function to do these, so pop * right into the outgoing args. */ code.popES ("%o2"); code.LpopES ("%o0"); } else { /* stack: op1.w1 op1.w2 op2.w1 op2.w2 -> %l2 %l4 */ code.LpopES ("%l4"); code.LpopES ("%l2"); } } else if (opdtype.equals ("xd")) { /* stack: op1.w1 op1.w2 op2.w1 op2.w2 -> %f2 %f4 */ code.DpopES ("%f4"); code.DpopES ("%f2"); } else { throw new InternalError ("Bad type in binop."); } /* Emit the code to operate on the results */ switch (i.opcode.code) { /* int operands: %l0 op %l1 -> %l0 */ case Opcode.IADD: code.ADD ("%l0", "%l1", "%l0"); break; case Opcode.ISUB: code.SUB ("%l0", "%l1", "%l0"); break; case Opcode.IMUL: code.SMUL ("%l0", "%l1", "%l0"); break; case Opcode.IREM: case Opcode.IDIV: /* We'll have to cheat until we get a v8 sparchitecture manual */ code.MOV ("%l0", "%o0"); code.MOV ("%l1", "%o1"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr ((Opcode.IREM == i.opcode.code) ? FID_intrem : FID_intdiv)); code.NOP (); code.MOV ("%o0", "%l0"); break; case Opcode.IAND: code.AND ("%l0", "%l1", "%l0"); break; case Opcode.IOR: code.OR ("%l0", "%l1", "%l0"); break; case Opcode.IXOR: code.XOR ("%l0", "%l1", "%l0"); break; case Opcode.ISHL: code.SLL ("%l0", "%l1", "%l0"); break; case Opcode.ISHR: code.SRA ("%l0", "%l1", "%l0"); break; case Opcode.IUSHR: code.SRL ("%l0", "%l1", "%l0"); break; /* long operands: %l2 op %l4 -> %l0 */ case Opcode.LADD: code.ADDcc ("%l3", "%l5", "%l1"); code.ADDX ("%l2", "%l4", "%l0"); break; case Opcode.LSUB: code.SUBcc ("%l3", "%l5", "%l1"); code.SUBX ("%l2", "%l4", "%l0"); break; case Opcode.LMUL: /* This is the sequence that gcc -mv8 -O3 uses. */ code.UMUL ("%l3", "%l5", "%l1"); code.RDY ("%l0"); code.SMUL ("%l3", "%l4", "%o7"); code.ADD ("%l0", "%o7", "%l0"); code.SMUL ("%l5", "%l2", "%l2"); code.ADD ("%l0", "%l2", "%l0"); break; case Opcode.LREM: case Opcode.LDIV: /* Everybody else does this with a function call; let's * do it that way too. */ code.MOV ("%l2", "%o0"); code.MOV ("%l3", "%o1"); code.MOV ("%l4", "%o2"); code.MOV ("%l5", "%o3"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr ((Opcode.LREM == i.opcode.code) ? FID_longrem : FID_longdiv)); code.NOP (); code.MOV ("%o0", "%l0"); code.MOV ("%o1", "%l1"); break; case Opcode.LAND: code.AND ("%l2", "%l4", "%l0"); code.AND ("%l3", "%l5", "%l1"); break; case Opcode.LOR: code.OR ("%l2", "%l4", "%l0"); code.OR ("%l3", "%l5", "%l1"); break; case Opcode.LXOR: code.XOR ("%l2", "%l4", "%l0"); code.XOR ("%l3", "%l5", "%l1"); break; case Opcode.LSHL: case Opcode.LSHR: case Opcode.LUSHR: /* Already have op1 and op2 into %o0, %o1, %o2, so put in * the operator type, and call the function. */ code.MOV (i.opcode.code, "%o3"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_longshift)); code.NOP (); /* Move result back into local registers */ code.MOV ("%o0", "%l0"); code.MOV ("%o1", "%l1"); break; /* Float operands: %f2 op %f3 -> %f0 */ case Opcode.FADD: code.FADDs ("%f2", "%f3", "%f0"); break; case Opcode.FSUB: code.FSUBs ("%f2", "%f3", "%f0"); break; case Opcode.FMUL: code.FMULs ("%f2", "%f3", "%f0"); break; case Opcode.FDIV: /*!! UNFINISHED -- check for divbyzero !!*/ code.FDIVs ("%f2", "%f3", "%f0"); break; case Opcode.FREM: /*!! UNFINISHED -- is this correct? !!*/ /* Convert from single to double precision, and call * the remdr function in toba */ code.FsTOd ("%f2", "%f0"); code.FsTOd ("%f3", "%f2"); code.STDF ("%f0", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o0"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o1"); code.STDF ("%f2", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o2"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o3"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_remdr)); code.NOP (); code.FdTOs ("%f0", "%f0"); break; /* Double operands: %f2 %f4 -> %f0 */ case Opcode.DADD: code.FADDd ("%f2", "%f4", "%f0"); break; case Opcode.DSUB: code.FSUBd ("%f2", "%f4", "%f0"); break; case Opcode.DMUL: code.FMULd ("%f2", "%f4", "%f0"); break; case Opcode.DDIV: /*!! UNFINISHED -- check for divbyzero !!*/ code.FDIVd ("%f2", "%f4", "%f0"); break; case Opcode.DREM: /* Call the remdr function in toba */ code.STDF ("%f2", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o0"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o1"); code.STDF ("%f4", "%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE)); code.LD ("%fp", - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o2"); code.LD ("%fp", 4 - (overheadSize + SPARC.ALUFPUXFERSIZE), "%o3"); code.reserveCode (CodeBlock.brACALL, i, "noreg", getFuncAddr (FID_remdr)); code.NOP (); break; default: throw new InternalError ("Binop code " + i.opcode + " not supported in JIT"); } /* Store the result back on the execution stack */ if (opdtype.equals ("i")) { /* stack: %l0 -> val */ code.pushES ("%l0"); } else if (opdtype.equals ("f")) { /* stack: %f0 -> val */ code.FpushES ("%f0"); } else if (opdtype.equals ("xl")) { /* stack: %l0 -> val.w1 val.w2 */ code.LpushES ("%l0"); } else if (opdtype.equals ("xd")) { /* stack: %f0 -> val.w1 val.w2 */ code.DpushES ("%f0"); } else { throw new InternalError ("Bad type in binop."); } return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -