⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c67-gen.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 5 页
字号:
	    /* relocation case */	    // get add into A0, then start the jump B3	    greloc(cur_text_section, vtop->sym, ind, R_C60LO16);	// rem the inst need to be patched	    greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);	    C67_MVKL(C67_A0, 0);	//r=reg to load, constant	    C67_MVKH(C67_A0, 0);	//r=reg to load, constant	    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	//  B.S2x  A0	    if (is_jmp) {		C67_NOP(5);	// simple jump, just put NOP	    } else {		// Call, must load return address into B3 during delay slots		sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address		greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched		greloc(cur_text_section, sym, ind + 4, R_C60HI16);		C67_MVKL(C67_B3, 0);	//r=reg to load, constant		C67_MVKH(C67_B3, 0);	//r=reg to load, constant		C67_NOP(3);	// put remaining NOPs	    }	} else {	    /* put an empty PC32 relocation */	    ALWAYS_ASSERT(FALSE);	}    } else {	/* otherwise, indirect call */	r = gv(RC_INT);	C67_IREG_B_REG(0, C67_CREG_ZERO, r);	//  B.S2x  r	if (is_jmp) {	    C67_NOP(5);		// simple jump, just put NOP	} else {	    // Call, must load return address into B3 during delay slots	    sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address	    greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched	    greloc(cur_text_section, sym, ind + 4, R_C60HI16);	    C67_MVKL(C67_B3, 0);	//r=reg to load, constant	    C67_MVKH(C67_B3, 0);	//r=reg to load, constant	    C67_NOP(3);		// put remaining NOPs	}    }}/* generate function call with address in (vtop->t, vtop->c) and free function   context. Stack entry is popped */void gfunc_call(int nb_args){    int i, r, size = 0;    int args_sizes[NoCallArgsPassedOnStack];    if (nb_args > NoCallArgsPassedOnStack) {	error("more than 10 function params not currently supported");	// handle more than 10, put some on the stack    }    for (i = 0; i < nb_args; i++) {	if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {	    ALWAYS_ASSERT(FALSE);	} else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {	    ALWAYS_ASSERT(FALSE);	} else {	    /* simple type (currently always same size) */	    /* XXX: implicit cast ? */	    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {		error("long long not supported");	    } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {		error("long double not supported");	    } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {		size = 8;	    } else {		size = 4;	    }	    // put the parameter into the corresponding reg (pair)	    r = gv(RC_C67_A4 << (2 * i));	    // must put on stack because with 1 pass compiler , no way to tell	    // if an up coming nested call might overwrite these regs	    C67_PUSH(r);	    if (size == 8) {		C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3);	// STW  r, *+SP[3] (go back and put the other)	    }	    args_sizes[i] = size;	}	vtop--;    }    // POP all the params on the stack into registers for the    // immediate call (in reverse order)    for (i = nb_args - 1; i >= 0; i--) {	if (args_sizes[i] == 8)	    C67_POP_DW(TREG_C67_A4 + i * 2);	else	    C67_POP(TREG_C67_A4 + i * 2);    }    gcall_or_jmp(0);    vtop--;}// to be compatible with Code Composer for the C67// the first 10 parameters must be passed in registers// (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and// ending with B12:B13.//// When a call is made, if the caller has its parameters// in regs A4-B13 these must be saved before/as the call // parameters are loaded and restored upon return (or if/when needed)./* generate function prolog of type 't' */void gfunc_prolog(CType * func_type){    int addr, align, size, func_call, i;    Sym *sym;    CType *type;    sym = func_type->ref;    func_call = sym->r;    addr = 8;    /* if the function returns a structure, then add an       implicit pointer parameter */    func_vt = sym->type;    if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {	func_vc = addr;	addr += 4;    }    NoOfCurFuncArgs = 0;    /* define parameters */    while ((sym = sym->next) != NULL) {	type = &sym->type;	sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);	size = type_size(type, &align);	size = (size + 3) & ~3;	// keep track of size of arguments so	// we can translate where tcc thinks they	// are on the stack into the appropriate reg	TranslateStackToReg[NoOfCurFuncArgs] = size;	NoOfCurFuncArgs++;#ifdef FUNC_STRUCT_PARAM_AS_PTR	/* structs are passed as pointer */	if ((type->t & VT_BTYPE) == VT_STRUCT) {	    size = 4;	}#endif	addr += size;    }    func_ret_sub = 0;    /* pascal type call ? */    if (func_call == FUNC_STDCALL)	func_ret_sub = addr - 8;    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;    switch (op) {    case '+':    case TOK_ADDC1:		/* add with carry generation */	opc = 0;      gen_op8:// C67 can't do const compares, must load into a reg// so just go to gv2 directly - tktk	if (op >= TOK_ULT && op <= TOK_GT)	    gv2(RC_INT_BSIDE, RC_INT);	// make sure r (src1) is on the B Side of CPU	else	    gv2(RC_INT, RC_INT);	r = vtop[-1].r;	fr = vtop[0].r;	C67_compare_reg = C67_B2;	if (op == TOK_LT) {	    C67_CMPLT(r, fr, C67_B2);	    C67_invert_test = false;	} else if (op == TOK_GE) {	    C67_CMPLT(r, fr, C67_B2);	    C67_invert_test = true;	} else if (op == TOK_GT) {	    C67_CMPGT(r, fr, C67_B2);	    C67_invert_test = false;	} else if (op == TOK_LE) {	    C67_CMPGT(r, fr, C67_B2);	    C67_invert_test = true;	} else if (op == TOK_EQ) {	    C67_CMPEQ(r, fr, C67_B2);	    C67_invert_test = false;	} else if (op == TOK_NE) {	    C67_CMPEQ(r, fr, C67_B2);	    C67_invert_test = true;	} else if (op == TOK_ULT) {	    C67_CMPLTU(r, fr, C67_B2);	    C67_invert_test = false;	} else if (op == TOK_UGE) {	    C67_CMPLTU(r, fr, C67_B2);	    C67_invert_test = true;	} else if (op == TOK_UGT) {	    C67_CMPGTU(r, fr, C67_B2);	    C67_invert_test = false;	} else if (op == TOK_ULE) {	    C67_CMPGTU(r, fr, C67_B2);	    C67_invert_test = true;	} else if (op == '+')	    C67_ADD(fr, r);	// ADD  r,fr,r	else if (op == '-')	    C67_SUB(fr, r);	// SUB  r,fr,r	else if (op == '&')	    C67_AND(fr, r);	// AND  r,fr,r	else if (op == '|')	    C67_OR(fr, r);	// OR  r,fr,r	else if (op == '^')	    C67_XOR(fr, r);	// XOR  r,fr,r	else	    ALWAYS_ASSERT(FALSE);	vtop--;	if (op >= TOK_ULT && op <= TOK_GT) {	    vtop->r = VT_CMP;	    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 '/'

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -