Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6428 → Rev 6429

/programs/develop/ktcc/trunk/source/c67-gen.c
18,8 → 18,10
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
 
//#define ASSEMBLY_LISTING_C67
#ifdef TARGET_DEFS_ONLY
 
/* #define ASSEMBLY_LISTING_C67 */
 
/* number of available registers */
#define NB_REGS 24
 
85,7 → 87,47
TREG_C67_B13,
};
 
int reg_classes[NB_REGS] = {
/* return registers for function */
#define REG_IRET TREG_C67_A4 /* single word int return register */
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
#define REG_FRET TREG_C67_A4 /* float return register */
 
/* defined if function parameters must be evaluated in reverse order */
/* #define INVERT_FUNC_PARAMS */
 
/* defined if structures are passed as pointers. Otherwise structures
are directly pushed on stack. */
/* #define FUNC_STRUCT_PARAM_AS_PTR */
 
/* pointer size, in bytes */
#define PTR_SIZE 4
 
/* long double size and alignment, in bytes */
#define LDOUBLE_SIZE 12
#define LDOUBLE_ALIGN 4
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
 
/******************************************************/
/* ELF defines */
 
#define EM_TCC_TARGET EM_C60
 
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_C60_32
#define R_DATA_PTR R_C60_32
#define R_JMP_SLOT R_C60_JMP_SLOT
#define R_COPY R_C60_COPY
 
#define ELF_START_ADDR 0x00000400
#define ELF_PAGE_SIZE 0x1000
 
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#include "tcc.h"
 
ST_DATA const int reg_classes[NB_REGS] = {
/* eax */ RC_INT | RC_FLOAT | RC_EAX,
// only allow even regs for floats (allow for doubles)
/* ecx */ RC_INT | RC_ECX,
114,18 → 156,6
/* B13 */ RC_C67_B11
};
 
/* return registers for function */
#define REG_IRET TREG_C67_A4 /* single word int return register */
#define REG_LRET TREG_C67_A5 /* second word return register (for long long) */
#define REG_FRET TREG_C67_A4 /* float return register */
 
 
#define ALWAYS_ASSERT(x) \
do {\
if (!(x))\
error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
} while (0)
 
// although tcc thinks it is passing parameters on the stack,
// the C67 really passes up to the first 10 params in special
// regs or regs pairs (for 64 bit params). So keep track of
132,7 → 162,6
// the stack offsets so we can translate to the appropriate
// reg (pair)
 
 
#define NoCallArgsPassedOnStack 10
int NoOfCurFuncArgs;
int TranslateStackToReg[NoCallArgsPassedOnStack];
139,42 → 168,24
int ParamLocOnStack[NoCallArgsPassedOnStack];
int TotalBytesPushedOnStack;
 
/* defined if function parameters must be evaluated in reverse order */
#ifndef FALSE
# define FALSE 0
# define TRUE 1
#endif
 
//#define INVERT_FUNC_PARAMS
#undef BOOL
#define BOOL int
 
/* defined if structures are passed as pointers. Otherwise structures
are directly pushed on stack. */
//#define FUNC_STRUCT_PARAM_AS_PTR
#define ALWAYS_ASSERT(x) \
do {\
if (!(x))\
tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
} while (0)
 
/* pointer size, in bytes */
#define PTR_SIZE 4
 
/* long double size and alignment, in bytes */
#define LDOUBLE_SIZE 12
#define LDOUBLE_ALIGN 4
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN 8
 
/******************************************************/
/* ELF defines */
 
#define EM_TCC_TARGET EM_C60
 
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_C60_32
#define R_JMP_SLOT R_C60_JMP_SLOT
#define R_COPY R_C60_COPY
 
#define ELF_START_ADDR 0x00000400
#define ELF_PAGE_SIZE 0x1000
 
/******************************************************/
 
static unsigned long func_sub_sp_offset;
static int func_ret_sub;
 
 
static BOOL C67_invert_test;
static int C67_compare_reg;
 
182,7 → 193,6
FILE *f = NULL;
#endif
 
 
void C67_g(int c)
{
int ind1;
235,8 → 245,8
}
 
// these are regs that tcc doesn't really know about,
// but asign them unique values so the mapping routines
// can distinquish them
// but assign them unique values so the mapping routines
// can distinguish them
 
#define C67_A0 105
#define C67_SP 106
243,7 → 253,7
#define C67_B3 107
#define C67_FP 108
#define C67_B2 109
#define C67_CREG_ZERO -1 // Special code for no condition reg test
#define C67_CREG_ZERO -1 /* Special code for no condition reg test */
 
 
int ConvertRegToRegClass(int r)
1552,12 → 1562,12
void load(int r, SValue * sv)
{
int v, t, ft, fc, fr, size = 0, element;
BOOL Unsigned = false;
BOOL Unsigned = FALSE;
SValue v1;
 
fr = sv->r;
ft = sv->type.t;
fc = sv->c.ul;
fc = sv->c.i;
 
v = fr & VT_VALMASK;
if (fr & VT_LVAL) {
1564,11 → 1574,11
if (v == VT_LLOCAL) {
v1.type.t = VT_INT;
v1.r = VT_LOCAL | VT_LVAL;
v1.c.ul = fc;
v1.c.i = fc;
load(r, &v1);
fr = r;
} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
error("long double not supported");
tcc_error("long double not supported");
} else if ((ft & VT_TYPE) == VT_BYTE) {
size = 1;
} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1716,13 → 1726,13
int fr, bt, ft, fc, size, t, element;
 
ft = v->type.t;
fc = v->c.ul;
fc = v->c.i;
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");
tcc_error("long double not supported");
} else {
if (bt == VT_SHORT)
size = 2;
1869,6 → 1879,13
}
}
 
/* Return the number of registers needed to return the struct, or 0 if
returning via struct pointer. */
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
*ret_align = 1; // Never have to re-align return values for x86-64
return 0;
}
 
/* generate function call with address in (vtop->t, vtop->c) and free function
context. Stack entry is popped */
void gfunc_call(int nb_args)
1877,7 → 1894,7
int args_sizes[NoCallArgsPassedOnStack];
 
if (nb_args > NoCallArgsPassedOnStack) {
error("more than 10 function params not currently supported");
tcc_error("more than 10 function params not currently supported");
// handle more than 10, put some on the stack
}
 
1884,8 → 1901,6
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 ? */
1892,9 → 1907,9
 
 
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
error("long long not supported");
tcc_error("long long not supported");
} else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
error("long double not supported");
tcc_error("long double not supported");
} else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
size = 8;
} else {
1954,6 → 1969,7
/* if the function returns a structure, then add an
implicit pointer parameter */
func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
func_vc = addr;
addr += 4;
1964,7 → 1980,7
/* define parameters */
while ((sym = sym->next) != NULL) {
type = &sym->type;
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr);
size = type_size(type, &align);
size = (size + 3) & ~3;
 
2090,13 → 2106,12
/* && 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;
n = vtop->c.i;
while (n != 0) {
p = (int *) (cur_text_section->data + n);
 
2112,38 → 2127,7
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;
}
2178,34 → 2162,34
 
if (op == TOK_LT) {
C67_CMPLT(r, fr, C67_B2);
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_GE) {
C67_CMPLT(r, fr, C67_B2);
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_GT) {
C67_CMPGT(r, fr, C67_B2);
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_LE) {
C67_CMPGT(r, fr, C67_B2);
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_EQ) {
C67_CMPEQ(r, fr, C67_B2);
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_NE) {
C67_CMPEQ(r, fr, C67_B2);
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_ULT) {
C67_CMPLTU(r, fr, C67_B2);
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_UGE) {
C67_CMPLTU(r, fr, C67_B2);
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_UGT) {
C67_CMPGTU(r, fr, C67_B2);
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_ULE) {
C67_CMPGTU(r, fr, C67_B2);
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == '+')
C67_ADD(fr, r); // ADD r,fr,r
else if (op == '-')
2319,13 → 2303,13
gv2(RC_FLOAT, RC_FLOAT); // make sure src2 is on b side
 
ft = vtop->type.t;
fc = vtop->c.ul;
fc = vtop->c.i;
r = vtop->r;
fr = vtop[-1].r;
 
 
if ((ft & VT_BTYPE) == VT_LDOUBLE)
error("long doubles not supported");
tcc_error("long doubles not supported");
 
if (op >= TOK_ULT && op <= TOK_GT) {
 
2340,7 → 2324,7
else
C67_CMPLTSP(r, fr, C67_B2);
 
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_GE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPLTDP(r, fr, C67_B2);
2347,7 → 2331,7
else
C67_CMPLTSP(r, fr, C67_B2);
 
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_GT) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
2354,7 → 2338,7
else
C67_CMPGTSP(r, fr, C67_B2);
 
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_LE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPGTDP(r, fr, C67_B2);
2361,7 → 2345,7
else
C67_CMPGTSP(r, fr, C67_B2);
 
C67_invert_test = true;
C67_invert_test = TRUE;
} else if (op == TOK_EQ) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
2368,7 → 2352,7
else
C67_CMPEQSP(r, fr, C67_B2);
 
C67_invert_test = false;
C67_invert_test = FALSE;
} else if (op == TOK_NE) {
if ((ft & VT_BTYPE) == VT_DOUBLE)
C67_CMPEQDP(r, fr, C67_B2);
2375,7 → 2359,7
else
C67_CMPEQSP(r, fr, C67_B2);
 
C67_invert_test = true;
C67_invert_test = TRUE;
} else {
ALWAYS_ASSERT(FALSE);
}
2477,7 → 2461,7
r = vtop->r;
 
if (t != VT_INT)
error("long long not supported");
tcc_error("long long not supported");
else {
if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
C67_DPTRUNC(r, r);
2544,5 → 2528,22
vtop--;
}
 
/* end of X86 code generator */
/* Save the stack pointer onto the stack and return the location of its address */
ST_FUNC void gen_vla_sp_save(int addr) {
tcc_error("variable length arrays unsupported for this target");
}
 
/* Restore the SP from a location on the stack */
ST_FUNC void gen_vla_sp_restore(int addr) {
tcc_error("variable length arrays unsupported for this target");
}
 
/* Subtract from the stack pointer, and push the resulting value onto the stack */
ST_FUNC void gen_vla_alloc(CType *type, int align) {
tcc_error("variable length arrays unsupported for this target");
}
 
/* end of C67 code generator */
/*************************************************************/
#endif
/*************************************************************/