home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / as32 / emitter.c < prev    next >
C/C++ Source or Header  |  1991-03-22  |  9KB  |  425 lines

  1. /* ----------------------------------------------------------------------
  2.  * FILE: emitter.c
  3.  * PACKAGE: as31 - 8031/8051 Assembler.
  4.  *
  5.  * DESCRIPTION:
  6.  *    This file contains the code to generate various
  7.  *    object code formats. Provisions exist to
  8.  *    support many types of output formats within the
  9.  *    same executable.
  10.  *
  11.  * REVISION HISTORY:
  12.  *    Jan. 19, 1990 - Created. (Ken Stauffer)
  13.  *    Jan. 29, 1990 - Added S-records (Theo Deraadt)
  14.  *
  15.  *
  16.  * AUTHOR:
  17.  *    All code in this file written by Ken Stauffer (University of Calgary).
  18.  *    January, 1990.
  19.  */
  20.  
  21. #include <stdio.h>
  22.  
  23. /* ----------------------------------------------------------------------
  24.  * DECLARE your own open(), close(), addr(), and byte() routines here.
  25.  *
  26.  */
  27.  
  28. static int open1(), close1(), addr1(), byte1();
  29. static int open2(), close2(), addr2(), byte2();
  30. static int open3(), close3(), addr3(), byte3();
  31. static int open4(), close4(), addr4(), byte4();
  32.  
  33. /* ----------------------------------------------------------------------
  34.  * ADD an entry to this table to register your
  35.  * output format routines. Give your object format
  36.  * a name to be specified with the -F option.
  37.  *
  38.  */
  39.  
  40. static int format;
  41. static struct {
  42.     char *name;
  43.     int (*e_open)();
  44.     int (*e_close)();
  45.     int (*e_addr)();
  46.     int (*e_byte)();
  47. } formtab[] = {
  48.     { "tdr",   open1, close1, addr1, byte1 },
  49.     { "byte",  open2, close2, addr2, byte2 },
  50.     { "od",    open3, close3, addr3, byte3 },
  51.     { "srec2", open4, close4, addr4, byte4 },
  52.     { "srec3", open4, close4, addr4, byte4 },
  53.     { "srec4", open4, close4, addr4, byte4 }
  54. };
  55.  
  56. #define FORMTABSIZE    (sizeof(formtab)/sizeof(formtab[0]))
  57.  
  58. emitusage()
  59. {
  60.     int i;
  61.     fprintf(stderr, "\tfmt is one of:");
  62.     for(i=0; i<FORMTABSIZE; ) {
  63.         fprintf(stderr, "%s", formtab[i].name);
  64.         if( ++i < FORMTABSIZE)
  65.             fprintf(stderr, ", ");
  66.     }
  67.     fprintf(stderr, ".\n");
  68. }
  69.  
  70. emitopen(file,ftype,arg)
  71. char *file,*ftype,*arg;
  72. {
  73.     int i;
  74.     if( ftype ) {
  75.         for(i=0; i<FORMTABSIZE; i++ ) {
  76.             if( !strcmp(formtab[i].name,ftype) ) {
  77.                 format = i;
  78.                 (*formtab[format].e_open)(file,ftype,arg);
  79.                 return;
  80.             }
  81.         }
  82.         fprintf(stderr, "warning: no format \"%s\", using \"%s\"\n",
  83.             ftype, formtab[0].name);
  84.     }
  85.     /*
  86.      * 0th entry is the default format type
  87.      */
  88.     format = 0;
  89.     (*formtab[format].e_open)(file,ftype,arg);
  90. }
  91.  
  92. emitclose()
  93. {
  94.     (*formtab[format].e_close)();
  95. }
  96.  
  97. emitaddr(a)
  98. unsigned long int a;
  99. {
  100.     (*formtab[format].e_addr)(a);
  101. }
  102.  
  103. emitbyte(b)
  104. int b;
  105. {
  106.     (*formtab[format].e_byte)(b);
  107. }
  108.  
  109. /* ----------------------------------------------------------------------
  110.  * Individual file format routines appear here:
  111.  *    Each file format must define the following routines:
  112.  *        open()    - Called ONCE before any of the others.
  113.  *            It is passed with a filename and a format
  114.  *            specific argument.
  115.  *
  116.  *        close() - Called ONCE when no more emit_byte()
  117.  *            function calls will be made.
  118.  *
  119.  *        addr() - Called when ever a new address has been set
  120.  *            in the assembler (ie. .org, .skip).
  121.  *            This routine is also called once when the
  122.  *            location counter is set to 0 at the very start of
  123.  *            assembling.
  124.  * 
  125.  *        byte() - Called with each byte to be outputed.
  126.  *
  127.  */
  128.  
  129. /* ----------------------------------------------------------------------
  130.  * "tdr" format. For tdr's 68008 system. Generates a
  131.  * script file readable by a debugger.
  132.  *    [addr] : [byte] [byte] ..
  133.  *
  134.  * arg: This is a number in decimal which specifies
  135.  *    the offset, -Ftdr -A0000
  136.  *
  137.  *    These options specifies the tdr format, with an argument
  138.  *    of 0. This becomes the offset used in generating the
  139.  *    script file. The default if no A is present is 0x10000.
  140.  * 
  141.  */
  142.  
  143. static unsigned long addr;
  144. static FILE *fout;
  145. static long int offset;
  146. static int newaddr;
  147. static int pos=-666;
  148.  
  149. static open1(file,ftype,arg)
  150. char *file, *ftype, *arg;
  151. {
  152.     fout = fopen(file,"w");
  153.     if( fout == NULL ) {
  154.         fprintf(stderr,"Cannot open %s for writting.\n",file);
  155.         exit(1);
  156.     }
  157.     if( arg ) {
  158.         offset = atoi(arg);
  159.     } else
  160.         offset = 0x10000;
  161. }
  162.  
  163. static close1()
  164. {
  165.     if( pos != 15 ) fprintf(fout,"\n");
  166.     fclose(fout);
  167. }
  168.  
  169. static addr1(a)
  170. unsigned long int a;
  171. {
  172.     addr = a;
  173.     newaddr = 1;
  174. }
  175.  
  176. static byte1(b)
  177. unsigned char b;
  178. {
  179.     if( newaddr ) {
  180.         if( pos != -666 ) fprintf(fout,"\n");
  181.         newaddr = 0;
  182.         pos = 15;
  183.         fprintf(fout,"%06x: ",addr+offset);
  184.     } else if( pos == 15 ) {
  185.         fprintf(fout,"%06x: ",addr+offset);
  186.     }
  187.  
  188.     fprintf(fout,"%02x ", b&0xff );
  189.  
  190.     if( pos-- == 0 ) {
  191.         fprintf(fout,"\n");
  192.         pos = 15;
  193.     }
  194.     addr += 1;
  195. }
  196.  
  197.  
  198. /* ----------------------------------------------------------------------
  199.  * "byte" format.
  200.  *    Like "tdr" but each byte is on a line by itself.
  201.  *    This is nice for debugging. No -A is used.
  202.  */
  203.  
  204. static open2(file,ftype,arg)
  205. char *file, *ftype, *arg;
  206. {
  207.     fout = fopen(file,"w");
  208.     if( fout == NULL ) {
  209.         fprintf(stderr,"Cannot open %s for writting.\n",file);
  210.         exit(1);
  211.     }
  212. }
  213.  
  214. static close2()
  215. {
  216.     fclose(fout);
  217. }
  218.  
  219. static addr2(a)
  220. unsigned long int a;
  221. {
  222.     addr = a;
  223. }
  224.  
  225. static byte2(b)
  226. unsigned char b;
  227. {
  228.     fprintf(fout,"%04x: %02x\n", addr, b&0xff );
  229.     addr += 1;
  230. }
  231.  
  232.  
  233. /* ----------------------------------------------------------------------
  234.  * "od", this format shows 16 bytes per line, with address.
  235.  *    It also includes ascii on one side.
  236.  *
  237.  * The format is similar to the od(1) program under Unix.
  238.  *
  239.  */
  240.  
  241. static int pos3;
  242. static unsigned char buf[16];
  243. static unsigned long saveaddr;
  244.  
  245. static open3(file,ftype,arg)
  246. char *file, *arg;
  247. {
  248.     fout = fopen(file,"w");
  249.     if( fout == NULL ) {
  250.         fprintf(stderr,"Cannot open %s for writting.\n",file);
  251.         exit(1);
  252.     }
  253. }
  254.  
  255. static close3()
  256. {
  257.     dumpline(saveaddr,buf,pos3-1);
  258.     fclose(fout);
  259. }
  260.  
  261. static addr3(a)
  262. unsigned long int a;
  263. {
  264.     newaddr = 1;
  265.     addr = a;
  266. }
  267.  
  268. static byte3(b)
  269. unsigned char b;
  270. {
  271.     if( newaddr ) {
  272.         dumpline(saveaddr,buf,pos3-1);
  273.         pos3 = 0;
  274.         newaddr = 0;
  275.         saveaddr = addr;
  276.     } else if( pos3 == 16 ) {
  277.         dumpline(saveaddr,buf,pos3-1);
  278.         pos3 = 0;
  279.         saveaddr = addr;
  280.     }
  281.     buf[pos3++] = b & 0x00ff;
  282.  
  283.     addr += 1;
  284. }
  285.  
  286. dumpline(a,b,len)
  287. unsigned long a;
  288. unsigned char *b;
  289. int len;
  290. {
  291.     int i;
  292.  
  293.     if(len <= 0 ) return;
  294.  
  295.     fprintf(fout,"%04x: ",a);
  296.  
  297.     for(i=0; i<8; i++ ) {
  298.         if( i <= len )
  299.             fprintf(fout,"%02x ",b[i]);
  300.         else
  301.             fprintf(fout,"   ");
  302.     }
  303.  
  304.     fprintf(fout,"- ");
  305.  
  306.     for(i=8; i<16; i++ ) {
  307.         if( i <= len )
  308.             fprintf(fout,"%02x ",b[i]);
  309.         else
  310.             fprintf(fout,"   ");
  311.     }
  312.     fprintf(fout,"   ");
  313.  
  314.     for(i=0; i<16; i++ ) {
  315.         if( i <= len )
  316.             fprintf(fout,"%c",
  317.                 (b[i]>=' ' && b[i]<='~') ? b[i] : '.' );
  318.         else
  319.             break;
  320.     }
  321.     fprintf(fout,"\n");
  322. }
  323.  
  324. /* ----------------------------------------------------------------------
  325.  * srecord format. This is called with "-Fsrec2", "-Fsrec3", or
  326.  * "-Fsrec4"...
  327.  *
  328.  * arg: This is a number in decimal which specifies
  329.  *    the offset, -Fsrec3 -A0000
  330.  *
  331.  *    These options specifies the tdr format, with an argument
  332.  *    of 0. This becomes the offset used in generating the
  333.  *    script file. The default if no A is present is 0x0000.
  334.  * 
  335.  */
  336. #define SREC_BYTESPERLINE 32
  337.  
  338. static char format4;
  339. static int check4, index4;
  340. static char buf4[SREC_BYTESPERLINE];
  341. static long address4;
  342.  
  343. static open4(file,ftype,arg)
  344. char *file, *ftype, *arg;
  345. {
  346.     format4 = ftype[4];        /* will be '2' -- '4' */
  347.  
  348.     fout = fopen(file,"w");
  349.     if( fout == NULL ) {
  350.         fprintf(stderr,"Cannot open %s for writing.\n",file);
  351.         exit(1);
  352.     }
  353.  
  354.     if(arg)    offset = atoi(arg);
  355.     else    offset = 0;
  356.  
  357.     fprintf(fout, "S0030000%02X\n", (~3 & 0xff) );
  358.  
  359. }
  360.  
  361. static close4()
  362. {
  363.     if(index4)
  364.         finishline();
  365.     switch(format4) {
  366.     case '2':
  367.         fprintf(fout, "S9030000%02X\n", ~3 & 0xff);
  368.         break;
  369.     case '3':
  370.         fprintf(fout, "S804000000%02X\n", ~4 & 0xff);
  371.         break;
  372.     case '4':
  373.         fprintf(fout, "S70500000000%02X\n", ~5 & 0xff);
  374.         break;
  375.     }
  376.     fclose(fout);
  377. }
  378.  
  379.  
  380. static addr4(a)
  381. unsigned long int a;
  382. {
  383.     if(index4>0)
  384.         finishline();
  385.     address4 = a + offset;
  386. }
  387.  
  388. static byte4(b)
  389. {
  390.     buf4[index4++] = b;
  391.     if(index4==SREC_BYTESPERLINE) {
  392.         finishline();
  393.         address4 += SREC_BYTESPERLINE;
  394.     }
  395. }
  396.  
  397. finishline()
  398. {
  399.     int i;
  400.  
  401.     check4 = index4 + (address4 & 0xff) + ((address4>>8) & 0xff) + 4;
  402.  
  403.     switch(format4) {
  404.     case '2':
  405.         fprintf(fout, "S1%02X%04X", index4 + 4,    address4 & 0xffff);
  406.         break;
  407.     case '3':
  408.         fprintf(fout, "S2%02X%06X", index4 + 6, address4 & 0xffffff);
  409.         check4 += ((address4>>16) & 0xff) + 2;
  410.         break;
  411.     case '4':
  412.         fprintf(fout, "S3%02X%08X", index4 + 8, address4);
  413.         check4 += ((address4>>16) & 0xff) +((address4>>24) & 0xff) + 4;
  414.         break;
  415.     }
  416.  
  417.     for(i=0; i<index4; i++) {
  418.         fprintf(fout, "%02X", buf4[i] & 0xff);
  419.         check4 += buf4[i];
  420.     }
  421.  
  422.     fprintf(fout, "%02X\n", (~check4 & 0xff) );
  423.     index4 = 0;
  424. }
  425.