📄 genexp.c
字号:
#include <stdio.h>
#include "genasm.h"
AddrMode *gen_exp(ExpNode *exp, int flag, int size)
{
AddrMode *res=NULL;
int lab0, lab1;
begin:
switch(exp->exptype)
{
case exp_void:
return NULL;
case exp_const:
if(exp->datatype->basic_type == bt_pointer
||exp->datatype->basic_type == bt_funcptr)
res = newImme(exp->val.addr.base, exp->val.addr.offset);
else
res = newImme(NULL, exp->val.i);
break;
case exp_label:
//function name and named label
res = newImme(exp->val.addr.base, exp->val.addr.offset);
if(flag&F_ADDR)
res ->mode = am_label;
return res;
case exp_aref:
if(exp->val.addr.base)
{
if(flag&F_ADDR)
return newDirect(exp->val.addr.base, exp->val.addr.offset);
else
res = newImme(exp->val.addr.base, exp->val.addr.offset);
}
else
{
AddrMode *tmp ;
res = newRelative(EBP, exp->val.addr.offset);
if(flag&F_ADDR)
return res;
tmp = temp_data();
gen_code(op_lea, 4, tmp, res);
res = tmp;
}
break;
case exp_vref:
if(exp->val.addr.base)
res = newDirect(exp->val.addr.base, exp->val.addr.offset);
else
res = newRelative(EBP, exp->val.addr.offset);
if(is_real(exp->datatype->basic_type))
res->size = exp->datatype->size;
break;
case exp_call:
res = gen_call(exp->val.opd[0], exp->val.opd[1]);
break;
case exp_assign:
res = gen_assign(exp->val.opd[0], exp->val.opd[1]);
break;
case exp_ptomem:
case exp_ntomem:
case exp_array:
res = gen_index(exp);
break;
case exp_ptr:
res = gen_ptr(exp->val.opd[1]);
break;
case exp_val:
res = gen_val(exp->val.opd[1]);
break;
case exp_uminus:
res = gen_unary(op_neg, exp->val.opd[1]);
break;
case exp_rvs:
res = gen_unary(op_not, exp->val.opd[1]);
break;
case exp_lnot:
case exp_land:
case exp_lor:
case exp_eq:
case exp_ueq:
case exp_gtr:
case exp_geq:
case exp_les:
case exp_leq:
lab0 = newlabelno++;
lab1 = newlabelno++;
falsejp(exp,lab0);
res = temp_data();
gen_code(op_mov, 4, res, newImme(NULL, 1));
gen_code(op_jmp, 4, newLabel(lab1), NULL);
gen_label(lab0);
gen_code(op_sub, 4, res, res);
gen_label(lab1);
break;
case exp_incr:
case exp_decr:
if(exp->val.opd[1])
res = gen_indecr(exp->exptype, exp->val.opd[1]);
else if(flag&F_NOVALUE)//opt
res = gen_indecr(exp->exptype, exp->val.opd[0]);
else
res = gen_indecr(-exp->exptype, exp->val.opd[0]);
break;
case exp_lsh:
res = gen_shift(op_sal, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_rsh:
res = gen_shift(op_sar, exp->val.opd[0], exp->val.opd[1]);
break;//????????????
case exp_mul:
res = gen_mul(op_imul, exp->val.opd[0], exp->val.opd[1], 0);
break;
case exp_div:
res = gen_mul(op_idiv, exp->val.opd[0], exp->val.opd[1], 0);
break;
case exp_mod:
res = gen_mul(op_idiv, exp->val.opd[0], exp->val.opd[1], 1);
break;
case exp_umul:
res = gen_mul(op_mul, exp->val.opd[0], exp->val.opd[1], 0);
break;
case exp_udiv:
res = gen_mul(op_div, exp->val.opd[0], exp->val.opd[1], 0);
break;
case exp_umod:
res = gen_mul(op_div, exp->val.opd[0], exp->val.opd[1], 1);
break;
case exp_and:
res = gen_binary(op_and, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_xor:
res = gen_binary(op_xor, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_or:
res = gen_binary(op_or, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_add:
res = gen_binary(op_add, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_sub:
res = gen_binary(op_sub, exp->val.opd[0], exp->val.opd[1]);
break;
case exp_trinary:
res = gen_trinary(exp);
break;
}
if(exp->next) //just for comma expression,
//the first few have no need to make_legal
{
exp=exp->next;
goto begin;
}
return make_legal(res, flag, size, is_unsigned(exp->datatype->basic_type));
}
//return the size of sp changed
int push_exp(struct _expnode *exp)
{
AddrMode *res;
int size,depth;
if(exp->datatype->array_vol)
size=depth=4;
else
{
size=exp->datatype->size;
depth=(size+3)&~3;
}
res= gen_exp(exp, F_ALL, exp->datatype->size);
if(size<=4)
{
res = make_legal(res, F_ALL, 4, is_unsigned(exp->datatype->basic_type));
gen_code(op_push, 4, res, NULL);
}
else
{
AddrMode *esp=newDreg(ESP);
gen_code(op_sub, 4, esp, newImme(0, depth));
esp->mode = am_relative;
block_move(esp, res, size);
}
freeregs(res);
return depth;
}
AddrMode *gen_call(
struct _expnode *func,
struct _expnode *arglist)
{
int depth=0;
AddrMode *funcaddr, *res=newDreg(EAX);
ExpNode *exp = arglist, *next;
funcaddr = gen_exp(func, F_ALL|F_ADDR, 4);
if(exp->exptype == exp_void)
goto call;
for(;exp;exp=next)
{
mark();
next = exp->next;
exp->next = NULL;
depth += push_exp(exp);
release();
}
call:
reserve();
gen_code(op_call, 4, funcaddr, NULL);
if(depth>0)
gen_code(op_add, 4, newDreg(ESP), newImme(NULL, depth));
res->size = func->datatype->subtype->size;
if(func->datatype->subtype->basic_type == bt_struct
|| func->datatype->subtype->basic_type == bt_union)
res->mode = am_relative;
return res;//???????
}
void block_move(AddrMode *dst, AddrMode *src, int size)
{
AddrMode *edi=newDreg(EDI), *esi=newDreg(ESI), *ecx=newDreg(ECX);
if(regs[EDI])
push_reg(EDI);
gen_code(op_lea, 4, edi, dst);
//leave some bugs, so troublesome
if(regs[ESI])
{
if(src->base_reg != ESI
&&src->index_reg !=ESI)
push_reg(ESI);
else
regs[ESI] = false;
}
gen_code(op_lea, 4, esi, src);
if(regs[ECX])
{
push_reg(ECX);
}
gen_code(op_mov, 4, ecx, newImme(NULL, size));
gen_code(op_cld, 4, NULL, NULL);
gen_code(op_rep, 4, NULL, NULL);
gen_code(op_movsb, 4, NULL, NULL);
if(regs[ECX])
pop_reg(ECX);
if(regs[ESI])
pop_reg(ESI);
if(regs[EDI])
pop_reg(EDI);
return;
}
AddrMode *gen_assign(
struct _expnode *opd1,
struct _expnode *opd2)
{
AddrMode *left, *right;
int size;
if(opd1->datatype->array_vol)
size=4;
else
size= opd1->datatype->size;
left = gen_exp(opd1, F_MEM, size);
mark();
right = gen_exp(opd2, F_DREG|F_IMME, size);
if(opd1->datatype->basic_type != bt_struct
&&opd1->datatype->basic_type != bt_union)
{
//no struct assign here
make_legal(right, F_DREG | F_IMME, size, is_unsigned(opd2->datatype->basic_type));
gen_code(op_mov, size, left, right);
}
else
block_move(left, right, size);
freeregs(right);
release();
return left;
}
//ap1 is dreg and size 4
//ap2 is all and size 4
//multiply, divide or mode
AddrMode *make_legal(AddrMode *ap, int flag, int size, int unsign)
{
AddrMode *res;
if(flag & F_NOVALUE)
{
freeregs(ap);
return ap;
}
/* if(flag & F_ADDR)
{
res = temp_data();
if(ap->mode == am_direct ||ap->mode == am_label)
{
ap->mode = am_imme;
gen_code(op_mov, 4, res, ap);
}
else if(ap->mode == am_relative
|| ap->mode == am_scale)
{
gen_code(op_lea, 4, res, ap);
freeregs(ap);
}
return res;
}
*/ if(size>ap->size&&size<=4)
{
freeregs(ap);
res = temp_data();
if(unsign)
gen_code2(op_movzx, size, res, ap->size, ap);
else
gen_code2(op_movsx, size, res, ap->size, ap);
ap = res;
}
switch(ap->mode)
{
case am_label:
return ap;
case am_imme:
if(flag&F_IMME)
return ap;
break;
case am_dreg:
if(flag&F_DREG)
return ap;
break;
case am_freg:
if(flag&F_FREG)
return ap;
break;//????
case am_direct:
case am_relative:
case am_scale:
if(flag&F_MEM)
return ap;
break;
}
if(flag&F_DREG)
{
freeregs(ap);
res = temp_data();
res->size = ap->size;
gen_code(op_mov, size, res, ap);
ap = res;
}
else
{
debug("need to tackle specially\n");
}
return ap;
}
AddrMode *gen_binary(
int op,
struct _expnode *opd1,
struct _expnode *opd2)
{
AddrMode *left, *right;
left = gen_exp(opd1, F_DREG, 4);
mark();
right = gen_exp(opd2, F_ALL, 4);
gen_code(op, 4, left, right);
freeregs(right);
release();
return left;
}
AddrMode *gen_mul(int op, struct _expnode *opd1, struct _expnode *opd2, int mod)
{
AddrMode *left, *right;
AddrMode *eax = newDreg(EAX), *ecx=newDreg(ECX), *edx = newDreg(EDX);
AddrMode *div;
int tmp, topush;
left = gen_exp(opd1, F_DREG, 4);
mark();
right = gen_exp(opd2, F_ALT, 4);
if(left->base_reg != EAX)
{
gen_code(op_xchg, 4, eax, left);
tmp = regs[EAX];
regs[EAX] = regs[left->base_reg];
regs[left->base_reg] = tmp;
/* if(right->base_reg == EAX)
right->base_reg = left->base_reg;
else if(ap2->index_reg == EAX)
right->index_reg = left->base_reg;
*/ }
if(right->base_reg == EDX ||right->index_reg == EDX)
{
topush = ECX;
div = ecx;
}
else
{
topush = EDX;
div = right;
}
if(regs[topush])
push_reg(topush);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -