Alien-TinyCC
view release on metacpan or search on metacpan
src/c67-gen.c view on Meta::CPAN
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
src/c67-gen.c view on Meta::CPAN
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)
C67_CMPLTDP(r, fr, C67_B2);
else
C67_CMPLTSP(r, fr, C67_B2);
C67_invert_test = TRUE;
} else if (op == TOK_GT) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
else
C67_CMPGTSP(r, fr, C67_B2);
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'
( run in 0.532 second using v1.01-cache-2.11-cpan-9bca49b1385 )