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 |
/*************************************************************/ |