/************************************************************* * File: tools/ghs.c * Purpose: The pmcc compiler driver for the Green Hills toolset * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 971211 Created from cygelf.c * 971231 Changed order of section in lnk file * 971231 Added option for -nosda * 980102 Added -noS5 option to gsrec * 980102 Fixed prob w pmcc w/o -o * 980113 Changed -O to -OS. Big size reduction! * 980312 Changed winbootdir to windir. NT doesn't have winbootdir. * 981020 Removed x from -l option. Added -LCOMP_ROOT/mips_r3 & -larch. * 981027 Changed mips_r3 to mips_sf. * 981028 Fixed mips_r3 selector to use table. * 981028 Fixed -cpu=r4000 option. Was -mcpu=r4000. * 981028 Added -soft-float option. * 981028 Moved std opts to misc.c. * 981118 Incorporated "-larch last" fix. * 981215 Verified against GHS 1.8.9 * 981217 Fixed prob w wrong lib used when lendef. */ #include #include #include #include "../include/defines.h" #include "misc.h" #define DYNDEFS #ifdef MSDOS #define LINKER "lx" char cmdchar[] = "@"; #endif /* set various defaults */ int vflag = 0; /* verbose flag */ int fast = 1; int ssyms_flag; int syms = 1; char *chksum = ""; char *ofile = "a"; char *initial_lc = "-lc -larch"; int driver; char cmdfile[] = "cmdfile"; char tmp[LNMAX],tmp2[LNMAX]; char *ENDIAN,*Gnum,*LSIPMCC; char *COMP_HOST_ROOT,*SDEROOT,*TMPDIR; Str flags,cflags,asflags,ldflags,ppflags,ofiles,llist,ilist,LIBS,files; Str *strlst[] = {&flags,&cflags,&asflags,&ldflags,&ppflags,&ofiles, &llist,&ilist,&LIBS,&files,0}; char *LSIPKG; char LIBC[100]; char objfile[100]; char tstart[10]; char *dstart; char *CC; int nfiles,msim; char stoppoint; int SZ; char tmppath[200]; char mname[32]; /* module object name */ char *clientpc; char *getDef(); char *ld_cmd_file1[] = { "-sec", "{", 0}; /* .text 0x9fc00000 : */ char *ld_cmd_file2[] = { ".syscall :", ".secinfo :", ".fixaddr :", ".fixtype :", ".robase align(8) :", ".rodata :", ".romdata ROM(.data) :", ".romsdata ROM(.sdata) :", 0}; /* .sdabase 0x80000100 : */ char *ld_cmd_file3[] = { ".data :", ".sdata :", ".sbss :", ".bss :", ".heap align(8) pad(0x100000) :", ".stack align(8) pad(0x80000) :", "}", 0}; extern int long_cmds_ok; /* the defines and table are how I figure out which library to link with */ #define MODE_MSK 3 #define MODE_4K 1 #define MODE_16 2 #define MODE_SF 4 #define MODE_LE 8 char *lib_mode[] = { "mips_r3", "mips_r4", "mips_16", 0, "mips_sf", "mips_sf", "mips_sf", 0, "mipsl_r3", "mipsl_r4", "mipsl_16", 0, "mipsl_sf", "mipsl_sf", "mipsl_sf", 0}; /************************************************************* * main(argc,argv) */ main(argc,argv) int argc; char *argv[]; { int i,status,SZ,sz; char *e,*p,h[20],*redir; char tmp2[100]; char *vtmp,*fmt,*file; SZ = 0; if (! (LSIPKG=getenv("LSIPKG"))) { fprintf(stderr,"pmcc: LSIPKG not set\n"); Exit(1); } #ifdef MSDOS if (getenv("windir")) long_cmds_ok = 1; #else long_cmds_ok = 1; #endif Strcpy(&LIBS,""); #ifdef DYNDEFS sprintf(tmp,"%s/include/defines.h",LSIPKG); readDefs(tmp); if (getDef("SREC")) fast = 0; if (clientpc=getDef("CLIENTPC")) strcpy(tstart,&clientpc[2]); else strcpy(tstart,"80020000"); if (getDef("LENDEF")) ENDIAN = "l"; else ENDIAN = "b"; #else #ifdef SREC fast = 0; #endif #ifdef CLIENTPC sprintf(tstart,"%08lx",CLIENTPC); #else strcpy(tstart,"80020000"); #endif #endif #ifdef MSDOS #if 0 if (! (TMPDIR=getenv("TMPDIR"))) { fprintf(stderr,"pmcc: TMPDIR not set\n"); Exit(1); } p = tmppath + sprintf(tmppath,"%s",TMPDIR); strcat(tmppath,"/PMXXXXXX"); mktemp(p); #endif #endif /* for backward compatability we set LSIPMCC */ if (! (LSIPMCC=getenv("LSIPMCC"))) LSIPMCC = ""; /* Select default Endianess. */ #ifdef LENDEF ENDIAN = "l"; #else ENDIAN = "b"; #endif Gnum = "o"; CC = "ccmipe"; stdcrt0 = "%s/lib/%s%s/crt0.o"; sprintf(tmp,"-I%s/include",LSIPKG); Strcpy(&ilist,tmp); sprintf(tmp,"-L%s/lib/%%s%%s",LSIPKG); Strcpy(&llist,tmp); sprintf(tmp,"-DPMCC -DGHS %s",LSIPMCC); Strcpy(&flags,tmp); getargs(argc,argv); if (vflag) addarg(&flags,"-v"); if (strequ(ENDIAN,"l")) CC = "ccmipel"; strcpy(objfile,ofile); if (strequ(ofile,"a")) strcpy(objfile,"a.out"); if (stoppoint==0) { addarg(&cflags,"-c"); /* never want the cc driver to call ld */ addarg(&asflags,"-c"); /* never want the cc driver to call ld */ addarg(&ldflags,"-o"); addarg(&ldflags,objfile); } sprintf(tmp,llist.str,ENDIAN,Gnum,ENDIAN,Gnum); addarg(&ldflags,tmp); addarg(&cflags,ilist.str); addarg(&ppflags,ilist.str); addarg(&asflags,"-DLANGUAGE_ASSEMBLY"); addarg(&cflags,"-DLANGUAGE_C"); if (strequ(ENDIAN,"l")) { addarg(&cflags,"-DMIPSEL"); addarg(&ppflags,"-DMIPSEL"); } else { addarg(&cflags,"-DMIPSEB"); addarg(&ppflags,"-DMIPSEB"); } if (nfiles == 0) { printf("Fatal error: no files specified.\n"); exit(1); } /* now invoke the compiler */ for (i=0;i %s\n",ifn,ofn); flag = 0; ifp = fopen(ifn,"r"); if (ifp == 0) { fprintf(stderr,"Can't open %s\n",ifn); Exit(1); } ofp = fopen(ofn,"w"); if (ofp == 0) { fprintf(stderr,"Can't open %s\n",ofn); Exit(1); } for (;;) { if (!fgets(buf,100,ifp)) break; chomp(buf); if (strlen(buf)==0) continue; if (!strncmp(buf,"Global Symbols",14)) flag = 1; if (!flag) continue; nf = argvize(field,buf); if (nf != 3) continue; if (field[0][0] != '.') continue; csum = 0; len = strlen(field[2])+8+2; fprintf(ofp,"S4%02X%s%s,%02x\n",len,field[1],field[2],csum); } fclose(ifp); fclose(ofp); } #ifndef Exit /************************************************************* * Exit(x) */ Exit(x) int x; { int i; for (i=0;strlst[i];i++) { if (strlst[i]->str) free(strlst[i]->str); } sprintf(tmp,"%s.t1",tmppath); if (fileExists(tmp)) unlink(tmp); sprintf(tmp,"%s.t2",tmppath); if (fileExists(tmp)) unlink(tmp); sprintf(tmp,"%s.sx",tmppath); if (fileExists(tmp)) unlink(tmp); exit(((x)>127)?1:(x)); } #endif /************************************************************* * fixasm(ifn,ofn) * This routine fixes all of the GHS assembly syntax differences. * It does use a few shortcuts and so may not work for all cases. * Output file must be named .mip. */ fixasm(ifn,ofn) char *ifn,*ofn; { FILE *ifp,*ofp; char buf1[200],buf2[200],*field[40],*p,*s,*e; int nf,flag,n; if (vflag) fprintf(stderr,"fixasm %s > %s\n",ifn,ofn); flag = 0; ifp = fopen(ifn,"r"); if (ifp == 0) { fprintf(stderr,"Can't open %s\n",ifn); exit(1); } ofp = fopen(ofn,"w"); if (ofp == 0) { fprintf(stderr,"Can't open %s\n",ofn); exit(1); } for (;;) { if (!fgets(buf1,200,ifp)) break; chomp(buf1); /* delete the newline char(s) */ /* GHS doesn't like '#' comments in a .mip file */ /* delete all of the comments */ while ((s=strstr(buf1,"/*")) && (e=strstr(s,"*/"))) strcpy(s,e+2); if (strlen(buf1) && (p=(char *)strchr(&buf1[1],'#'))) *p = 0; strcpy(buf2,buf1); nf = argvize(field,buf2); /* split the line into args */ /* now handle the directives that are different */ /* GHS align is # of bytes, MIPS align is 2^# bytes */ if (nf >= 2 && strequ(field[0],".align")) { sscanf(field[1],"%d",&n); fprintf(ofp,"\t.align %d\n",1<= 2 && strequ(field[0],".extern") && (p=strchr(field[1],','))) { *p = 0; p++; fprintf(ofp," .extern %s\n",field[1]); } else fprintf(ofp,"%s\n",buf1); } fclose(ifp); fclose(ofp); } /************************************************************* * mklnkfile(basename) */ mklnkfile(basename) char *basename; { FILE *sfp; sprintf(tmp,"%s.lnk",basename); sfp = fopen(tmp,"w"); if (!sfp) { fprintf(stderr,"can't open %s\n",tmp); exit(1); } wrfile(sfp,ld_cmd_file1); fprintf(sfp,"\t.text\t\t0x%s\t:\n",tstart); wrfile(sfp,ld_cmd_file2); fprintf(sfp,"\t.sdabase\t0x%s\t:\n",dstart); wrfile(sfp,ld_cmd_file3); fclose(sfp); }