/* * SPEEDUP O B J E C T C O D E 'O P T I M I S E R' * * (c) Chris Undery 1983 * 11 Margaret st Newtown 2042 * Sydney Australia. Desription:- This program was written to 'optimise' bds c object code to take advantage of the undocumented instructions of the Intel 8085 mpu. see cpu.asm for macros to enable assembly of these instructions. hl <- (de) hl -> (de) 16 bit shifts 16 bit subtraction stack + offset references conditional branch with dcx inx using the x5 flag restart on overflow These instructions 'live' in all Intel 8085 mpus. They were not published when the mpu was first realeased for some weird marketing reason. Taken in perspective they really shed new light on the Z80 8085 comparison stakes. The file supplied .. CPU.ASM should be assembled using MAC or M80 and loaded to binary format (use link, load or ddt/sid). This program should be invoked as:- speedup infile_name outfile_name cpu.com The result of this is that BDS C programs will run faster. Programs which make use of much pointer work and string comparisons will be most effected by this tom foolery. There are many more code sequences generated by the bds compiler which could be worked over..see who can get the fastest sieve benchmark going! Heavily disk io bound software will not see much improvement by the use of speedup, but other software will. Dont expect too much for nothing. I have not doctored the 16 bit rotates in c.ccc, they are good candidates for optimising using the 16 bit rotate instructions play around and have fun. */ #include bdscio.h #define BUFSECS 20000 / 128 /* # of sectors which fit in buf*/ #define NO 0 /* booleans */ #define YES 1 #define TEXT char #define UCOUNT unsigned #define COUNT int #define BYTE char /* leading byte on rules file holds cpu type */ #define I8080 0 #define I8085 1 #define Z80 2 #define I8886 3 #define ASCII 4 /* Global Data Storage */ TEXT object[20000], /* object code buffer */ rules[256][64], /* transformation table */ rulebuf[BUFSIZ], /* file buffer for rules */ cpu, /* cpu descriptor */ rule; /* current rule being checked */ UCOUNT infile, /* input file descriptor */ outfile, /* output file descriptor */ size, /* no of sects read from input */ bytes, /* bytes transferred */ num_rules, /* max number of sequences */ modified; /* total bytes modified */ main(argc,argv) TEXT **argv; { num_rules = modified = size = NULL; if (argc < 4) { puts("Usage: SPEEDUP input_file output_file mask_file\n"); exit(); } puts("\nSPEEDUP Object Code 'Optimiser' V 1.0 (C) Chris Undery 1983\n"); if (fopen(argv[3],rulebuf) == ERROR) { printf("%s not found\n",argv[3]); exit(); } load_rules(); /* load rules table from file */ if ((infile = open(argv[1],0)) == ERROR) { printf("%s not found\n",argv[1]); exit(); } if ((outfile = creat(argv[2])) == ERROR) { printf("Can't create %s\n",argv[2]); exit(); } size = read(infile,object,BUFSECS); /* gulp */ if (size == ERROR) { printf("Error reading %s\n",argv[1]); exit(); } printf("Now processing %s [file size = %d]\n",argv[1],size*128); optimise(); /* modify the com file */ if (write(outfile,object,size) != size) { printf("Error writing %s, check disk space\n",argv[2]); exit(); } close(infile); if (close(outfile) == ERROR) { printf("Error closing %s\n",argv[2]); exit(); } puts("CPU type = "); switch (cpu) { case I8080: puts("8080"); break; case I8085: puts("8085");break; case I8886: puts("8088 / 8086");break; case Z80: puts("Z80"); break; default: puts("ASCII TEXT replacement"); } printf(" Bytes altered = %5u\n",modified); } /* scan rules table until all transformations completed */ optimise() { COUNT k, j, loop; TEXT *msecs,*secs,*mins; msecs = 0xe837; secs = 0xe838; mins = 0xe839; *msecs = *secs = *mins = k = j = NULL; while (k < num_rules) { printf("Pass %02d, Replacements ",k+1); transform(j); j += 2; k++; if (k == num_rules) break; puts("\r \r"); } puts("\n"); /* printf("Cpu time <%02d:%02d:%03d>\n", *mins,*secs,*msecs); */ } /* scan object code for match in rules table */ transform(k) COUNT k; { COUNT pos; /* result of index function */ TEXT *p; /* pointer to nex element in object */ COUNT subs; subs = pos = NULL; p = &object[0]; /* assign to start of object */ /* * rules[k][0] length of search mask * rules[k][1..31] search mask * rules[k+1][0] length of replacement data * rules[k+1][1..31] replacement data */ while (pos != ERROR ) { pos = match(p,(size * 128) - pos ,&rules[k][1],rules[k][0]); if (pos == ERROR) break; p += pos; /* add the offset needed */ movmem(&rules[k+1][1],p,rules[k+1][0]); modified += rules[k+1][0]; back(5); puts(" "); back(5); printf("%5u",++subs); } } /* find pattern in buffer , match for n characters */ match(s,s_len,t,t_len) TEXT s[], t[]; COUNT s_len, t_len; { COUNT i, j, k; for (i = 0; i < s_len; i++) { for (j = i, k= 0; s[j] == t[k]; j++, k++) ; if (k == t_len) return i; /* return valid index */ } return ERROR; /* no match found in buffer */ } /* load search masks and replacement patterns */ load_rules() { COUNT c, j, k, i; i = j = NULL; if ((c = getc(rulebuf)) != CPMEOF) cpu = c; else return YES; while ((c = getc(rulebuf)) != CPMEOF) { k = rules[i][0] = c; if (!c) return YES; /* count feild = zero */ while (k--) { /* load sequence string */ rules[i][++j] = getc(rulebuf); if (j > 63) { printf("Sequence %d too long ",i); puts("or format error\n"); exit(); } } i++; j = 0; num_rules += (i % 2); if (num_rules > 128) return YES; } } /* run cursor backwards n spaces */ back(n) COUNT n; { COUNT j; for (j = 0 ; j < n; j++) putchar(0x08); } .