Alien-TinyCC
view release on metacpan or search on metacpan
src/c67-gen.c view on Meta::CPAN
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 '*':
case TOK_UMULL:
gv2(RC_INT, RC_INT);
r = vtop[-1].r;
fr = vtop[0].r;
vtop--;
C67_MPYI(fr, r); // 32 bit bultiply fr,r,fr
C67_NOP(8); // NOP 8 for worst case
break;
case TOK_SHL:
gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
r = vtop[-1].r;
fr = vtop[0].r;
vtop--;
C67_SHL(fr, r); // arithmetic/logical shift
break;
case TOK_SHR:
gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
r = vtop[-1].r;
fr = vtop[0].r;
vtop--;
C67_SHRU(fr, r); // logical shift
break;
case TOK_SAR:
gv2(RC_INT_BSIDE, RC_INT_BSIDE); // shift amount must be on same side as dst
r = vtop[-1].r;
fr = vtop[0].r;
vtop--;
C67_SHR(fr, r); // arithmetic shift
break;
case '/':
t = TOK__divi;
call_func:
vswap();
/* call generic idiv function */
vpush_global_sym(&func_old_type, t);
vrott(3);
gfunc_call(2);
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = VT_CONST;
break;
case TOK_UDIV:
case TOK_PDIV:
t = TOK__divu;
goto call_func;
case '%':
t = TOK__remi;
goto call_func;
case TOK_UMOD:
t = TOK__remu;
goto call_func;
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 ft, fc, fr, r;
if (op >= TOK_ULT && op <= TOK_GT)
gv2(RC_EDX, RC_EAX); // make sure src2 is on b side
else
gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
ft = vtop->type.t;
fc = vtop->c.ul;
r = vtop->r;
fr = vtop[-1].r;
if ((ft & VT_BTYPE) == VT_LDOUBLE)
tcc_error("long doubles not supported");
if (op >= TOK_ULT && op <= TOK_GT) {
r = vtop[-1].r;
fr = vtop[0].r;
C67_compare_reg = C67_B2;
if (op == TOK_LT) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPLTDP(r, fr, C67_B2);
else
C67_CMPLTSP(r, fr, C67_B2);
C67_invert_test = FALSE;
} else if (op == TOK_GE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
src/c67-gen.c view on Meta::CPAN
C67_invert_test = FALSE;
} else if (op == TOK_LE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
else
C67_CMPGTSP(r, fr, C67_B2);
C67_invert_test = TRUE;
} else if (op == TOK_EQ) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
else
C67_CMPEQSP(r, fr, C67_B2);
C67_invert_test = FALSE;
} else if (op == TOK_NE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
else
C67_CMPEQSP(r, fr, C67_B2);
C67_invert_test = TRUE;
} else {
ALWAYS_ASSERT(FALSE);
}
vtop->r = VT_CMP; // tell TCC that result is in "flags" actually B2
} else {
if (op == '+') {
if ((ft & VT_BTYPE) == VT_DOUBLE) {
C67_ADDDP(r, fr); // ADD fr,r,fr
C67_NOP(6);
} else {
C67_ADDSP(r, fr); // ADD fr,r,fr
C67_NOP(3);
}
vtop--;
} else if (op == '-') {
if ((ft & VT_BTYPE) == VT_DOUBLE) {
C67_SUBDP(r, fr); // SUB fr,r,fr
C67_NOP(6);
} else {
C67_SUBSP(r, fr); // SUB fr,r,fr
C67_NOP(3);
}
vtop--;
} else if (op == '*') {
if ((ft & VT_BTYPE) == VT_DOUBLE) {
C67_MPYDP(r, fr); // MPY fr,r,fr
C67_NOP(9);
} else {
C67_MPYSP(r, fr); // MPY fr,r,fr
C67_NOP(3);
}
vtop--;
} else if (op == '/') {
if ((ft & VT_BTYPE) == VT_DOUBLE) {
// must call intrinsic DP floating point divide
vswap();
/* call generic idiv function */
vpush_global_sym(&func_old_type, TOK__divd);
vrott(3);
gfunc_call(2);
vpushi(0);
vtop->r = REG_FRET;
vtop->r2 = REG_LRET;
} else {
// must call intrinsic SP floating point divide
vswap();
/* call generic idiv function */
vpush_global_sym(&func_old_type, TOK__divf);
vrott(3);
gfunc_call(2);
vpushi(0);
vtop->r = REG_FRET;
vtop->r2 = VT_CONST;
}
} else
ALWAYS_ASSERT(FALSE);
}
}
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
and 'long long' cases. */
void gen_cvt_itof(int t)
{
int r;
gv(RC_INT);
r = vtop->r;
if ((t & VT_BTYPE) == VT_DOUBLE) {
if (t & VT_UNSIGNED)
C67_INTDPU(r, r);
else
C67_INTDP(r, r);
C67_NOP(4);
vtop->type.t = VT_DOUBLE;
} else {
if (t & VT_UNSIGNED)
C67_INTSPU(r, r);
else
C67_INTSP(r, r);
C67_NOP(3);
vtop->type.t = VT_FLOAT;
}
}
/* convert fp to int 't' type */
/* XXX: handle long long case */
void gen_cvt_ftoi(int t)
{
int r;
gv(RC_FLOAT);
r = vtop->r;
if (t != VT_INT)
tcc_error("long long not supported");
else {
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
C67_DPTRUNC(r, r);
C67_NOP(3);
} else {
C67_SPTRUNC(r, r);
C67_NOP(3);
( run in 0.503 second using v1.01-cache-2.11-cpan-5735350b133 )