📄 gexpr386.c
字号:
//-------------------------------------------------------------------------
int isshort(ENODE *node)
/*
* return true if the node passed can be generated as a short
* offset.
*/
{
return (isintconst(node->nodetype) && (node->v.i >= - 32768L && node->v.i
<= 32767L));
}
//-------------------------------------------------------------------------
int isbyte(ENODE *node)
/*
* return true if the node passed can be evaluated as a byte
* offset.
*/
{
return isintconst(node->nodetype) && ( - 128 <= node->v.i && node->v.i <=
127);
}
//-------------------------------------------------------------------------
static int depth(ENODE *node)
{
int a, b;
if (!node)
return 0;
switch (node->nodetype)
{
case en_structret:
return 0;
case en_cl_reg:
return depth(node->v.p[0]);
case en_cfi:
case en_cfc:
case en_cri:
case en_crc:
case en_clri:
case en_clrc:
case en_cl:
case en_cul:
case en_ci:
case en_cui:
case en_cp:
case en_cfp:
case en_csp:
case en_cbool:
case en_cub:
case en_cb:
case en_cuw:
case en_cw:
case en_cd:
case en_cld:
case en_cf:
case en_cll:
case en_cull:
case en_bits:
case en_ll_ref:
case en_ull_ref:
case en_l_ref:
case en_ul_ref:
case en_a_ref:
case en_ua_ref:
case en_i_ref:
case en_ui_ref:
case en_ub_ref:
case en_bool_ref:
case en_b_ref:
case en_fp_ref:
case en_uw_ref:
case en_w_ref:
case en_longdoubleref:
case en_doubleref:
case en_floatref:
case en_fimaginaryref:
case en_rimaginaryref:
case en_lrimaginaryref:
case en_fcomplexref:
case en_rcomplexref:
case en_lrcomplexref:
case en_substack:
return 1+depth(node->v.p[0]);
case en_uminus:
case en_moveblock:
case en_stackblock:
case en_clearblock:
return 1+depth(node->v.p[0]);
case en_fimaginarycon:
case en_rimaginarycon:
case en_lrimaginarycon:
case en_fcomplexcon:
case en_rcomplexcon:
case en_lrcomplexcon:
case en_llcon:
case en_llucon:
case en_icon:
case en_lcon:
case en_lucon:
case en_iucon:
case en_boolcon:
case en_ccon:
case en_cucon:
case en_rcon:
case en_lrcon:
case en_fcon:
case en_absacon:
case en_trapcall:
case en_labcon:
case en_nacon:
case en_autocon:
case en_autoreg:
case en_napccon:
case en_nalabcon:
case en_tempref:
case en_regref:
return 1;
case en_not:
case en_compl:
return 1+depth(node->v.p[0]);
case en_eq:
case en_ne:
case en_lt:
case en_le:
case en_gt:
case en_ge:
case en_ugt:
case en_uge:
case en_ult:
case en_ule:
case en_land:
case en_lor:
case en_div:
case en_udiv:
case en_pdiv:
case en_mod:
case en_umod:
case en_assign:
case en_refassign:
case en_lassign:
case en_asuminus:
case en_ascompl:
case en_add:
case en_sub:
case en_addstruc:
case en_umul:
case en_pmul:
case en_arrayindex:
case en_mul:
case en_and:
case en_or:
case en_xor:
case en_asalsh:
case en_asarsh:
case en_alsh:
case en_arsh:
case en_arshd:
case en_asarshd:
case en_lsh:
case en_rsh:
case en_asadd:
case en_assub:
case en_asmul:
case en_asdiv:
case en_asmod:
case en_asand:
case en_asumod:
case en_asudiv:
case en_asumul:
case en_asor:
case en_aslsh:
case en_asxor:
case en_asrsh:
case en_repcons:
case en_ainc:
case en_adec:
case en_array:
a = depth(node->v.p[0]);
b = depth(node->v.p[1]);
if (a > b)
return 1+a;
return 1+b;
case en_void:
case en_cond:
case en_voidnz:
case en_dvoid:
return 1+depth(node->v.p[1]);
case en_conslabel:
case en_destlabel:
case en_movebyref:
case en_addcast:
return depth(node->v.p[0]);
case en_sfcall:
case en_sfcallb:
case en_scallblock:
case en_pfcall:
case en_pfcallb:
case en_fcall:
case en_intcall:
case en_callblock:
case en_fcallb:
case en_pcallblock:
case en_thiscall:
return 1;
default:
DIAG("error in depth routine.");
return 1;
}
}
//-------------------------------------------------------------------------
void noids(AMODE *ap)
{
if (ap->mode == am_indispscale)
if (ap->length == BESZ_QWORD || ap->length == - BESZ_QWORD)
do_extend(ap, ap->length, F_AXDX);
else
do_extend(ap, ap->length, F_DREG | F_VOL);
}
//-------------------------------------------------------------------------
AMODE *indx_data(AMODE *ap)
{
// we have to go to all this work to prevent accidental pops
AMODE *ap3 = 0, ap4, ap5;
int preg, sreg;
memset(&ap4, 0, sizeof(ap4));
ap4.mode = am_none;
if (ap->mode != am_indispscale)
{
DIAG("indx_data: unscaled mode");
freeop(ap);
ap3 = temp_data();
}
else
{
if (ap->preg == - 1)
{
if (ap->sreg >= 3)
{
freeop(ap);
ap3 = temp_data();
}
else
{
ap3 = xalloc(sizeof(AMODE));
ap3->mode = am_dreg;
ap3->preg = ap->sreg;
}
}
else
{
if (ap->preg >= 3)
{
if (ap->sreg >= 3)
{
freeop(ap);
ap3 = temp_data();
}
else
{
ap3 = xalloc(sizeof(AMODE));
ap3->mode = am_dreg;
ap3->preg = ap->sreg;
}
}
else
{
ap3 = xalloc(sizeof(AMODE));
ap3->mode = am_dreg;
ap3->preg = ap->preg;
ap4.mode = am_dreg;
ap4.preg = ap->sreg;
}
}
}
ap3->length = BESZ_DWORD ;
gen_codes(op_lea, BESZ_DWORD , ap3, ap);
ap3->seg = ap->seg;
freeop(&ap4);
ap3->mode = am_indisp;
ap3->offset = makeintnode(en_icon, 0);
return ap3;
}
//-------------------------------------------------------------------------
AMODE *doindex(ENODE *node, enum e_node type)
{
AMODE *ap, *ap3;
ENODE node2;
int scale;
switch (node->nodetype)
{
case en_icon:
ap = gen_expr(node, FALSE, TRUE, BESZ_DWORD );
break;
case en_lsh:
if ((scale = node->v.p[1]->v.i) < 4 && scale)
{
ap = gen_expr(node->v.p[0], FALSE, TRUE, BESZ_DWORD );
if (node->v.p[0]->nodetype == en_bits)
ap = bit_load(ap, node->v.p[0]);
if (ap->mode != am_immed)
do_extend(ap, BESZ_DWORD , F_DREG);
if (ap->mode == am_immed)
{
while (--scale)
ap->offset->v.i <<= 1;
}
else
{
do_extend(ap, BESZ_DWORD , 0);
ap->mode = am_indispscale;
ap->sreg = ap->preg;
ap->preg = - 1;
ap->scale = scale;
ap->offset = makeintnode(en_icon, 0);
}
break;
}
default:
node2.v.p[0] = node;
node2.nodetype = type;
ap = gen_deref(&node2, BESZ_DWORD );
switch (ap->mode)
{
default:
break;
case am_indispscale:
if (ap->sreg >= 0 && ap->preg >= 0)
{
ap = indx_data(ap);
}
}
break;
}
return ap;
}
//-------------------------------------------------------------------------
AMODE *gen_index(ENODE *node)
/*
* generate code to evaluate an index node (^+) and return
* the addressing mode of the result. This routine takes no
* flags since it always returns either am_ind or am_indx.
*/
{
AMODE *ap1, *ap2, *ap, *ap3;
ENODE node2;
int a = depth(node->v.p[1]) - depth(node->v.p[0]);
int nsize;
if (a <= 2)
{
ap1 = doindex(node->v.p[0], node->nodetype);
nsize = natural_size(node->v.p[1]);
if (nsize == BESZ_QWORD || nsize == - BESZ_QWORD)
aprtocx(ap1);
ap2 = doindex(node->v.p[1], node->nodetype);
}
else
{
ap2 = doindex(node->v.p[1], node->nodetype);
nsize = natural_size(node->v.p[0]);
if (nsize == BESZ_QWORD || nsize == - BESZ_QWORD)
aprtocx(ap2);
ap1 = doindex(node->v.p[0], node->nodetype);
}
switch (ap1->mode)
{
case am_dreg:
switch (ap2->mode)
{
case am_dreg:
do_extend(ap1, BESZ_DWORD , 0);
ap1->sreg = ap2->preg;
ap1->scale = 0;
ap1->mode = am_indispscale;
ap1->offset = makeintnode(en_icon, 0);
if (!ap1->seg)
ap1->seg = ap2->seg;
return ap1;
case am_immed:
case am_direct:
ap2->preg = ap1->preg;
ap2->mode = am_indisp;
if (!ap2->seg)
ap2->seg = ap1->seg;
return ap2;
case am_indisp:
ap2->sreg = ap2->preg;
ap2->preg = ap1->preg;
ap2->mode = am_indispscale;
ap2->offset = ap1->offset;
ap2->scale = 0;
if (!ap2->seg)
ap2->seg = ap1->seg;
return ap2;
case am_indispscale:
if (ap2->preg == - 1)
{
ap2->preg = ap1->preg;
if (!ap2->seg)
ap2->seg = ap1->seg;
return ap2;
}
ap = indx_data(ap2);
ap->sreg = ap1->preg;
ap->mode = am_indispscale;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -