Alien-TinyCC

 view release on metacpan or  search on metacpan

src/c67-gen.c  view on Meta::CPAN

    C67_MV(C67_FP, C67_A0);	//  move FP -> A0
    C67_MV(C67_SP, C67_FP);	//  move SP -> FP

    // place all the args passed in regs onto the stack

    loc = 0;
    for (i = 0; i < NoOfCurFuncArgs; i++) {

	ParamLocOnStack[i] = loc;	// remember where the param is
	loc += -8;

	C67_PUSH(TREG_C67_A4 + i * 2);

	if (TranslateStackToReg[i] == 8) {
	    C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3);	// STW  r, *+SP[1] (go back and put the other)
	}
    }

    TotalBytesPushedOnStack = -loc;

    func_sub_sp_offset = ind;	// remember where we put the stack instruction 
    C67_ADDK(0, C67_SP);	//  ADDK.L2 loc,SP  (just put zero temporarily)

    C67_PUSH(C67_A0);
    C67_PUSH(C67_B3);
}

/* generate function epilog */
void gfunc_epilog(void)
{
    {
	int local = (-loc + 7) & -8;	// stack must stay aligned to 8 bytes for LDDW instr
	C67_POP(C67_B3);
	C67_NOP(4);		// NOP wait for load
	C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3);	//  B.S2  B3
	C67_POP(C67_FP);
	C67_ADDK(local, C67_SP);	//  ADDK.L2 loc,SP  
	C67_Adjust_ADDK((int *) (cur_text_section->data +
				 func_sub_sp_offset),
			-local + TotalBytesPushedOnStack);
	C67_NOP(3);		// NOP 
    }
}

/* generate a jump to a label */
int gjmp(int t)
{
    int ind1 = ind;

    C67_MVKL(C67_A0, t);	//r=reg to load,  constant
    C67_MVKH(C67_A0, t);	//r=reg to load,  constant
    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	// [!R] B.S2x  A0
    C67_NOP(5);
    return ind1;
}

/* generate a jump to a fixed address */
void gjmp_addr(int a)
{
    Sym *sym;
    // I guess this routine is used for relative short
    // local jumps, for now just handle it as the general
    // case

    // define a label that will be relocated

    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
    greloc(cur_text_section, sym, ind, R_C60LO16);
    greloc(cur_text_section, sym, ind + 4, R_C60HI16);

    gjmp(0);			// place a zero there later the symbol will be added to it
}

/* generate a test. set 'inv' to invert test. Stack entry is popped */
int gtst(int inv, int t)
{
    int ind1, n;
    int v, *p;

    v = vtop->r & VT_VALMASK;
    if (v == VT_CMP) {
	/* fast case : can jump directly since flags are set */
	// C67 uses B2 sort of as flags register
	ind1 = ind;
	C67_MVKL(C67_A0, t);	//r=reg to load, constant
	C67_MVKH(C67_A0, t);	//r=reg to load, constant

	if (C67_compare_reg != TREG_EAX &&	// check if not already in a conditional test reg
	    C67_compare_reg != TREG_EDX &&
	    C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
	    C67_MV(C67_compare_reg, C67_B2);
	    C67_compare_reg = C67_B2;
	}

	C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0);	// [!R] B.S2x  A0
	C67_NOP(5);
	t = ind1;		//return where we need to patch

    } else if (v == VT_JMP || v == VT_JMPI) {
	/* && or || optimization */
	if ((v & 1) == inv) {
	    /* insert vtop->c jump list in t */
	    p = &vtop->c.i;

	    // I guess the idea is to traverse to the
	    // null at the end of the list and store t
	    // there

	    n = *p;
	    while (n != 0) {
		p = (int *) (cur_text_section->data + n);

		// extract 32 bit address from MVKH/MVKL
		n = ((*p >> 7) & 0xffff);
		n |= ((*(p + 1) >> 7) & 0xffff) << 16;
	    }
	    *p |= (t & 0xffff) << 7;
	    *(p + 1) |= ((t >> 16) & 0xffff) << 7;
	    t = vtop->c.i;

	} else {
	    t = gjmp(t);
	    gsym(vtop->c.i);
	}
    } else {
	if (is_float(vtop->type.t)) {
	    vpushi(0);
	    gen_op(TOK_NE);
	}
	if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
	    /* constant jmp optimization */
	    if ((vtop->c.i != 0) != inv)
		t = gjmp(t);
	} else {
	    // I think we need to get the value on the stack
	    // into a register, test it, and generate a branch
	    // return the address of the branch, so it can be
	    // later patched

	    v = gv(RC_INT);	// get value into a reg 
	    ind1 = ind;
	    C67_MVKL(C67_A0, t);	//r=reg to load, constant
	    C67_MVKH(C67_A0, t);	//r=reg to load, constant

	    if (v != TREG_EAX &&	// check if not already in a conditional test reg
		v != TREG_EDX && v != TREG_ST0 && v != C67_B2) {
		C67_MV(v, C67_B2);
		v = C67_B2;
	    }

	    C67_IREG_B_REG(inv, v, C67_A0);	// [!R] B.S2x  A0
	    C67_NOP(5);
	    t = ind1;		//return where we need to patch
	    ind1 = ind;
	}
    }
    vtop--;
    return t;
}

/* generate an integer binary operation */
void gen_opi(int op)
{
    int r, fr, opc, t;



( run in 1.239 second using v1.01-cache-2.11-cpan-e1769b4cff6 )