📄 intel86.j4
字号:
/** * Implementation of CodeBlock for Intel Architecture systems * @version $Id: Intel86.j4,v 1.6 1999/01/05 18:43:30 pab Exp $ * @author Peter A. Bigot * * DO NOT MODIFY THIS FILE. It is generated from $RCSFile$ automatically * by a macro preprocessor. */dnl This is the M4-source for $RCSFile$. It's ok to edit this one./* This is part of the Just-In-Time compiler for the Toba system. */package toba.jit;/* We need the basic Toba runtime data structures, and the classfile * structures. */import java.io.*;import toba.classfile.*;import toba.runtime.*;classIntel86extends CodeBlock{ private void BasicInit () { setBVlength (8); setLittleEndian (true); setCheckWordAlign (false); setJumpFromNextInstr (true); } public Intel86 (Method m, int imax) { super (m, imax); BasicInit (); } public Intel86 (Method m) { super (m); BasicInit (); } /** Activation record layout for JIT-compiled Intel86 code * * | | * |-------------------------------| * | incoming call parameter ... | * |-------------------------------| * | incoming call parameter 1 | * |-------------------------------| * | incoming call parameter 0 | * |-------------------------------| <- %ebp+8 * | return address | * |-------------------------------| <- %ebp+4 ; incoming %esp * | saved %ebp | * %ebp->|-------------------------------| * | callee saved regs (si,di,bx) | * |-------------------------------|\ <- %ebp-overheadOffs * | sync method instance object | | * |-------------------------------| | * | struct mythread * tdata | | * |-------------------------------| > Local data structures required * | void * oldbuf | | for handling of exceptions. * |-------------------------------| | Block is absent from frames * | volatile int pcormheld | | that don't need it. Size * |-------------------------------| | overheadSize is kept in the * | jmpbuf newbuf (non-const len)| | JITCodeGen instance. * |-------------------------------|-/ <- %ebp-overheadOffs-overheadSize * | JVM evaluation stack top | (conceptually at LV(-1)) * |-------------------------------| * | JVM local variables | * |-------------------------------| * | JVM evaluation stack | * |-------------------------------| <- %ebp - LVBase = initial %esp * %esp->| X86 eval stack | * |-------------------------------| * * Don't mix the JVM and X86 stacks; there are cases where we need * to pretend to drop things off the JVMstack in case a called * function throws an exception, but we still need them for a little * while if it doesn't. * * The integer eStackBase in this module is set to the (positive) * distance from %ebp of the JVM estack; the value eStackCurTop * is set at the start of code generation for an JVM instruction, * and indicates the offset from %ebp to the top of the evaluation * at the start of the instruction. It is modified herein by the * push/popES routines. This eliminates the need for runtime maintenance * of the evaluation stack pointer. */ static final int AR_RIP_SIZE = 4; static final int AR_EBP_SIZE = 4; static final int AR_ESI_SIZE = 4; static final int AR_EDI_SIZE = 4; static final int AR_EBX_SIZE = 4; /* Pseudo-enumeration to describe the type of an operand: constant, * register, memory reference, or missing */ private static final int OT_imm = 1; private static final int OT_reg = 2; private static final int OT_mem = 3; private static final int OT_fpstack = 4; private static final int OT_absent = 5; private static void emitByteArray (byte rv[]) { int i; for (i = 0; i < rv.length; i++) { int bv = 0xFF & rv [i]; if (0x10 > bv) { System.out.print ("0" + Integer.toHexString (0xFF & rv [i]) + " "); } else { System.out.print (Integer.toHexString (0xFF & rv [i]) + " "); } if (15 == (i % 16)) { System.out.println (); } } if (0 != (i % 16)) { System.out.println (); } return; } protected static int CND_o = 0x00; protected static int CND_no = 0x01; protected static int CND_b = 0x02; protected static int CND_nae = CND_b; protected static int CND_nb = 0x03; protected static int CND_ae = CND_nb; protected static int CND_e = 0x04; protected static int CND_z = CND_e; protected static int CND_ne = 0x05; protected static int CND_nz = CND_ne; protected static int CND_be = 0x06; protected static int CND_na = CND_be; protected static int CND_nbe = 0x07; protected static int CND_a = CND_nbe; protected static int CND_s = 0x08; protected static int CND_ns = 0x09; protected static int CND_p = 0x0a; protected static int CND_pe = CND_p; protected static int CND_np = 0x0b; protected static int CND_po = CND_np; protected static int CND_l = 0x0c; protected static int CND_nge = CND_l; protected static int CND_nl = 0x0d; protected static int CND_ge = CND_nl; protected static int CND_le = 0x0e; protected static int CND_ng = CND_le; protected static int CND_nle = 0x0f; protected static int CND_g = CND_nle; /* Set this once: it's the positive offset, in bytes, from %ebp, to * the top of the JVM evaluation stack. */ private int eStackBase; protected int setEStackBase (int esb) { int ov = eStackBase; eStackBase = esb; return ov; } /* Relative offset (add to %ebp) of the current top-of-stack */ private int eStackOffs; /** Set the current top-of-stack to be so-many words down the JVM * evaluation stack. */ protected void setEStackTop (int nw) { int ov = eStackOffs; eStackOffs = - (eStackBase + 4 * nw); return; } public int getEStackDepth () { return (eStackOffs + eStackBase) / -4; } /** Create a memory-style operand string refering to offs bytes from * %ebp. */ private MemoryRef relBPop (int offs) { return new MemoryRef (new Immediate (offs), Register.R_ebp); } /* We're going to push something. Return the offset from %ebp where the * value should go, and update the stack pointer */ protected int pushEStackOffs () { eStackOffs -= 4; return eStackOffs; } protected int popEStackOffs () { eStackOffs += 4; return eStackOffs - 4; } protected int tossEStackOffs (int nw) { eStackOffs += 4 * nw; return eStackOffs; } protected int peekEStackOffs (int nw) { return eStackOffs + 4 * nw; } /** Look at a string and determine what kind of operand it represents. * @param s String representation of operand * @returns int OT_type for type of operand */ private static int OpType (Object s) // String operand { char c; /* Missing operands tagged as "absent" */ if (null == s) { return OT_absent; } if (s instanceof Register) { Register r = (Register) s; return (r.isFPReg ()) ? OT_fpstack : OT_reg; } if (s instanceof MemoryRef) { return OT_mem; } if (s instanceof Immediate) { return OT_imm; } /* Anything else is bogus. */ throw new InternalError ("x86: Invalid operand: " + s); } /** Return true iff the integer value fits in an 8-bit byte. * @param v value of integer * @returns boolean true if in range for 8bit entity */ private static boolean fitsin8bit (int v) { return ((-128 <= v) && (v <= 127)); } /** Build a mod/rm sequence: this is the mod/rm byte, the sib (if present), * and the displacement. * @param src Source operand * @param dst Dest operand * @returns byte[] Array of bytes encoding instruction */ private byte [] makeModRM (Object src, // Source register, immediate, memory, null Object dst) // Destination register, memory { int sot; // Optype of src int dot; // Optype of dst byte rv []; // Instruction byte sequence int rvs; // Number of bytes in rv so far int mod; // "mod" field of ModR/M byte int reg; // "reg" field of ModR/M byte int rm; // "r/m" field of ModR/M byte int sibv; // value of sibv; -1 if not present boolean emitdisp; // If true, emit a displacement int dispv; // value of displacement boolean smdisp; // If true, emit 8bit displacement // ModR/M + SIB + 32-bit displ rv = new byte [1 + 1 + 4]; rvs = 0; /* Initialize src/dst type information */ sot = OpType (src); dot = OpType (dst); /* Operations with memory source and register dest need to * swap source and dest, and set the direction bit, because * memory operands can only be placed in the r/m field * of the Mod-R/M byte, which with direction=0 specifies the * destination operand. */ if ((OT_mem == sot) && (OT_reg == dot)) { int xot = sot; sot = dot; dot = xot; Object tmp = src; src = dst; dst = tmp; } /* If the destination type is memory (only one that can be memory), * parse it. Set the smdisp flag to indicate whether the displacement * value fits in an 8-bit immediate. Compute the SIB byte value, * if appropriate. */ sibv = -1; emitdisp = false; dispv = 0; smdisp = true; mod = 0x03; // assume OT_reg for dst reg = 0x00; // reg component is 0 unless specified rm = 0x00; // r/m is 0 unless specified if (OT_mem == dot) { int sibd; // Encoded memory component structure int sf; // Scale factor encoding bits in SIB int i; // General index String illegal; // If set, indicates why operation is illegal MemoryRef mdst; // MemoryRef reference to destination operand /* Assume no problems with component interactions */ illegal = null; /* Simplify life by referring to this through its natural class. */ mdst = (MemoryRef) dst; /* Extract disp. Emit if it's nonzero; emit small if possible */ dispv = mdst.getDisplacement (); emitdisp = (0 != dispv); smdisp = fitsin8bit (dispv); /* Assume this is a pure base-only format. */ mod = 0x00; if (emitdisp) { /* Not base-only; use 8 or 32bit displacement version */ mod = (smdisp ? 0x01 : 0x02); } /* Compute the integer value of the scale bits in the SIB */ sf = mdst.getScaleBits (); /* Encode the operand components into a 4-bit integer, so we can * pick what type of operand this is and compute the necessary * SIB and other fields. */ sibd = ((((1 != mdst.getScaleFactor()) ? 1 : 0) << 3) | (((null != mdst.getIndexReg()) ? 1 : 0) << 2) | (((null != mdst.getBaseReg()) ? 1 : 0) << 1) | (((0 != dispv) ? 1 : 0) << 0)); /* What to do to encode the operand is highly nontrivial. Rather * than try to optimize common cases, or combine common settings, * we just deal with each separately. The modrm file contains * the analysis on which the switches are based. */ switch (sibd) {/*# Id: modrm,v 1.2 1997/08/16 18:00:14 pab Exp # ModR/M and SIB definition for memory operandsscale: 0 iff (1 == scale)index: 0 iff (undefined index)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -