⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i386-gen.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 2 页
字号:
               ind + 1, R_386_32);        oad(0xb8, 0); /* mov %eax, xxx */        sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);        greloc(cur_text_section, sym,                ind + 1, R_386_PC32);        oad(0xe8, -4);        o(0x585a); /* restore returned value, if any */    }#endif    o(0xc9); /* leave */    if (func_ret_sub == 0) {        o(0xc3); /* ret */    } else {        o(0xc2); /* ret n */        g(func_ret_sub);        g(func_ret_sub >> 8);    }    /* align local size to word & save local variables */    *(int *)(cur_text_section->data + func_sub_sp_offset) = (-loc + 3) & -4; }/* generate a jump to a label */int gjmp(int t){    return psym(0xe9, t);}/* generate a jump to a fixed address */void gjmp_addr(int a){    int r;    r = a - ind - 2;    if (r == (char)r) {        g(0xeb);        g(r);    } else {        oad(0xe9, a - ind - 5);    }}/* generate a test. set 'inv' to invert test. Stack entry is popped */int gtst(int inv, int t){    int v, *p;    v = vtop->r & VT_VALMASK;    if (v == VT_CMP) {        /* fast case : can jump directly since flags are set */        g(0x0f);        t = psym((vtop->c.i - 16) ^ inv, t);    } else if (v == VT_JMP || v == VT_JMPI) {        /* && or || optimization */        if ((v & 1) == inv) {            /* insert vtop->c jump list in t */            p = &vtop->c.i;            while (*p != 0)                p = (int *)(cur_text_section->data + *p);            *p = t;            t = vtop->c.i;        } else {            t = gjmp(t);            gsym(vtop->c.i);        }    } else {        if (is_float(vtop->type.t)) {            vpushi(0);            gen_op(TOK_NE);        }        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {            /* constant jmp optimization */            if ((vtop->c.i != 0) != inv)                 t = gjmp(t);        } else {            v = gv(RC_INT);            o(0x85);            o(0xc0 + v * 9);            g(0x0f);            t = psym(0x85 ^ inv, t);        }    }    vtop--;    return t;}/* generate an integer binary operation */void gen_opi(int op){    int r, fr, opc, c;    switch(op) {    case '+':    case TOK_ADDC1: /* add with carry generation */        opc = 0;    gen_op8:        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {            /* constant case */            vswap();            r = gv(RC_INT);            vswap();            c = vtop->c.i;            if (c == (char)c) {                /* XXX: generate inc and dec for smaller code ? */                o(0x83);                o(0xc0 | (opc << 3) | r);                g(c);            } else {                o(0x81);                oad(0xc0 | (opc << 3) | r, c);            }        } else {            gv2(RC_INT, RC_INT);            r = vtop[-1].r;            fr = vtop[0].r;            o((opc << 3) | 0x01);            o(0xc0 + r + fr * 8);         }        vtop--;        if (op >= TOK_ULT && op <= TOK_GT) {            vtop->r = VT_CMP;            vtop->c.i = op;        }        break;    case '-':    case TOK_SUBC1: /* sub with carry generation */        opc = 5;        goto gen_op8;    case TOK_ADDC2: /* add with carry use */        opc = 2;        goto gen_op8;    case TOK_SUBC2: /* sub with carry use */        opc = 3;        goto gen_op8;    case '&':        opc = 4;        goto gen_op8;    case '^':        opc = 6;        goto gen_op8;    case '|':        opc = 1;        goto gen_op8;    case '*':        gv2(RC_INT, RC_INT);        r = vtop[-1].r;        fr = vtop[0].r;        vtop--;        o(0xaf0f); /* imul fr, r */        o(0xc0 + fr + r * 8);        break;    case TOK_SHL:        opc = 4;        goto gen_shift;    case TOK_SHR:        opc = 5;        goto gen_shift;    case TOK_SAR:        opc = 7;    gen_shift:        opc = 0xc0 | (opc << 3);        if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {            /* constant case */            vswap();            r = gv(RC_INT);            vswap();            c = vtop->c.i & 0x1f;            o(0xc1); /* shl/shr/sar $xxx, r */            o(opc | r);            g(c);        } else {            /* we generate the shift in ecx */            gv2(RC_INT, RC_ECX);            r = vtop[-1].r;            o(0xd3); /* shl/shr/sar %cl, r */            o(opc | r);        }        vtop--;        break;    case '/':    case TOK_UDIV:    case TOK_PDIV:    case '%':    case TOK_UMOD:    case TOK_UMULL:        /* first operand must be in eax */        /* XXX: need better constraint for second operand */        gv2(RC_EAX, RC_ECX);        r = vtop[-1].r;        fr = vtop[0].r;        vtop--;        save_reg(TREG_EDX);        if (op == TOK_UMULL) {            o(0xf7); /* mul fr */            o(0xe0 + fr);            vtop->r2 = TREG_EDX;            r = TREG_EAX;        } else {            if (op == TOK_UDIV || op == TOK_UMOD) {                o(0xf7d231); /* xor %edx, %edx, div fr, %eax */                o(0xf0 + fr);            } else {                o(0xf799); /* cltd, idiv fr, %eax */                o(0xf8 + fr);            }            if (op == '%' || op == TOK_UMOD)                r = TREG_EDX;            else                r = TREG_EAX;        }        vtop->r = r;        break;    default:        opc = 7;        goto gen_op8;    }}/* generate a floating point operation 'v = t1 op t2' instruction. The   two operands are guaranted to have the same floating point type *//* XXX: need to use ST1 too */void gen_opf(int op){    int a, ft, fc, swapped, r;    /* convert constants to memory references */    if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {        vswap();        gv(RC_FLOAT);        vswap();    }    if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)        gv(RC_FLOAT);    /* must put at least one value in the floating point register */    if ((vtop[-1].r & VT_LVAL) &&        (vtop[0].r & VT_LVAL)) {        vswap();        gv(RC_FLOAT);        vswap();    }    swapped = 0;    /* swap the stack if needed so that t1 is the register and t2 is       the memory reference */    if (vtop[-1].r & VT_LVAL) {        vswap();        swapped = 1;    }    if (op >= TOK_ULT && op <= TOK_GT) {        /* load on stack second operand */        load(TREG_ST0, vtop);        save_reg(TREG_EAX); /* eax is used by FP comparison code */        if (op == TOK_GE || op == TOK_GT)            swapped = !swapped;        else if (op == TOK_EQ || op == TOK_NE)            swapped = 0;        if (swapped)            o(0xc9d9); /* fxch %st(1) */        o(0xe9da); /* fucompp */        o(0xe0df); /* fnstsw %ax */        if (op == TOK_EQ) {            o(0x45e480); /* and $0x45, %ah */            o(0x40fC80); /* cmp $0x40, %ah */        } else if (op == TOK_NE) {            o(0x45e480); /* and $0x45, %ah */            o(0x40f480); /* xor $0x40, %ah */            op = TOK_NE;        } else if (op == TOK_GE || op == TOK_LE) {            o(0x05c4f6); /* test $0x05, %ah */            op = TOK_EQ;        } else {            o(0x45c4f6); /* test $0x45, %ah */            op = TOK_EQ;        }        vtop--;        vtop->r = VT_CMP;        vtop->c.i = op;    } else {        /* no memory reference possible for long double operations */        if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {            load(TREG_ST0, vtop);            swapped = !swapped;        }                switch(op) {        default:        case '+':            a = 0;            break;        case '-':            a = 4;            if (swapped)                a++;            break;        case '*':            a = 1;            break;        case '/':            a = 6;            if (swapped)                a++;            break;        }        ft = vtop->type.t;        fc = vtop->c.ul;        if ((ft & VT_BTYPE) == VT_LDOUBLE) {            o(0xde); /* fxxxp %st, %st(1) */            o(0xc1 + (a << 3));        } else {            /* if saved lvalue, then we must reload it */            r = vtop->r;            if ((r & VT_VALMASK) == VT_LLOCAL) {                SValue v1;                r = get_reg(RC_INT);                v1.type.t = VT_INT;                v1.r = VT_LOCAL | VT_LVAL;                v1.c.ul = fc;                load(r, &v1);                fc = 0;            }            if ((ft & VT_BTYPE) == VT_DOUBLE)                o(0xdc);            else                o(0xd8);            gen_modrm(a, r, vtop->sym, fc);        }        vtop--;    }}/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'   and 'long long' cases. */void gen_cvt_itof(int t){    save_reg(TREG_ST0);    gv(RC_INT);    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {        /* signed long long to float/double/long double (unsigned case           is handled generically) */        o(0x50 + vtop->r2); /* push r2 */        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */        o(0x242cdf); /* fildll (%esp) */        o(0x08c483); /* add $8, %esp */    } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==                (VT_INT | VT_UNSIGNED)) {        /* unsigned int to float/double/long double */        o(0x6a); /* push $0 */        g(0x00);        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */        o(0x242cdf); /* fildll (%esp) */        o(0x08c483); /* add $8, %esp */    } else {        /* int to float/double/long double */        o(0x50 + (vtop->r & VT_VALMASK)); /* push r */        o(0x2404db); /* fildl (%esp) */        o(0x04c483); /* add $4, %esp */    }    vtop->r = TREG_ST0;}/* convert fp to int 't' type *//* XXX: handle long long case */void gen_cvt_ftoi(int t){    int r, r2, size;    Sym *sym;    CType ushort_type;    ushort_type.t = VT_SHORT | VT_UNSIGNED;    gv(RC_FLOAT);    if (t != VT_INT)        size = 8;    else         size = 4;        o(0x2dd9); /* ldcw xxx */    sym = external_global_sym(TOK___tcc_int_fpu_control,                               &ushort_type, VT_LVAL);    greloc(cur_text_section, sym,            ind, R_386_32);    gen_le32(0);        oad(0xec81, size); /* sub $xxx, %esp */    if (size == 4)        o(0x1cdb); /* fistpl */    else        o(0x3cdf); /* fistpll */    o(0x24);    o(0x2dd9); /* ldcw xxx */    sym = external_global_sym(TOK___tcc_fpu_control,                               &ushort_type, VT_LVAL);    greloc(cur_text_section, sym,            ind, R_386_32);    gen_le32(0);    r = get_reg(RC_INT);    o(0x58 + r); /* pop r */    if (size == 8) {        if (t == VT_LLONG) {            vtop->r = r; /* mark reg as used */            r2 = get_reg(RC_INT);            o(0x58 + r2); /* pop r2 */            vtop->r2 = r2;        } else {            o(0x04c483); /* add $4, %esp */        }    }    vtop->r = r;}/* convert from one floating point type to another */void gen_cvt_ftof(int t){    /* all we have to do on i386 is to put the float in a register */    gv(RC_FLOAT);}/* computed goto support */void ggoto(void){    gcall_or_jmp(1);    vtop--;}/* bound check support functions */#ifdef CONFIG_TCC_BCHECK/* generate a bounded pointer addition */void gen_bounded_ptr_add(void){    Sym *sym;    /* prepare fast i386 function call (args in eax and edx) */    gv2(RC_EAX, RC_EDX);    /* save all temporary registers */    vtop -= 2;    save_regs(0);    /* do a fast function call */    sym = external_global_sym(TOK___bound_ptr_add, &func_old_type, 0);    greloc(cur_text_section, sym,            ind + 1, R_386_PC32);    oad(0xe8, -4);    /* returned pointer is in eax */    vtop++;    vtop->r = TREG_EAX | VT_BOUNDED;    /* address of bounding function call point */    vtop->c.ul = (cur_text_section->reloc->data_offset - sizeof(Elf32_Rel)); }/* patch pointer addition in vtop so that pointer dereferencing is   also tested */void gen_bounded_ptr_deref(void){    int func;    int size, align;    Elf32_Rel *rel;    Sym *sym;    size = 0;    /* XXX: put that code in generic part of tcc */    if (!is_float(vtop->type.t)) {        if (vtop->r & VT_LVAL_BYTE)            size = 1;        else if (vtop->r & VT_LVAL_SHORT)            size = 2;    }    if (!size)        size = type_size(&vtop->type, &align);    switch(size) {    case  1: func = TOK___bound_ptr_indir1; break;    case  2: func = TOK___bound_ptr_indir2; break;    case  4: func = TOK___bound_ptr_indir4; break;    case  8: func = TOK___bound_ptr_indir8; break;    case 12: func = TOK___bound_ptr_indir12; break;    case 16: func = TOK___bound_ptr_indir16; break;    default:        error("unhandled size when derefencing bounded pointer");        func = 0;        break;    }    /* patch relocation */    /* XXX: find a better solution ? */    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);    sym = external_global_sym(func, &func_old_type, 0);    if (!sym->c)        put_extern_sym(sym, NULL, 0, 0);    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));}#endif/* end of X86 code generator *//*************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -