1541 lines
45 KiB
Plaintext
1541 lines
45 KiB
Plaintext
|
|
#define FBO1_NOT_CONST 0
|
|
#define FBO1_INT 1
|
|
#define FBO1_DOUBLE 2
|
|
|
|
|
|
BoolU8 FixupBinaryOp1(IntermediateCode *tempi,
|
|
IntermediateCode *tempi1,IntermediateCode *tempi2,
|
|
BoolU4 *is_unsigned)
|
|
{
|
|
ClassStruct *tempc=tempi->ic_class,*tempc1,*tempc2;
|
|
tempc1=tempi1->ic_class;
|
|
while (tempc1->return_class)
|
|
tempc1=tempc1->return_class;
|
|
tempc2=tempi2->ic_class;
|
|
while (tempc2->return_class)
|
|
tempc2=tempc2->return_class;
|
|
if (tempc1->sub_type>tempc2->sub_type)
|
|
tempi->ic_class=tempc1;
|
|
else
|
|
tempi->ic_class=tempc2;
|
|
tempc=tempi->ic_class;
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (!(tempi->ic_flags&ICF_USE_INT)) {
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
tempi1->ic_data><(double)=tempi1->ic_data;
|
|
tempi1->ic_class=sys_internal_types[IT_DOUBLE];
|
|
tempi1->ic_opcode=EC_DOUBLE;
|
|
} else
|
|
if (tempc1->sub_type!=IT_DOUBLE)
|
|
tempi1->ic_flags|=ICF_R_TO_DOUBLE;
|
|
if (tempi2->ic_opcode==EC_IMM) {
|
|
tempi2->ic_data><(double)=tempi2->ic_data;
|
|
tempi2->ic_class=sys_internal_types[IT_DOUBLE];
|
|
tempi2->ic_opcode=EC_DOUBLE;
|
|
} else
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
}
|
|
if (tempi1->ic_opcode==EC_DOUBLE &&
|
|
tempi2->ic_opcode==EC_DOUBLE &&
|
|
!(tempi->ic_flags&(ICF_PUSH_CMP|ICF_POP_CMP))) {
|
|
tempi->ic_flags|=tempi1->ic_flags|tempi2->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
return FBO1_DOUBLE;
|
|
} else
|
|
return FBO1_NOT_CONST;
|
|
}
|
|
tempi->ic_flags&=~ICF_USE_INT;
|
|
*is_unsigned=tempc1->sub_type&1 || tempc2->sub_type&1;
|
|
if (tempi1->ic_opcode==EC_IMM &&
|
|
tempi2->ic_opcode==EC_IMM &&
|
|
!(tempi->ic_flags&(ICF_PUSH_CMP|ICF_POP_CMP))) {
|
|
tempi->ic_flags|=tempi1->ic_flags|tempi2->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
return FBO1_INT;
|
|
} else
|
|
return FBO1_NOT_CONST;
|
|
}
|
|
|
|
BoolU8 FixupBinaryOp2(IntermediateCode **tempi1,IntermediateCode **tempi2)
|
|
{
|
|
IntermediateCode *tempii1=*tempi1,
|
|
*tempii2=*tempi2;
|
|
if (tempii1->ic_opcode==EC_IMM &&
|
|
!(tempii1->ic_flags & ICF_R_TO_DOUBLE))
|
|
return TRUE;
|
|
if (tempii2->ic_opcode==EC_IMM &&
|
|
!(tempii2->ic_flags & ICF_R_TO_DOUBLE)) {
|
|
*tempi1=tempii2;
|
|
*tempi2=tempii1;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU8 FixupUnaryOp(IntermediateCode *tempi,
|
|
IntermediateCode *tempi1,
|
|
BoolU4 *is_unsigned)
|
|
{
|
|
ClassStruct *tempc,*tempc1;
|
|
tempc1=tempi1->ic_class;
|
|
while (tempc1->return_class)
|
|
tempc1=tempc1->return_class;
|
|
tempi->ic_class=tempc1;
|
|
tempc=tempi->ic_class;
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (!(tempi->ic_flags&ICF_USE_INT)) {
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
tempi1->ic_data><(double)=tempi1->ic_data;
|
|
tempi1->ic_class=sys_internal_types[IT_DOUBLE];
|
|
tempi1->ic_opcode=EC_DOUBLE;
|
|
} else
|
|
if (tempc1->sub_type!=IT_DOUBLE)
|
|
tempi1->ic_flags|=ICF_R_TO_DOUBLE;
|
|
}
|
|
if (tempi1->ic_opcode==EC_DOUBLE) {
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
return FBO1_DOUBLE;
|
|
} else
|
|
return FBO1_NOT_CONST;
|
|
}
|
|
tempi->ic_flags&=~ICF_USE_INT;
|
|
*is_unsigned=tempc1->sub_type&1;
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
return FBO1_INT;
|
|
} else
|
|
return FBO1_NOT_CONST;
|
|
}
|
|
|
|
I8 CmpOffsetToReg(I8 offset,I8 *register_offsets)
|
|
{
|
|
I8 i;
|
|
for (i=0;i<NUM_REGS;i++)
|
|
if (offset==register_offsets[i])
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
void OptMissing(LexStruct *lx,I8 pass,IntermediateCode *tempi)
|
|
{
|
|
coutln "Pass:",pass," Missing IC handler";
|
|
CbPutIc(tempi);
|
|
PrsExcept(lx,"ST_OPT_INTERNAL_ERROR");
|
|
}
|
|
|
|
IntermediateCode opt_nop;
|
|
|
|
|
|
ParseStack *OptStart(LexStruct *lx,IntermediateCode **temp_lag)
|
|
{
|
|
I8 i;
|
|
ParseStack *ps=MAlloc(sizeof(ParseStack));
|
|
CbInitInPtrs(&lx->cb);
|
|
ps->ptr=0;
|
|
for (i=0;i<4;i++)
|
|
temp_lag[i]=&opt_nop;
|
|
return ps;
|
|
}
|
|
|
|
LTextern CP_OPTNEXT BoolU4 OptNext(IntermediateCode *tempi,
|
|
IntermediateCode **temp_lag);
|
|
|
|
LTextern CP_OPTNEXT2 BoolU4 OptNext2(IntermediateCode *tempi,
|
|
IntermediateCode **temp_lag);
|
|
|
|
LTextern CP_OPTNEXT3 BoolU4 OptNext3(IntermediateCode *tempi,
|
|
IntermediateCode **temp_lag);
|
|
|
|
void OptEnd(LexStruct *lx,I8 pass,ParseStack *ps)
|
|
{
|
|
if (ps->ptr>2) {
|
|
PrintF("Pass:%d Stack:%08X\r\n",pass,ps->ptr);
|
|
PrsExcept(lx,"ST_OPT_INTERNAL_ERROR");
|
|
}
|
|
Free(ps);
|
|
}
|
|
|
|
|
|
IntermediateCode *OptLag(LexStruct *lx,IntermediateCode *tempi)
|
|
{
|
|
do {
|
|
if (tempi==lx->cb.cb_in_ptr)
|
|
return NULL;
|
|
else
|
|
tempi-=sizeof(IntermediateCode);
|
|
} while (tempi->ic_opcode<=EC_END_EXP);
|
|
return tempi;
|
|
}
|
|
|
|
IntermediateCode *OptLag1(LexStruct *lx,IntermediateCode *tempi)
|
|
{
|
|
do {
|
|
if (tempi==lx->cb.cb_in_ptr)
|
|
return NULL;
|
|
else
|
|
tempi-=sizeof(IntermediateCode);
|
|
} while (tempi->ic_opcode==EC_NOP||tempi->ic_opcode==EC_NOP1);
|
|
return tempi;
|
|
}
|
|
|
|
IntermediateCode *OptLead1(LexStruct *lx,IntermediateCode *tempi)
|
|
{
|
|
nounusedwarn lx;
|
|
do {
|
|
tempi+=sizeof(IntermediateCode);
|
|
if (tempi->ic_opcode==EC_NULL)
|
|
return NULL;
|
|
} while (tempi->ic_opcode==EC_NOP||tempi->ic_opcode==EC_NOP1);
|
|
return tempi;
|
|
}
|
|
|
|
extern void OptBrNotZero(LexStruct *lx,IntermediateCode *tempi);
|
|
|
|
IntermediateCode *OptBrZero(LexStruct *lx,IntermediateCode *tempi)
|
|
{
|
|
CbMiscStruct *templ_true,*templ_false;
|
|
IntermediateCode *tempii=OptLag(lx,tempi),*tempii2;
|
|
switch (tempii->ic_opcode) {
|
|
case EC_NOT:
|
|
tempi->ic_opcode=EC_BR_NOT_ZERO;
|
|
tempi->ic_class=tempii->ic_class;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
tempi->p1c=tempii->p1c;
|
|
tempi->p1t=tempii->p1t;
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempii->ic_flags=0;
|
|
return OptBrNotZero(lx,tempi);
|
|
case EC_EQUAL_EQUAL:
|
|
tempi->ic_opcode=EC_BR_NOT_EQUAL;
|
|
break;
|
|
case EC_NOT_EQUAL:
|
|
tempi->ic_opcode=EC_BR_EQUAL_EQUAL;
|
|
break;
|
|
case EC_LESS:
|
|
tempi->ic_opcode=EC_BR_GREATER_EQUAL;
|
|
break;
|
|
case EC_GREATER:
|
|
tempi->ic_opcode=EC_BR_LESS_EQUAL;
|
|
break;
|
|
case EC_LESS_EQUAL:
|
|
tempi->ic_opcode=EC_BR_GREATER;
|
|
break;
|
|
case EC_GREATER_EQUAL:
|
|
tempi->ic_opcode=EC_BR_LESS;
|
|
break;
|
|
case EC_OR_OR:
|
|
tempi->ic_opcode=EC_BR_OR_OR_ZERO;
|
|
break;
|
|
case EC_AND_AND:
|
|
tempi->ic_opcode=EC_BR_AND_AND_ZERO;
|
|
break;
|
|
case EC_AND:
|
|
tempi->ic_opcode=EC_BR_AND_ZERO;
|
|
break;
|
|
case EC_CALL_END:
|
|
tempii2=OptLag(lx,tempii);
|
|
switch (tempii2->ic_opcode) {
|
|
case EC_BT:
|
|
tempii2->ic_opcode=EC_BR_NOT_BT;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTS:
|
|
tempii2->ic_opcode=EC_BR_NOT_BTS;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTR:
|
|
tempii2->ic_opcode=EC_BR_NOT_BTR;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTC:
|
|
tempii2->ic_opcode=EC_BR_NOT_BTC;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTS:
|
|
tempii2->ic_opcode=EC_BR_NOT_LBTS;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTR:
|
|
tempii2->ic_opcode=EC_BR_NOT_LBTR;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTC:
|
|
tempii2->ic_opcode=EC_BR_NOT_LBTC;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
}
|
|
break;
|
|
}
|
|
if (tempi->ic_opcode!=EC_BR_ZERO) {
|
|
tempi->ic_class=tempii->ic_class;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
tempi->p1c=tempii->p1c;
|
|
tempi->p2c=tempii->p2c;
|
|
tempi->p1t=tempii->p1t;
|
|
tempi->p2t=tempii->p2t;
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempii->ic_flags=0;
|
|
templ_true=tempi->ic_data;
|
|
if (tempi->ic_opcode==EC_BR_AND_AND_ZERO) {
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempii=tempi->p1t+sizeof(IntermediateCode);
|
|
tempii->ic_data=templ_true;
|
|
tempii->p1t=tempi->p1t;
|
|
tempii->p1c=tempi->p1c;
|
|
tempii->ic_opcode=EC_BR_ZERO;
|
|
OptBrZero(lx,tempii);
|
|
tempii=tempi->p2t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p2t;
|
|
tempii->p1c=tempi->p2c;
|
|
tempii->ic_data=templ_true;
|
|
tempii->ic_opcode=EC_BR_ZERO;
|
|
return OptBrZero(lx,tempii);
|
|
} else if (tempi->ic_opcode==EC_BR_OR_OR_ZERO) {
|
|
templ_false=CbMiscNew(lx,CBMT_LABEL);
|
|
tempi->ic_opcode=EC_LABEL;
|
|
tempi->ic_flags=0;
|
|
tempi->ic_data=templ_false;
|
|
tempii=tempi->p1t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p1t;
|
|
tempii->p1c=tempi->p1c;
|
|
tempii->ic_data=templ_false;
|
|
tempii->ic_opcode=EC_BR_NOT_ZERO;
|
|
OptBrNotZero(lx,tempii);
|
|
tempii=tempi->p2t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p2t;
|
|
tempii->p1c=tempi->p2c;
|
|
tempii->ic_data=templ_true;
|
|
tempii->ic_opcode=EC_BR_ZERO;
|
|
return OptBrZero(lx,tempii);
|
|
}
|
|
}
|
|
return tempi;
|
|
}
|
|
|
|
|
|
IntermediateCode *OptBrNotZero(LexStruct *lx,IntermediateCode *tempi)
|
|
{
|
|
CbMiscStruct *templ_true,*templ_false;
|
|
IntermediateCode *tempii=OptLag(lx,tempi),*tempii2;
|
|
switch (tempii->ic_opcode) {
|
|
case EC_NOT:
|
|
tempi->ic_opcode=EC_BR_ZERO;
|
|
tempi->ic_class=tempii->ic_class;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
tempi->p1c=tempii->p1c;
|
|
tempi->p1t=tempii->p1t;
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempii->ic_flags=0;
|
|
return OptBrZero(lx,tempi);
|
|
case EC_EQUAL_EQUAL:
|
|
tempi->ic_opcode=EC_BR_EQUAL_EQUAL;
|
|
break;
|
|
case EC_NOT_EQUAL:
|
|
tempi->ic_opcode=EC_BR_NOT_EQUAL;
|
|
break;
|
|
case EC_LESS:
|
|
tempi->ic_opcode=EC_BR_LESS;
|
|
break;
|
|
case EC_GREATER:
|
|
tempi->ic_opcode=EC_BR_GREATER;
|
|
break;
|
|
case EC_LESS_EQUAL:
|
|
tempi->ic_opcode=EC_BR_LESS_EQUAL;
|
|
break;
|
|
case EC_GREATER_EQUAL:
|
|
tempi->ic_opcode=EC_BR_GREATER_EQUAL;
|
|
break;
|
|
case EC_OR_OR:
|
|
tempi->ic_opcode=EC_BR_OR_OR_NOT_ZERO;
|
|
break;
|
|
case EC_AND_AND:
|
|
tempi->ic_opcode=EC_BR_AND_AND_NOT_ZERO;
|
|
break;
|
|
case EC_AND:
|
|
tempi->ic_opcode=EC_BR_AND_NOT_ZERO;
|
|
break;
|
|
case EC_CALL_END:
|
|
tempii2=OptLag(lx,tempii);
|
|
switch (tempii2->ic_opcode) {
|
|
case EC_BT:
|
|
tempii2->ic_opcode=EC_BR_BT;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTS:
|
|
tempii2->ic_opcode=EC_BR_BTS;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTR:
|
|
tempii2->ic_opcode=EC_BR_BTR;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_BTC:
|
|
tempii2->ic_opcode=EC_BR_BTC;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTS:
|
|
tempii2->ic_opcode=EC_BR_LBTS;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTR:
|
|
tempii2->ic_opcode=EC_BR_LBTR;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
case EC_LBTC:
|
|
tempii2->ic_opcode=EC_BR_LBTC;
|
|
tempii2->ic_data=tempi->ic_data;
|
|
tempii->ic_opcode=EC_CALL_END2;
|
|
tempi->ic_opcode=EC_NOP;
|
|
return tempii;
|
|
}
|
|
break;
|
|
}
|
|
if (tempi->ic_opcode!=EC_BR_NOT_ZERO) {
|
|
tempi->ic_class=tempii->ic_class;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
tempi->p1c=tempii->p1c;
|
|
tempi->p2c=tempii->p2c;
|
|
tempi->p1t=tempii->p1t;
|
|
tempi->p2t=tempii->p2t;
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempii->ic_flags=0;
|
|
templ_true=tempi->ic_data;
|
|
if (tempi->ic_opcode==EC_BR_OR_OR_NOT_ZERO) {
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempii=tempi->p1t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p1t;
|
|
tempii->p1c=tempi->p1c;
|
|
tempii->ic_data=templ_true;
|
|
tempii->ic_opcode=EC_BR_NOT_ZERO;
|
|
OptBrNotZero(lx,tempii);
|
|
tempii=tempi->p2t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p2t;
|
|
tempii->p1c=tempi->p2c;
|
|
tempii->ic_data=templ_true;
|
|
tempii->ic_opcode=EC_BR_NOT_ZERO;
|
|
return OptBrNotZero(lx,tempii);
|
|
} else if (tempi->ic_opcode==EC_BR_AND_AND_NOT_ZERO) {
|
|
templ_false=CbMiscNew(lx,CBMT_LABEL);
|
|
tempi->ic_opcode=EC_LABEL;
|
|
tempi->ic_flags=0;
|
|
tempi->ic_data=templ_false;
|
|
tempii=tempi->p1t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p1t;
|
|
tempii->p1c=tempi->p1c;
|
|
tempii->ic_data=templ_false;
|
|
tempii->ic_opcode=EC_BR_ZERO;
|
|
OptBrZero(lx,tempii);
|
|
tempii=tempi->p2t+sizeof(IntermediateCode);
|
|
tempii->p1t=tempi->p2t;
|
|
tempii->p1c=tempi->p2c;
|
|
tempii->ic_data=templ_true;
|
|
tempii->ic_opcode=EC_BR_NOT_ZERO;
|
|
return OptBrNotZero(lx,tempii);
|
|
}
|
|
}
|
|
return tempi;
|
|
}
|
|
|
|
IntermediateCode *CmpOptPass1(LexStruct *lx,ClassStruct *fun_class,BoolU4 combined)
|
|
{
|
|
/*
|
|
Simplify CONST arithmetic.
|
|
Sets the class throughout Expression trees.
|
|
Returns the type of an Expression for use
|
|
in int<-->double conversions of function
|
|
parameters.
|
|
*/
|
|
I8 code,i;
|
|
BoolU4 is_unsigned;
|
|
ClassStruct *tempc,*tempc1,*tempc2,*tempc3,*tempcc;
|
|
IntermediateCode *tempi,*tempi1,*tempi2,*tempi3,*tempi_push,
|
|
*temp_lag[4],*last_with_class=NULL,*tempii;
|
|
ParseStack *ps=OptStart(lx,temp_lag);
|
|
if (combined)
|
|
tempi=lx->cb.cb_in_ptr;
|
|
else
|
|
tempi=CbGetIc1(&lx->cb);
|
|
while (code=tempi->ic_opcode) {
|
|
OptNext(tempi,temp_lag);
|
|
tempc=tempi->ic_class;
|
|
tempi->original_class=tempc;
|
|
tempi_push=tempi;
|
|
switch (cmp_param_cnt[code]) {
|
|
case 9:
|
|
ps->ptr-=tempi->ic_data>>2;
|
|
break;
|
|
case 3:
|
|
tempi3=PrsPop(ps);
|
|
tempc3=tempi3->ic_class;
|
|
tempi->p3t=tempi3;
|
|
tempi->p3c=PrsPop(ps);
|
|
case 2:
|
|
tempi2=PrsPop(ps);
|
|
tempc2=tempi2->ic_class;
|
|
tempi->p2t=tempi2;
|
|
tempi->p2c=PrsPop(ps);
|
|
case 1:
|
|
tempi1=PrsPop(ps);
|
|
tempc1=tempi1->ic_class;
|
|
tempi->p1t=tempi1;
|
|
tempi->p1c=PrsPop(ps);
|
|
break;
|
|
}
|
|
if (Bt(not_constant_bitmap,code))
|
|
lx->flags|=LF_NOT_CONSTANT;
|
|
switch (code) {
|
|
case EC_IMM:
|
|
case EC_DOUBLE:
|
|
case EC_STR_CONST:
|
|
case EC_RBP:
|
|
case EC_FS:
|
|
case EC_GS:
|
|
break;
|
|
case EC_PUSH_CMP:
|
|
tempi1=temp_lag[1];
|
|
if (tempi1->ic_opcode==EC_AND_AND)
|
|
tempi1=temp_lag[2];
|
|
tempi->ic_class=tempi1->ic_class;
|
|
tempi->original_class=tempi->ic_class;
|
|
tempi->ic_data=0;
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
break;
|
|
case EC_COM:
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempi1->ic_opcode==EC_DOUBLE) {
|
|
tempi->ic_data><(double)=~tempi1->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
}
|
|
break;
|
|
}
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
tempi->ic_data=~tempi1->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_NOT:
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempi1->ic_opcode==EC_DOUBLE) {
|
|
tempi->ic_data><(double)=!tempi1->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
}
|
|
break;
|
|
}
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
tempi->ic_data=!tempi1->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_UNARY_MINUS:
|
|
if (i=FixupUnaryOp(tempi,tempi1,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
tempi->ic_data=-tempi1->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (tempi->ic_flags&ICF_USE_INT) {
|
|
tempi->ic_data=-tempi1->ic_data><(double);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=-tempi1->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
}
|
|
}
|
|
if (tempc1->type&HTT_INTERNAL_TYPE && tempc1->sub_type& 1)
|
|
tempi->ic_class=sys_internal_types[tempc1->sub_type-1];
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_DEREF:
|
|
case EC__PP:
|
|
case EC__MM:
|
|
case EC_PP_:
|
|
case EC_MM_:
|
|
break;
|
|
case EC_SHL_CONST:
|
|
case EC_SHR_CONST:
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
|
|
case EC_POWER:
|
|
if (tempc1->sub_type>tempc2->sub_type)
|
|
tempi->ic_class=tempc1;
|
|
else
|
|
tempi->ic_class=tempc2;
|
|
tempc=tempi->ic_class;
|
|
if (tempc1->sub_type!=IT_DOUBLE)
|
|
tempi1->ic_flags|=ICF_R_TO_DOUBLE;
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
if (tempc->sub_type!=IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_R_TO_INT|ICF_USE_DOUBLE;
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_SHL:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)<<tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)<<tempi2->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double) << tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
} else if (tempi2->ic_opcode==EC_IMM) {
|
|
tempi->ic_flags|=tempi2->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_data=tempi2->ic_data;
|
|
tempi->ic_opcode=EC_SHL_CONST;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_SHR:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)>>tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)>>tempi2->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double) >> tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
} else if (tempi2->ic_opcode==EC_IMM) {
|
|
tempi->ic_flags|=tempi2->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_data=tempi2->ic_data;
|
|
tempi->ic_opcode=EC_SHR_CONST;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_MUL:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)*tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)*tempi2->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (tempi->ic_flags&ICF_USE_INT) {
|
|
tempi->ic_data=tempi1->ic_data><(double)*
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double)*
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
}
|
|
} else {
|
|
if (tempi2->ic_opcode==EC_IMM) {
|
|
tempcc=tempi->p1c;
|
|
tempii=tempi2;
|
|
tempi2=tempi1;
|
|
tempi1=tempii;
|
|
} else
|
|
tempcc=tempi->p2c;
|
|
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
i=tempi1->ic_data;
|
|
switch (i) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
tempi2->ic_flags|=tempi->ic_flags|tempi1->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi2->p1c=tempi->p1c;
|
|
tempi2->p1t=tempi->p1t;
|
|
tempi2->original_class=tempi->original_class;
|
|
tempi_push=tempi2;
|
|
break;
|
|
default:
|
|
if (Bsf(i)==Bsr(i)) {
|
|
tempi->ic_flags|=tempi1->ic_flags;
|
|
tempi->p1c=tempcc;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi->ic_data=Bsf(i);
|
|
tempi->ic_opcode=EC_SHL_CONST;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_DIV:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (!tempi2->ic_data) PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)/tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)/tempi2->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double)/
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
} else {
|
|
if (tempi2->ic_opcode==EC_IMM) {
|
|
i=tempi2->ic_data;
|
|
switch (i) {
|
|
case 0:
|
|
PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
break;
|
|
case 1:
|
|
tempi1->ic_flags|=tempi2->ic_flags|tempi->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi1->p1c=tempi->p1c;
|
|
tempi1->p1t=tempi->p1t;
|
|
tempi1->original_class=tempi->original_class;
|
|
tempi_push=tempi1;
|
|
break;
|
|
default:
|
|
if (Bsf(i)==Bsr(i)) {
|
|
tempi->ic_flags|=tempi2->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_data=Bsf(i);
|
|
tempi->ic_opcode=EC_SHR_CONST;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_MOD:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (!tempi2->ic_data) PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)%tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)%tempi2->ic_data><(I8);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double)%
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
} else {
|
|
if (tempi2->ic_opcode==EC_IMM) {
|
|
i=tempi2->ic_data;
|
|
switch (i) {
|
|
case 0:
|
|
PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
break;
|
|
default:
|
|
if (i>0 && Bsf(i)==Bsr(i)) {
|
|
tempi2->ic_data=i-1;
|
|
tempi->ic_opcode=EC_AND;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_AND:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data&tempi2->ic_data;
|
|
if (i==FBO1_INT)
|
|
tempi->ic_opcode=EC_IMM;
|
|
else
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_OR:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data|tempi2->ic_data;
|
|
if (i==FBO1_INT)
|
|
tempi->ic_opcode=EC_IMM;
|
|
else
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_XOR:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data^tempi2->ic_data;
|
|
if (i==FBO1_INT)
|
|
tempi->ic_opcode=EC_IMM;
|
|
else
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_ADD:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
tempi->ic_data=tempi1->ic_data+tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (tempi->ic_flags&ICF_USE_INT) {
|
|
tempi->ic_data=tempi1->ic_data><(double)*
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double)+
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
}
|
|
} else {
|
|
if (tempi1->ic_opcode==EC_IMM) {
|
|
/******* we got problems--class needs to propigate back
|
|
if (!tempi1->ic_data) {
|
|
tempi2->ic_flags|=tempi1->ic_flags|tempi->ic_flags;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi2->p1c=tempi->p1c;
|
|
tempi2->p1t=tempi->p1t;
|
|
tempi2->original_class=tempi->original_class;
|
|
tempi_push=tempi2;
|
|
} else
|
|
*******/
|
|
|
|
// we got problems--class needs to propigate back
|
|
if (tempi2->ic_opcode==EC_ADD||
|
|
tempi2->ic_opcode==EC_SUB) {
|
|
if (tempi2->p1t->ic_opcode==EC_IMM) {
|
|
tempi2->ic_flags|=tempi->ic_flags;
|
|
if (tempi2->ic_opcode==EC_ADD)
|
|
tempi2->p1t->ic_data+=tempi1->ic_data;
|
|
else
|
|
tempi2->p1t->ic_data-=tempi1->ic_data;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi2->p1c=tempi->p1c;
|
|
tempi2->p1t=tempi->p1t;
|
|
tempi2->original_class=tempi->original_class;
|
|
tempi_push=tempi2;
|
|
} else if (tempi2->p2t->ic_opcode==EC_IMM) {
|
|
tempi2->ic_flags|=tempi->ic_flags;
|
|
if (tempi2->ic_opcode==EC_ADD)
|
|
tempi2->p2t->ic_data+=tempi1->ic_data;
|
|
else
|
|
tempi2->p2t->ic_data-=tempi1->ic_data;
|
|
tempi1->ic_opcode=EC_NOP;
|
|
tempi1->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi2->p1c=tempi->p1c;
|
|
tempi2->p1t=tempi->p1t;
|
|
tempi2->original_class=tempi->original_class;
|
|
tempi_push=tempi2;
|
|
}
|
|
}
|
|
} else if (tempi2->ic_opcode==EC_IMM) {
|
|
/******* we got problems--class needs to propigate back
|
|
if (!tempi2->ic_data) {
|
|
tempi1->ic_flags|=tempi2->ic_flags|tempi->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi1->p1c=tempi->p1c;
|
|
tempi1->p1t=tempi->p1t;
|
|
tempi1->original_class=tempi->original_class;
|
|
tempi_push=tempi1;
|
|
} else
|
|
*******/
|
|
|
|
// we got problems--class needs to propigate back
|
|
if (tempi1->ic_opcode==EC_ADD ||
|
|
tempi1->ic_opcode==EC_SUB) {
|
|
if (tempi1->p1t->ic_opcode==EC_IMM) {
|
|
tempi1->ic_flags|=tempi->ic_flags;
|
|
if (tempi1->ic_opcode==EC_ADD)
|
|
tempi1->p1t->ic_data+=tempi2->ic_data;
|
|
else
|
|
tempi1->p1t->ic_data-=tempi2->ic_data;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi1->p1c=tempi->p1c;
|
|
tempi1->p1t=tempi->p1t;
|
|
tempi1->original_class=tempi->original_class;
|
|
tempi_push=tempi1;
|
|
} else if (tempi1->p2t->ic_opcode==EC_IMM) {
|
|
tempi1->ic_flags|=tempi->ic_flags;
|
|
if (tempi1->ic_opcode==EC_ADD)
|
|
tempi1->p2t->ic_data+=tempi2->ic_data;
|
|
else
|
|
tempi1->p2t->ic_data-=tempi2->ic_data;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi1->p1c=tempi->p1c;
|
|
tempi1->p1t=tempi->p1t;
|
|
tempi1->original_class=tempi->original_class;
|
|
tempi_push=tempi1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_SUB:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
tempi->ic_data=tempi1->ic_data-tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
tempi->ic_data><(double)=tempi1->ic_data><(double)-
|
|
tempi2->ic_data><(double);
|
|
tempi->ic_opcode=EC_DOUBLE;
|
|
}
|
|
} else {
|
|
if (tempi2->ic_opcode==EC_IMM && !tempi2->ic_data) {
|
|
tempi1->ic_flags|=tempi2->ic_flags|tempi->ic_flags;
|
|
tempi2->ic_opcode=EC_NOP;
|
|
tempi2->ic_flags=0;
|
|
tempi->ic_opcode=EC_NOP;
|
|
tempi->ic_flags=0;
|
|
tempi1->p1c=tempi->p1c;
|
|
tempi1->p1t=tempi->p1t;
|
|
tempi1->original_class=tempi->original_class;
|
|
tempi_push=tempi1;
|
|
}
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_EQUAL_EQUAL:
|
|
if (FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data==tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_NOT_EQUAL:
|
|
if (FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data!=tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_LESS:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)<tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)<tempi2->ic_data><(I8);
|
|
} else {
|
|
tempi->ic_data=tempi1->ic_data><(double)<
|
|
tempi2->ic_data><(double);
|
|
}
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (is_unsigned)
|
|
tempi->ic_flags|=ICF_USE_UNSIGNED;
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_GREATER:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)>tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)>tempi2->ic_data><(I8);
|
|
} else {
|
|
tempi->ic_data=tempi1->ic_data><(double)>
|
|
tempi2->ic_data><(double);
|
|
}
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (is_unsigned)
|
|
tempi->ic_flags|=ICF_USE_UNSIGNED;
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_LESS_EQUAL:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)<=tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)<=tempi2->ic_data><(I8);
|
|
} else {
|
|
tempi->ic_data=tempi1->ic_data><(double)<=
|
|
tempi2->ic_data><(double);
|
|
}
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (is_unsigned)
|
|
tempi->ic_flags|=ICF_USE_UNSIGNED;
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_GREATER_EQUAL:
|
|
if (i=FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
if (i==FBO1_INT) {
|
|
if (is_unsigned)
|
|
tempi->ic_data=tempi1->ic_data><(U8)>=tempi2->ic_data><(U8);
|
|
else
|
|
tempi->ic_data=tempi1->ic_data><(I8)>=tempi2->ic_data><(I8);
|
|
} else {
|
|
tempi->ic_data=tempi1->ic_data><(double)>=
|
|
tempi2->ic_data><(double);
|
|
}
|
|
tempi->ic_opcode=EC_IMM;
|
|
} else {
|
|
if (is_unsigned)
|
|
tempi->ic_flags|=ICF_USE_UNSIGNED;
|
|
if (tempi->ic_class->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_USE_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
if (tempi_push->ic_flags & ICF_PUSH_CMP)
|
|
tempi->ic_class=tempi->original_class;
|
|
else
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_AND_AND:
|
|
if (FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data&&tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_OR_OR:
|
|
if (FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data||tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_XOR_XOR:
|
|
if (FixupBinaryOp1(tempi,tempi1,tempi2,&is_unsigned)) {
|
|
tempi->ic_data=tempi1->ic_data^^tempi2->ic_data;
|
|
tempi->ic_opcode=EC_IMM;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else if (is_unsigned)
|
|
tempi_push->original_class=sys_internal_types[IT_U8];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
tempi->ic_class=sys_internal_types[IT_I8];
|
|
break;
|
|
case EC_COLON:
|
|
if (tempc2->sub_type>tempc3->sub_type)
|
|
tempi->ic_class=tempc2;
|
|
else
|
|
tempi->ic_class=tempc3;
|
|
tempc=tempi->ic_class;
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
if (tempc3->sub_type!=IT_DOUBLE)
|
|
tempi3->ic_flags|=ICF_R_TO_DOUBLE;
|
|
}
|
|
if (!tempi_push->ic_class->ptr_cnt) {
|
|
if (tempi_push->ic_class->sub_type==IT_DOUBLE)
|
|
tempi_push->original_class=sys_internal_types[IT_DOUBLE];
|
|
else
|
|
tempi_push->original_class=sys_internal_types[IT_I8];
|
|
}
|
|
break;
|
|
case EC_MUL_EQUAL:
|
|
if (tempi2->ic_opcode==EC_IMM &&
|
|
tempc->sub_type!=IT_DOUBLE &&
|
|
tempc2->sub_type!=IT_DOUBLE) {
|
|
if (i=tempi2->ic_data) {
|
|
if (Bsf(i)==Bsr(i)) {
|
|
tempi2->ic_data=Bsf(i);
|
|
tempi->ic_opcode=EC_SHL_EQUAL;
|
|
}
|
|
}
|
|
}
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
} else {
|
|
if (tempc2->sub_type==IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_INT;
|
|
}
|
|
break;
|
|
case EC_DIV_EQUAL:
|
|
if (tempi2->ic_opcode==EC_IMM &&
|
|
tempc->sub_type!=IT_DOUBLE &&
|
|
tempc2->sub_type!=IT_DOUBLE) {
|
|
if (i=tempi2->ic_data) {
|
|
if (Bsf(i)==Bsr(i)) {
|
|
tempi2->ic_data=Bsf(i);
|
|
tempi->ic_opcode=EC_SHR_EQUAL;
|
|
}
|
|
} else
|
|
PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
}
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
} else {
|
|
if (tempc2->sub_type==IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_INT;
|
|
}
|
|
break;
|
|
case EC_MOD_EQUAL:
|
|
if (tempi2->ic_opcode==EC_IMM &&
|
|
tempc->sub_type!=IT_DOUBLE &&
|
|
tempc2->sub_type!=IT_DOUBLE) {
|
|
if (i=tempi2->ic_data) {
|
|
if (i>0 && Bsf(i)==Bsr(i)) {
|
|
tempi2->ic_data=i-1;
|
|
tempi->ic_opcode=EC_AND_EQUAL;
|
|
}
|
|
} else
|
|
PrsExcept(lx,"ST_DIVIDE_BY_ZERO");
|
|
}
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
} else {
|
|
if (tempc2->sub_type==IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_INT;
|
|
}
|
|
break;
|
|
case EC_ADD_EQUAL:
|
|
case EC_SUB_EQUAL:
|
|
case EC_ASSIGN:
|
|
if (tempc->sub_type==IT_DOUBLE) {
|
|
if (tempc2->sub_type!=IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_DOUBLE;
|
|
} else {
|
|
if (tempc2->sub_type==IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_INT;
|
|
}
|
|
break;
|
|
case EC_SHL_EQUAL:
|
|
case EC_SHR_EQUAL:
|
|
case EC_AND_EQUAL:
|
|
case EC_OR_EQUAL:
|
|
case EC_XOR_EQUAL:
|
|
if (tempc2->sub_type==IT_DOUBLE)
|
|
tempi2->ic_flags|=ICF_R_TO_INT;
|
|
break;
|
|
case EC_ENTER:
|
|
case EC_LEAVE:
|
|
tempi->ic_data=-fun_class->size;
|
|
break;
|
|
case EC_ADD_RSP:
|
|
if (temp_lag[1]->ic_opcode==EC_ADD_RSP) {
|
|
tempi->ic_data+=temp_lag[1]->ic_data;
|
|
tempi->ic_flags|=temp_lag[1]->ic_flags;
|
|
temp_lag[1]->ic_opcode=EC_NOP;
|
|
temp_lag[1]->ic_flags=0;
|
|
}
|
|
break;
|
|
|
|
case EC_CALL:
|
|
case EC_CALL_INDIRECT:
|
|
case EC_CALL_INDIRECT2:
|
|
case EC_CALL_EXTERN:
|
|
case EC_CLI:
|
|
case EC_STI:
|
|
case EC_WBINVD:
|
|
case EC_INVD:
|
|
case EC_ENABLE_CACHE:
|
|
case EC_DISABLE_CACHE:
|
|
case EC_GET_FLAGS:
|
|
case EC_GET_BASE_PTR:
|
|
case EC_GET_STACK_PTR:
|
|
case EC_RETURN_START:
|
|
case EC_RETURN_END:
|
|
case EC_ABSOLUTE_ADDRESS:
|
|
case EC_GET_LABEL:
|
|
case EC_TYPE:
|
|
case EC_RDTSC:
|
|
case EC_SET_FLAGS:
|
|
case EC_SET_BASE_PTR:
|
|
case EC_SET_STACK_PTR:
|
|
case EC_SET_RAX:
|
|
case EC_BSF:
|
|
case EC_BSR:
|
|
case EC_PREEMPT:
|
|
case EC_ABSI8:
|
|
case EC_REMQUE:
|
|
case EC_INPD:
|
|
case EC_INPW:
|
|
case EC_INP:
|
|
case EC_STRLEN:
|
|
case EC_BT:
|
|
case EC_BTS:
|
|
case EC_BTR:
|
|
case EC_BTC:
|
|
case EC_LBTS:
|
|
case EC_LBTR:
|
|
case EC_LBTC:
|
|
case EC_INSQUE:
|
|
case EC_INSQUE_REV:
|
|
case EC_OUTPD:
|
|
case EC_OUTPW:
|
|
case EC_OUTP:
|
|
case EC_SWITCH:
|
|
case EC_MEMCPY:
|
|
case EC_MEMSET:
|
|
break;
|
|
|
|
case EC_BR_ZERO:
|
|
if (combined)
|
|
tempi_push=OptBrZero(lx,tempi);
|
|
break;
|
|
case EC_BR_NOT_ZERO:
|
|
if (combined)
|
|
tempi_push=OptBrNotZero(lx,tempi);
|
|
break;
|
|
case EC_BR_NOT_EQUAL:
|
|
case EC_BR_EQUAL_EQUAL:
|
|
case EC_BR_GREATER_EQUAL:
|
|
case EC_BR_LESS_EQUAL:
|
|
case EC_BR_GREATER:
|
|
case EC_BR_LESS:
|
|
case EC_BR_OR_OR_NOT_ZERO:
|
|
case EC_BR_OR_OR_ZERO:
|
|
case EC_BR_AND_AND_NOT_ZERO:
|
|
case EC_BR_AND_AND_ZERO:
|
|
case EC_BR_AND_NOT_ZERO:
|
|
case EC_BR_AND_ZERO:
|
|
case EC_BR_BT:
|
|
case EC_BR_BTS:
|
|
case EC_BR_BTR:
|
|
case EC_BR_BTC:
|
|
case EC_BR_NOT_BT:
|
|
case EC_BR_NOT_BTS:
|
|
case EC_BR_NOT_BTR:
|
|
case EC_BR_NOT_BTC:
|
|
case EC_BR_LBTS:
|
|
case EC_BR_LBTR:
|
|
case EC_BR_LBTC:
|
|
case EC_BR_NOT_LBTS:
|
|
case EC_BR_NOT_LBTR:
|
|
case EC_BR_NOT_LBTC:
|
|
break;
|
|
|
|
case EC_NOP:
|
|
if (combined && tempi->ic_flags&ICF_PUSH_RESULT) {
|
|
tempii=tempi;
|
|
do tempii-=sizeof(IntermediateCode);
|
|
while (tempii->ic_opcode==EC_NOP);
|
|
tempii->ic_flags|=ICF_PUSH_RESULT;
|
|
tempi->ic_flags&=~ICF_PUSH_RESULT;
|
|
}
|
|
break;
|
|
case EC_NOP1:
|
|
ps->ptr+=tempi->ic_data<<1;
|
|
break;
|
|
case EC_LABEL:
|
|
tempii=temp_lag[1];
|
|
if (tempii->ic_opcode==EC_JMP) {
|
|
if (tempii->ic_data==tempi->ic_data) {
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
}
|
|
} else if (tempii->ic_opcode==EC_LABEL) {
|
|
tempii=temp_lag[2];
|
|
if (tempii->ic_opcode==EC_JMP) {
|
|
if (tempii->ic_data==tempi->ic_data) {
|
|
tempii->ic_opcode=EC_NOP;
|
|
tempi->ic_flags|=tempii->ic_flags;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EC_NULL:
|
|
case EC_ADDRESS:
|
|
case EC_QUESTION:
|
|
case EC_RET:
|
|
case EC_END_EXP:
|
|
case EC_CALL_START:
|
|
case EC_CALL_END:
|
|
case EC_CALL_END2:
|
|
case EC_PUSH_REGS:
|
|
case EC_POP_REGS:
|
|
case EC_IRQ:
|
|
case EC_JMP:
|
|
break;
|
|
default:
|
|
OptMissing(lx,1,tempi);
|
|
}
|
|
if (cmp_result_cnt[tempi_push->ic_opcode]) {
|
|
PrsPush(ps,tempi->original_class);
|
|
PrsPush(ps,tempi_push);
|
|
}
|
|
if (tempi->ic_class) {
|
|
if (code!=EC_RETURN_END && code>EC_END_EXP)
|
|
last_with_class=tempi;
|
|
}
|
|
if (combined)
|
|
tempi+=sizeof(IntermediateCode);
|
|
else
|
|
tempi=CbGetIc1(&lx->cb);
|
|
}
|
|
OptEnd(lx,1,ps);
|
|
|
|
/*
|
|
This is for determining type conversions
|
|
for passing parameters to functions.
|
|
*/
|
|
return last_with_class;
|
|
}
|
|
|