📄 ghs.c
字号:
/************************************************************* * 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. * 990119 Added -lind for _fmul etc. */#include <stdio.h>#include <malloc.h>#include <string.h>#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 -lind";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 8char *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 MSDOSif (getenv("windir")) long_cmds_ok = 1;#elselong_cmds_ok = 1;#endifStrcpy(&LIBS,"");#ifdef DYNDEFSsprintf(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 SRECfast = 0;#endif#ifdef CLIENTPCsprintf(tstart,"%08lx",CLIENTPC);#elsestrcpy(tstart,"80020000");#endif#endif#ifdef MSDOS#if 0if (! (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 LENDEFENDIAN = "l";#elseENDIAN = "b";#endifGnum = "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<nfiles;i++) { file = getStrn(&files,i); e = extent(file); getHead(h,file); if (nfiles == 1 && !strequ(ofile,"a") && stoppoint != 0) strcpy(mname,ofile); else sprintf(mname,"%s.o",h); if (strequ(e,"s")) { sprintf(tmp,"%s.mip",h); fixasm(file,tmp); fmt = "%s -c -DLANGUAGE_ASSEMBLY %s %s %s -o %s %s"; sz = strlen(CC)+strlen(flags.str)+strlen(ppflags.str)+ strlen(asflags.str)+strlen(mname)+strlen(tmp)+ strlen(fmt); vtmp = malloc(sz); sprintf(vtmp,fmt,CC,flags.str,ppflags.str, asflags.str, mname,tmp); if (status=System(vtmp)) Exit(status); free(vtmp); getHead(tmp,file); strcat(tmp,".o"); addarg(&ofiles,tmp); } else if (strequ(e,"rec")) { fmt = "rdsrec -A dat1 %s -o tmp.s"; sz = strlen(fmt)+strlen(file); vtmp = malloc(sz); sprintf(vtmp,fmt,file); if (status=System(vtmp)) Exit(status); free(vtmp); fmt = "%s -c %s %s %s -o %s tmp.s"; sz = strlen(CC)+strlen(flags.str)+strlen(ppflags.str)+ strlen(asflags.str)+strlen(mname)+strlen(tmp)+ strlen(fmt); vtmp = malloc(sz); sprintf(vtmp,fmt,CC,flags.str,ppflags.str, asflags.str, mname); if (status=System(vtmp)) Exit(status); free(vtmp); getHead(tmp,file); strcat(tmp,".o"); addarg(&ofiles,tmp); } else if (strequ(e,"c")) { fmt = "%s -Z1250 -U__ghs_stdcall -Xt -unsignedchar %s %s -o %s %s"; sz = strlen(CC)+strlen(flags.str)+strlen(cflags.str)+ strlen(mname)+strlen(file)+strlen(fmt); vtmp = malloc(sz); sprintf(vtmp,fmt,CC,flags.str,cflags.str,mname,file); if (status=System(vtmp)) Exit(status); free(vtmp); getHead(tmp,file); strcat(tmp,".o"); addarg(&ofiles,tmp); } else if (strequ(e,"o")) { addarg(&ofiles,file); } else if (strequ(e,"a")) { addarg(&ofiles,file); } else { fprintf(stderr,"pmcc: %s: bad extent\n",e); Exit(1); } free(file); }if (stoppoint != 0) Exit(0);/* Select C library */sprintf(LIBC,"%s/lib/%s%s",LSIPKG,ENDIAN,Gnum);if (stdcrt0) addcrt0(stdcrt0,LSIPKG,ENDIAN,Gnum);if (crt0.str == 0) Strcpy(&crt0,"");if (dstart) { mklnkfile(ofile); fmt = "lx -map @%s.lnk %s %s %s %s %s"; sz = strlen(ofile)+strlen(ldflags.str)+Strlen(&crt0)+ strlen(ofiles.str)+strlen(initial_lc)+strlen(LIBS.str)+strlen(fmt); vtmp = malloc(sz); sprintf(vtmp,fmt,ofile,ldflags.str,crt0.str,ofiles.str,LIBS.str, initial_lc); }else { fmt = "lx -map -T %s %s %s %s %s %s"; sz = strlen(tstart)+strlen(ldflags.str)+Strlen(&crt0)+ strlen(ofiles.str)+strlen(initial_lc)+strlen(LIBS.str)+strlen(fmt); vtmp = malloc(sz); sprintf(vtmp,fmt, tstart,ldflags.str,crt0.str,ofiles.str,LIBS.str, initial_lc); }if (status=System(vtmp)) Exit(status);free(vtmp);if (syms || driver) fmt = "gsrec -noS5 -o %s.tmp %s";else fmt = "gsrec -noS5 -o %s.rec %s";sz = strlen(fmt)+strlen(ofile)+strlen(objfile);vtmp = malloc(sz);#if 0sprintf(vtmp,fmt,objfile,ofile);#else /* 980102 */sprintf(vtmp,fmt,ofile,objfile);#endifif (status=System(vtmp)) Exit(status);free(vtmp);if (driver) { sprintf(tmp2,"%s.rec",ofile); str2file(tmp2,"SD"); sprintf(tmp,"%s.tmp",ofile); appendFile(tmp2,tmp); unlink(tmp); Exit(0); }if (syms) { sprintf(tmp,"%s.map",ofile); sprintf(tmp2,"%s.rec",ofile); mksyms(tmp,tmp2); sprintf(tmp,"%s.tmp",ofile); appendFile(tmp2,tmp); }if (fast) { /* build fastFormat records */ sprintf(tmp,"%s.tmp",ofile); sprintf(tmp2,"%s.rec",ofile); unlink(tmp); /* make sure that there's no .tmp file */ rename(tmp2,tmp); /* rename .rec file as .tmp */ /* convert the srecs in the .tmp file to fastrecs. put the result in .rec file */ sprintf(tmp,"rdsrec -f %s.tmp -o %s.rec",ofile,ofile); if (status=System(tmp)) Exit(status); /* execute & exit if error */ }if (ssyms_flag) { sprintf(tmp,"%s.map",ofile); sprintf(tmp2,"%s.sym",ofile); mksyms(tmp,tmp2); }Exit(0);}/************************************************************** getargs(argc,argv)*/getargs(argc,argv)int argc;char *argv[];{int i,mode;char buf[LNMAX];/*# This while loop does several jobs:# 1. strips off any pmcc defined options# 2. some options, if specified, must preceed path specs# so extract them from here, and add them to flags.# 3. find the output filename, if specified*/if (getDef("LENDEF")) mode = MODE_LE;else mode = 0;for (i=1;i < argc;i++) { if (strequ(argv[i],"-mips2")) { mode &= ~MODE_MSK; mode |= MODE_4K; addarg(&cflags,argv[i]); addarg(&cflags,"-cpu=r4000"); addarg(&asflags,argv[i]); addarg(&asflags,"-cpu=r4000"); } else if (strequ(argv[i],"-mips16")) { mode &= ~MODE_MSK; mode |= MODE_16; addarg(&cflags,argv[i]); addarg(&cflags,"-cpu=r4000"); addarg(&asflags,argv[i]); addarg(&asflags,"-cpu=r4000"); } else if (strequ(argv[i],"-G")) { i++; if (!strequ(argv[i],"0")) { sprintf(tmp,"-sda=%s",argv[i]); Gnum = "o"; } else { sprintf(tmp,"-nosda"); Gnum = "g"; } addarg(&cflags,tmp); addarg(&asflags,tmp); } else if (!strncmp(argv[i],"-O",2)) { addarg(&cflags,"-OS"); /* 980113 */ } else if (strequ(argv[i],"-soft-float")) { /* 981028 */ mode |= MODE_SF; addarg(&cflags,"-fsoft"); addarg(&LIBS,"-lind"); } else if (strequ(argv[i],"-float")) { addarg(&flags,argv[i]); addarg(&flags,"-DFLOAT"); SZ = 1; } else if (strequ(argv[i],"-EB")) { ENDIAN = "b"; mode &= ~MODE_LE; } else if (strequ(argv[i],"-EL")) { ENDIAN = "l"; mode |= MODE_LE; } else if (getStdArgs(argc,argv,&i)) ; else if (argv[i][0] == '-') { fprintf(stderr,"%s: bad arg\n",argv[i]); exit(1); } else { addarg(&files,argv[i]); nfiles++; } }sprintf(buf,"-L%s/%s",getDef("COMP_ROOT"),lib_mode[mode]);addarg(&llist,buf);}/************************************************************** wrfile(fp,msg)*/wrfile(fp,msg)FILE *fp;char *msg[];{int i;for (i=0;msg[i];i++) fprintf(fp,"%s\n",msg[i]);}/************************************************************** mksyms(char *ifn,char *ofn)*/mksyms(ifn,ofn)char *ifn,*ofn;{FILE *ifp,*ofp;char buf[100],*field[10];int nf,flag,csum,len;if (vflag) fprintf(stderr,"mksyms %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(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<<n); } /* GHS .word does not accept repeat ':' option */ else if (nf == 2 && strequ(field[0],".word") && (p=strchr(field[1],':'))) { *p = 0; p++; fprintf(ofp," .rept %s\n",p); fprintf(ofp," .word %s\n",field[1]); fprintf(ofp," .endr\n"); } /* GHS .extern does not accept the size option */ else if (nf >= 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -