2537 lines · 69.3 KB · C
RawDownload
/* *  TMS320C67xx code generator for TCC *  *  Copyright (c) 2001, 2002 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */ #ifdef TARGET_DEFS_ONLY /* #define ASSEMBLY_LISTING_C67 */ /* number of available registers */#define NB_REGS            24 /* a register can belong to several classes. The classes must be   sorted from more general to more precise (see gv2() code which does   assumptions on it). */#define RC_INT     0x0001	/* generic integer register */#define RC_FLOAT   0x0002	/* generic float register */#define RC_EAX     0x0004#define RC_ST0     0x0008#define RC_ECX     0x0010#define RC_EDX     0x0020#define RC_INT_BSIDE  0x00000040	/* generic integer register  on b side */#define RC_C67_A4     0x00000100#define RC_C67_A5     0x00000200#define RC_C67_B4     0x00000400#define RC_C67_B5     0x00000800#define RC_C67_A6     0x00001000#define RC_C67_A7     0x00002000#define RC_C67_B6     0x00004000#define RC_C67_B7     0x00008000#define RC_C67_A8     0x00010000#define RC_C67_A9     0x00020000#define RC_C67_B8     0x00040000#define RC_C67_B9     0x00080000#define RC_C67_A10    0x00100000#define RC_C67_A11    0x00200000#define RC_C67_B10    0x00400000#define RC_C67_B11    0x00800000#define RC_C67_A12    0x01000000#define RC_C67_A13    0x02000000#define RC_C67_B12    0x04000000#define RC_C67_B13    0x08000000#define RC_IRET    RC_C67_A4	/* function return: integer register */#define RC_IRE2    RC_C67_A5	/* function return: second integer register */#define RC_FRET    RC_C67_A4	/* function return: float register */ /* pretty names for the registers */enum {    TREG_EAX = 0,		// really A2    TREG_ECX,			// really A3    TREG_EDX,			// really B0    TREG_ST0,			// really B1    TREG_C67_A4,    TREG_C67_A5,    TREG_C67_B4,    TREG_C67_B5,    TREG_C67_A6,    TREG_C67_A7,    TREG_C67_B6,    TREG_C67_B7,    TREG_C67_A8,    TREG_C67_A9,    TREG_C67_B8,    TREG_C67_B9,    TREG_C67_A10,    TREG_C67_A11,    TREG_C67_B10,    TREG_C67_B11,    TREG_C67_A12,    TREG_C67_A13,    TREG_C67_B12,    TREG_C67_B13,}; /* return registers for function */#define REG_IRET TREG_C67_A4	/* single word int return register */#define REG_IRE2 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 /******************************************************/#else /* ! TARGET_DEFS_ONLY *//******************************************************/#define USING_GLOBALS#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,    /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,    // only allow even regs for floats (allow for doubles)    /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,    /* A4  */ RC_C67_A4,    /* A5  */ RC_C67_A5,    /* B4  */ RC_C67_B4,    /* B5  */ RC_C67_B5,    /* A6  */ RC_C67_A6,    /* A7  */ RC_C67_A7,    /* B6  */ RC_C67_B6,    /* B7  */ RC_C67_B7,    /* A8  */ RC_C67_A8,    /* A9  */ RC_C67_A9,    /* B8  */ RC_C67_B8,    /* B9  */ RC_C67_B9,    /* A10  */ RC_C67_A10,    /* A11  */ RC_C67_A11,    /* B10  */ RC_C67_B10,    /* B11  */ RC_C67_B11,    /* A12  */ RC_C67_A10,    /* A13  */ RC_C67_A11,    /* B12  */ RC_C67_B10,    /* B13  */ RC_C67_B11}; // 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// the stack offsets so we can translate to the appropriate // reg (pair) #define NoCallArgsPassedOnStack 10int NoOfCurFuncArgs;int TranslateStackToReg[NoCallArgsPassedOnStack];int ParamLocOnStack[NoCallArgsPassedOnStack];int TotalBytesPushedOnStack; #ifndef FALSE# define FALSE 0# define TRUE 1#endif #undef BOOL#define BOOL int #define ALWAYS_ASSERT(x) \do {\   if (!(x))\       tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\} while (0) /******************************************************/static unsigned long func_sub_sp_offset;static int func_ret_sub; static BOOL C67_invert_test;static int C67_compare_reg; #ifdef ASSEMBLY_LISTING_C67FILE *f = NULL;#endif void C67_g(int c){    int ind1;    if (nocode_wanted)        return;#ifdef ASSEMBLY_LISTING_C67    fprintf(f, " %08X", c);#endif    ind1 = ind + 4;    if (ind1 > (int) cur_text_section->data_allocated)	section_realloc(cur_text_section, ind1);    cur_text_section->data[ind] = c & 0xff;    cur_text_section->data[ind + 1] = (c >> 8) & 0xff;    cur_text_section->data[ind + 2] = (c >> 16) & 0xff;    cur_text_section->data[ind + 3] = (c >> 24) & 0xff;    ind = ind1;}  /* output a symbol and patch all calls to it */void gsym_addr(int t, int a){    int n, *ptr;    while (t) {	ptr = (int *) (cur_text_section->data + t);	{	    Sym *sym; 	    // extract 32 bit address from MVKH/MVKL	    n = ((*ptr >> 7) & 0xffff);	    n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; 	    // define a label that will be relocated 	    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);	    greloc(cur_text_section, sym, t, R_C60LO16);	    greloc(cur_text_section, sym, t + 4, R_C60HI16); 	    // clear out where the pointer was 	    *ptr &= ~(0xffff << 7);	    *(ptr + 1) &= ~(0xffff << 7);	}	t = n;    }} // these are regs that tcc doesn't really know about, // but assign them unique values so the mapping routines// can distinguish them #define C67_A0 105#define C67_SP 106#define C67_B3 107#define C67_FP 108#define C67_B2 109#define C67_CREG_ZERO -1	/* Special code for no condition reg test */  int ConvertRegToRegClass(int r){    // only works for A4-B13     return RC_C67_A4 << (r - TREG_C67_A4);}  // map TCC reg to C67 reg number int C67_map_regn(int r){    if (r == 0)			// normal tcc regs	return 0x2;		// A2    else if (r == 1)		// normal tcc regs	return 3;		// A3    else if (r == 2)		// normal tcc regs	return 0;		// B0    else if (r == 3)		// normal tcc regs	return 1;		// B1    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs	return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;    else if (r == C67_A0)	return 0;		// set to A0 (offset reg)    else if (r == C67_B2)	return 2;		// set to B2 (offset reg)    else if (r == C67_B3)	return 3;		// set to B3 (return address reg)    else if (r == C67_SP)	return 15;		// set to SP (B15) (offset reg)    else if (r == C67_FP)	return 15;		// set to FP (A15) (offset reg)    else if (r == C67_CREG_ZERO)	return 0;		// Special code for no condition reg test    else	ALWAYS_ASSERT(FALSE);     return 0;} // mapping from tcc reg number to // C67 register to condition code field//// valid condition code regs are://// tcc reg 2 ->B0 -> 1// tcc reg 3 ->B1 -> 2// tcc reg 0 -> A2 -> 5// tcc reg 1 -> A3 -> X// tcc reg      B2 -> 3 int C67_map_regc(int r){    if (r == 0)			// normal tcc regs	return 0x5;    else if (r == 2)		// normal tcc regs	return 0x1;    else if (r == 3)		// normal tcc regs	return 0x2;    else if (r == C67_B2)	// normal tcc regs	return 0x3;    else if (r == C67_CREG_ZERO)	return 0;		// Special code for no condition reg test    else	ALWAYS_ASSERT(FALSE);     return 0;}  // map TCC reg to C67 reg side A or B int C67_map_regs(int r){    if (r == 0)			// normal tcc regs	return 0x0;    else if (r == 1)		// normal tcc regs	return 0x0;    else if (r == 2)		// normal tcc regs	return 0x1;    else if (r == 3)		// normal tcc regs	return 0x1;    else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs	return (r & 2) >> 1;    else if (r == C67_A0)	return 0;		// set to A side     else if (r == C67_B2)	return 1;		// set to B side     else if (r == C67_B3)	return 1;		// set to B side    else if (r == C67_SP)	return 0x1;		// set to SP (B15) B side     else if (r == C67_FP)	return 0x0;		// set to FP (A15) A side     else	ALWAYS_ASSERT(FALSE);     return 0;} int C67_map_S12(char *s){    if (strstr(s, ".S1") != NULL)	return 0;    else if (strcmp(s, ".S2"))	return 1;    else	ALWAYS_ASSERT(FALSE);     return 0;} int C67_map_D12(char *s){    if (strstr(s, ".D1") != NULL)	return 0;    else if (strcmp(s, ".D2"))	return 1;    else	ALWAYS_ASSERT(FALSE);     return 0;}   void C67_asm(char *s, int a, int b, int c){    BOOL xpath; #ifdef ASSEMBLY_LISTING_C67    if (!f) {	f = fopen("TCC67_out.txt", "wt");    }    fprintf(f, "%04X ", ind);#endif     if (strstr(s, "MVKL") == s) {	C67_g((C67_map_regn(b) << 23) |	      ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));    } else if (strstr(s, "MVKH") == s) {	C67_g((C67_map_regn(b) << 23) |	      (((a >> 16) & 0xffff) << 7) |	      (0x1a << 2) | (C67_map_regs(b) << 1));    } else if (strstr(s, "STW.D SP POST DEC") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//SP B15	      (2 << 13) |	//ucst5 (must keep 8 byte boundary !!)	      (0xa << 9) |	//mode a = post dec ucst	      (0 << 8) |	//r (LDDW bit 0)	      (1 << 7) |	//y D1/D2 use B side	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STB.D *+SP[A0]") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//base reg A15	      (0 << 13) |	//offset reg A0	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg	      (0 << 8) |	//r (LDDW bit 0)	      (0 << 7) |	//y D1/D2 A side	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STH.D *+SP[A0]") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//base reg A15	      (0 << 13) |	//offset reg A0	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg	      (0 << 8) |	//r (LDDW bit 0)	      (0 << 7) |	//y D1/D2 A side	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STB.D *+SP[A0]") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//base reg A15	      (0 << 13) |	//offset reg A0	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg	      (0 << 8) |	//r (LDDW bit 0)	      (0 << 7) |	//y D1/D2 A side	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STH.D *+SP[A0]") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//base reg A15	      (0 << 13) |	//offset reg A0	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg	      (0 << 8) |	//r (LDDW bit 0)	      (0 << 7) |	//y D1/D2 A side	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STW.D *+SP[A0]") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (15 << 18) |	//base reg A15	      (0 << 13) |	//offset reg A0	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg	      (0 << 8) |	//r (LDDW bit 0)	      (0 << 7) |	//y D1/D2 A side	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STW.D *") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (C67_map_regn(b) << 18) |	//base reg A0	      (0 << 13) |	//cst5	      (1 << 9) |	//mode 1 = pos cst offset	      (0 << 8) |	//r (LDDW bit 0)	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STH.D *") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (C67_map_regn(b) << 18) |	//base reg A0	      (0 << 13) |	//cst5	      (1 << 9) |	//mode 1 = pos cst offset	      (0 << 8) |	//r (LDDW bit 0)	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STB.D *") == s) {	C67_g((C67_map_regn(a) << 23) |	//src	      (C67_map_regn(b) << 18) |	//base reg A0	      (0 << 13) |	//cst5	      (1 << 9) |	//mode 1 = pos cst offset	      (0 << 8) |	//r (LDDW bit 0)	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "STW.D +*") == s) {	ALWAYS_ASSERT(c < 32);	C67_g((C67_map_regn(a) << 23) |	//src	      (C67_map_regn(b) << 18) |	//base reg A0	      (c << 13) |	//cst5	      (1 << 9) |	//mode 1 = pos cst offset	      (0 << 8) |	//r (LDDW bit 0)	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU 	      (1 << 2) |	//opcode	      (C67_map_regs(a) << 1) |	//side of src	      (0 << 0));	//parallel    } else if (strstr(s, "LDW.D SP PRE INC") == s) {	C67_g((C67_map_regn(a) << 23) |	//dst	      (15 << 18) |	//base reg B15	      (2 << 13) |	//ucst5 (must keep 8 byte boundary)

Lines 1–500 of 2537.