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 )