📄 c67-gen.c
字号:
/* * 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 *///#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_LRET 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,};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};/* 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// the stack offsets so we can translate to the appropriate // reg (pair)#define NoCallArgsPassedOnStack 10int NoOfCurFuncArgs;int TranslateStackToReg[NoCallArgsPassedOnStack];int ParamLocOnStack[NoCallArgsPassedOnStack];int TotalBytesPushedOnStack;/* 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_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;#ifdef ASSEMBLY_LISTING_C67FILE *f = NULL;#endifvoid C67_g(int c){ int ind1;#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; }}void gsym(int t){ gsym_addr(t, ind);}// these are regs that tcc doesn't really know about, // but asign them unique values so the mapping routines// can distinquish 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 testint ConvertRegToRegClass(int r){ // only works for A4-B13 return RC_C67_A4 << (r - TREG_C67_A4);}// map TCC reg to C67 reg numberint 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 -> 3int 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 Bint 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -