📄 c67-gen.c
字号:
void C67_CMPGTDP(int s1, int s2, int dst){ C67_asm("CMPGTDP.S1", s1, s2, dst);}void C67_CMPEQDP(int s1, int s2, int dst){ C67_asm("CMPEQDP.S1", s1, s2, dst);}void C67_IREG_B_REG(int inv, int r1, int r2) // [!R] B r2{ C67_asm("B.S2", inv, r1, r2);}// call with how many 32 bit words to skip// (0 would branch to the branch instruction)void C67_B_DISP(int disp) // B +2 Branch with constant displacement{ // Branch point is relative to the 8 word fetch packet // // we will assume the text section always starts on an 8 word (32 byte boundary) // // so add in how many words into the fetch packet the branch is C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);}void C67_NOP(int n){ C67_asm("NOP", n, 0, 0);}void C67_ADDK(int n, int r){ ALWAYS_ASSERT(abs(n) < 32767); C67_asm("ADDK", n, r, 0);}void C67_ADDK_PARALLEL(int n, int r){ ALWAYS_ASSERT(abs(n) < 32767); C67_asm("||ADDK", n, r, 0);}void C67_Adjust_ADDK(int *inst, int n){ ALWAYS_ASSERT(abs(n) < 32767); *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);}void C67_MV(int r, int v){ C67_asm("MV.L", 0, r, v);}void C67_DPTRUNC(int r, int v){ C67_asm("DPTRUNC.L", 0, r, v);}void C67_SPTRUNC(int r, int v){ C67_asm("SPTRUNC.L", 0, r, v);}void C67_INTSP(int r, int v){ C67_asm("INTSP.L", 0, r, v);}void C67_INTDP(int r, int v){ C67_asm("INTDP.L", 0, r, v);}void C67_INTSPU(int r, int v){ C67_asm("INTSPU.L", 0, r, v);}void C67_INTDPU(int r, int v){ C67_asm("INTDPU.L", 0, r, v);}void C67_SPDP(int r, int v){ C67_asm("SPDP.L", 0, r, v);}void C67_DPSP(int r, int v) // note regs must be on the same side{ C67_asm("DPSP.L", 0, r, v);}void C67_ADD(int r, int v){ C67_asm("ADD.L", v, r, v);}void C67_SUB(int r, int v){ C67_asm("SUB.L", v, r, v);}void C67_AND(int r, int v){ C67_asm("AND.L", v, r, v);}void C67_OR(int r, int v){ C67_asm("OR.L", v, r, v);}void C67_XOR(int r, int v){ C67_asm("XOR.L", v, r, v);}void C67_ADDSP(int r, int v){ C67_asm("ADDSP.L", v, r, v);}void C67_SUBSP(int r, int v){ C67_asm("SUBSP.L", v, r, v);}void C67_MPYSP(int r, int v){ C67_asm("MPYSP.M", v, r, v);}void C67_ADDDP(int r, int v){ C67_asm("ADDDP.L", v, r, v);}void C67_SUBDP(int r, int v){ C67_asm("SUBDP.L", v, r, v);}void C67_MPYDP(int r, int v){ C67_asm("MPYDP.M", v, r, v);}void C67_MPYI(int r, int v){ C67_asm("MPYI.M", v, r, v);}void C67_SHL(int r, int v){ C67_asm("SHL.S", r, v, v);}void C67_SHRU(int r, int v){ C67_asm("SHRU.S", r, v, v);}void C67_SHR(int r, int v){ C67_asm("SHR.S", r, v, v);}/* load 'r' from value 'sv' */void load(int r, SValue * sv){ int v, t, ft, fc, fr, size = 0, element; BOOL Unsigned = false; SValue v1; fr = sv->r; ft = sv->type.t; fc = sv->c.ul; v = fr & VT_VALMASK; if (fr & VT_LVAL) { if (v == VT_LLOCAL) { v1.type.t = VT_INT; v1.r = VT_LOCAL | VT_LVAL; v1.c.ul = fc; load(r, &v1); fr = r; } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { error("long double not supported"); } else if ((ft & VT_TYPE) == VT_BYTE) { size = 1; } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { size = 1; Unsigned = TRUE; } else if ((ft & VT_TYPE) == VT_SHORT) { size = 2; } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) { size = 2; Unsigned = TRUE; } else if ((ft & VT_BTYPE) == VT_DOUBLE) { size = 8; } else { size = 4; } // check if fc is a positive reference on the stack, // if it is tcc is referencing what it thinks is a parameter // on the stack, so check if it is really in a register. if (v == VT_LOCAL && fc > 0) { int stack_pos = 8; for (t = 0; t < NoCallArgsPassedOnStack; t++) { if (fc == stack_pos) break; stack_pos += TranslateStackToReg[t]; } // param has been pushed on stack, get it like a local var fc = ParamLocOnStack[t] - 8; } if ((fr & VT_VALMASK) < VT_CONST) // check for pure indirect { if (size == 1) { if (Unsigned) C67_LDBU_PTR(v, r); // LDBU *v,r else C67_LDB_PTR(v, r); // LDB *v,r } else if (size == 2) { if (Unsigned) C67_LDHU_PTR(v, r); // LDHU *v,r else C67_LDH_PTR(v, r); // LDH *v,r } else if (size == 4) { C67_LDW_PTR(v, r); // LDW *v,r } else if (size == 8) { C67_LDDW_PTR(v, r); // LDDW *v,r } C67_NOP(4); // NOP 4 return; } else if (fr & VT_SYM) { greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16); C67_MVKL(C67_A0, fc); //r=reg to load, constant C67_MVKH(C67_A0, fc); //r=reg to load, constant if (size == 1) { if (Unsigned) C67_LDBU_PTR(C67_A0, r); // LDBU *A0,r else C67_LDB_PTR(C67_A0, r); // LDB *A0,r } else if (size == 2) { if (Unsigned) C67_LDHU_PTR(C67_A0, r); // LDHU *A0,r else C67_LDH_PTR(C67_A0, r); // LDH *A0,r } else if (size == 4) { C67_LDW_PTR(C67_A0, r); // LDW *A0,r } else if (size == 8) { C67_LDDW_PTR(C67_A0, r); // LDDW *A0,r } C67_NOP(4); // NOP 4 return; } else { element = size; // divide offset in bytes to create element index C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant if (size == 1) { if (Unsigned) C67_LDBU_SP_A0(r); // LDBU r, SP[A0] else C67_LDB_SP_A0(r); // LDB r, SP[A0] } else if (size == 2) { if (Unsigned) C67_LDHU_SP_A0(r); // LDHU r, SP[A0] else C67_LDH_SP_A0(r); // LDH r, SP[A0] } else if (size == 4) { C67_LDW_SP_A0(r); // LDW r, SP[A0] } else if (size == 8) { C67_LDDW_SP_A0(r); // LDDW r, SP[A0] } C67_NOP(4); // NOP 4 return; } } else { if (v == VT_CONST) { if (fr & VT_SYM) { greloc(cur_text_section, sv->sym, ind, R_C60LO16); // rem the inst need to be patched greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16); } C67_MVKL(r, fc); //r=reg to load, constant C67_MVKH(r, fc); //r=reg to load, constant } else if (v == VT_LOCAL) { C67_MVKL(r, fc + 8); //r=reg to load, constant C67 stack points to next free C67_MVKH(r, fc + 8); //r=reg to load, constant C67_ADD(C67_FP, r); // MV v,r v -> r } else if (v == VT_CMP) { C67_MV(C67_compare_reg, r); // MV v,r v -> r } else if (v == VT_JMP || v == VT_JMPI) { t = v & 1; C67_B_DISP(4); // Branch with constant displacement, skip over this branch, load, nop, load C67_MVKL(r, t); // r=reg to load, 0 or 1 (do this while branching) C67_NOP(4); // NOP 4 gsym(fc); // modifies other branches to branch here C67_MVKL(r, t ^ 1); // r=reg to load, 0 or 1 } else if (v != r) { C67_MV(v, r); // MV v,r v -> r if ((ft & VT_BTYPE) == VT_DOUBLE) C67_MV(v + 1, r + 1); // MV v,r v -> r } }}/* store register 'r' in lvalue 'v' */void store(int r, SValue * v){ int fr, bt, ft, fc, size, t, element; ft = v->type.t; fc = v->c.ul; fr = v->r & VT_VALMASK; bt = ft & VT_BTYPE; /* XXX: incorrect if float reg to reg */ if (bt == VT_LDOUBLE) { error("long double not supported"); } else { if (bt == VT_SHORT) size = 2; else if (bt == VT_BYTE) size = 1; else if (bt == VT_DOUBLE) size = 8; else size = 4; if ((v->r & VT_VALMASK) == VT_CONST) { /* constant memory reference */ if (v->r & VT_SYM) { greloc(cur_text_section, v->sym, ind, R_C60LO16); // rem the inst need to be patched greloc(cur_text_section, v->sym, ind + 4, R_C60HI16); } C67_MVKL(C67_A0, fc); //r=reg to load, constant C67_MVKH(C67_A0, fc); //r=reg to load, constant if (size == 1) C67_STB_PTR(r, C67_A0); // STB r, *A0 else if (size == 2) C67_STH_PTR(r, C67_A0); // STH r, *A0 else if (size == 4 || size == 8) C67_STW_PTR(r, C67_A0); // STW r, *A0 if (size == 8) C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1); // STW r, *+A0[1] } else if ((v->r & VT_VALMASK) == VT_LOCAL) { // check case of storing to passed argument that // tcc thinks is on the stack but for C67 is // passed as a reg. However it may have been // saved to the stack, if that reg was required // for a call to a child function if (fc > 0) // argument ?? { // walk through sizes and figure which param int stack_pos = 8; for (t = 0; t < NoCallArgsPassedOnStack; t++) { if (fc == stack_pos) break; stack_pos += TranslateStackToReg[t]; } // param has been pushed on stack, get it like a local var fc = ParamLocOnStack[t] - 8; } if (size == 8) element = 4; else element = size; // divide offset in bytes to create word index C67_MVKL(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant C67_MVKH(C67_A0, (fc / element) + 8 / element); //r=reg to load, constant if (size == 1) C67_STB_SP_A0(r); // STB r, SP[A0] else if (size == 2) C67_STH_SP_A0(r); // STH r, SP[A0] else if (size == 4 || size == 8) C67_STW_SP_A0(r); // STW r, SP[A0] if (size == 8) { C67_ADDK(1, C67_A0); // ADDK 1,A0 C67_STW_SP_A0(r + 1); // STW r, SP[A0] } } else { if (size == 1) C67_STB_PTR(r, fr); // STB r, *fr else if (size == 2) C67_STH_PTR(r, fr); // STH r, *fr else if (size == 4 || size == 8) C67_STW_PTR(r, fr); // STW r, *fr if (size == 8) { C67_STW_PTR_PRE_INC(r + 1, fr, 1); // STW r, *+fr[1] } } }}/* 'is_jmp' is '1' if it is a jump */static void gcall_or_jmp(int is_jmp){ int r; Sym *sym; if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* constant case */ if (vtop->r & VT_SYM) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -