83#define DIRECT_PAGE 0x2100
86#define KEEP_COMMENTS 1
88#define DO_DIRECT_PAGE 1
93static inline char _toUpper(
char a) {
94 return (a>=
'a' && a<=
'z') ? a-
'a'+
'A' : a;
98static inline int _eol(
char c) {
99 return c==
'\0' || c==
'\n';
103static inline int _eq(
char pat,
char txt) {
104 return (pat<=
' ') ? (txt<=
' ') : (_toUpper(pat)==_toUpper(txt));
109 char * _buffer = buf->
str;
114 if ( *_buffer ==
'\r' || *_buffer ==
'\n' ) {
118 if ( *_buffer ==
' ' || *_buffer ==
'\t' ) {
120 }
else if ( *_buffer ==
';' ) {
130static int change = 0;
131static int peephole_pass = 0;
132static int num_dp = 0;
133static int num_inlined = 0;
134static int num_unread = 0;
137static void optim(
POBuffer buf,
const char *rule,
const char *repl, ...)
138 __attribute__ ((format (printf, 3, 4)));
143#define RULE "r" R_(__LINE__) " "
147static void optim(
POBuffer buf,
const char *rule,
const char *repl, ...) {
156 if(rule)
po_buf_printf(tmp,
"; peephole(%d): %s\n", peephole_pass, rule);
162 if ( (s = strchr(buf->
str,
'\n')) != NULL) *s =
'\0';
185static int isZero(
char *s) {
187 while(*s ==
'0') ++s;
191 return buf!=NULL && isZero(buf->
str);
214 if(
po_buf_match( buf[0],
" LD *, 0", v1) && strchr(
"A", _toUpper(*v1->
str) ) != NULL ) {
215 optim( buf[0],
RULE "(LD A, 0)->(XOR A)",
"\tXOR %c", _toUpper(*v1->
str) );
227 optim( buf[0],
RULE "(LD B, x; LD C, x)->(LD BC, xx)",
"\tLD BC, ($%s * 256) + $%s", v1->
str, v2->
str );
228 optim( buf[1],
"", NULL );
237 optim( buf[2],
RULE "(LD A, x; LD (x), A; LD A, x)->(LD A, x; LD (x), A)", NULL );
242 && (strtol(v1->
str, NULL, 16) == strtol(v2->
str, NULL, 16))
244 optim(buf[0],
RULE "(LD HL, LD A, same value)->(LD A)", NULL );
313 optim( buf[0],
RULE "(XOR $FF)->(CPL)",
"\tCPL" );
343 optim( buf[0],
RULE "(SLA+RL)->(ADD)",
"\tADD HL, HL" );
344 optim( buf[1], NULL, NULL );
376 optim( buf[0],
RULE "(CALL+RET)->(JP)",
"\tJP %s", v1->
str );
377 optim( buf[1], NULL, NULL );
390 optim( buf[0],
RULE "(DEC B+JR NZ)->(DJNZ)",
"\tDJNZ %s", v1->
str );
391 optim( buf[1], NULL, NULL );
399 optim( buf[2],
RULE "(LD A, *; LD A, *)->(LD, A)", NULL );
427static void vars_clear(
void) {
429 for(i=0; i<vars.size; ++i) {
430 struct var *v = &vars.tab[i];
432 if(v->init)
free(v->init);
441 struct var *ret = NULL;
444 char *s=strchr(
name,
'+');
447 for(i=0; i<vars.size ; ++i) {
448 if(strcmp(vars.tab[i].name,
name)==0) {
453 if(vars.size == vars.capacity) {
455 vars.tab = realloc(vars.tab,
sizeof(*vars.tab)*vars.capacity);
457 ret = &vars.tab[vars.size++];
458 ret->name = strdup(
name);
477 if(
name->str[0]==
'_')
return 1;
503 if(
po_buf_match( buf[0],
" LD *, (*+*)", tmp, arg, ofs ) ) {
if(vars_ok(arg)) {
506 } }
else if(
po_buf_match( buf[0],
" LD *, (*)", tmp, arg ) ) {
if(vars_ok(arg)) {
512 strstr(
"A B C D E AD BC DE HL IX IY", tmp->
str)!=NULL
518 if (
po_buf_match( buf[0],
" LD (*+*), *", arg, ofs, tmp) ) {
if(vars_ok(arg)) {
521 } }
else if (
po_buf_match( buf[0],
" LD (*), *", arg, tmp) ) {
if(vars_ok(arg)) {
527 strstr(
"A B C D E AD BC DE HL IX IY", tmp->
str)!=NULL
533 if(
po_buf_match( buf[0],
" *: defs *", tmp, arg) && vars_ok(tmp)) {
535 v->size = atoi(arg->
str);
536 v->init = strdup(
"1-1");
539 if(
po_buf_match(buf[0],
" *: defb *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
542 v->init = strdup(isZero(arg->
str) ?
"1-1" : arg->
str);
545 if(
po_buf_match(buf[0],
" *: defw *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
548 v->init = strdup(arg->
str);
554static int vars_cmp(
const void *_a,
const void *_b) {
555 const struct var *a = _a;
556 const struct var *b = _b;
558 int diff = ((a->nb_rd + a->nb_wr) - (b->nb_rd + b->nb_wr));
560 return -(diff!=0 ? diff : strcmp(a->name, b->name));
572 if(
po_buf_match( buf[0],
" LD (*+*), *", var, ofs, op) && vars_ok(var)) {
574 if(v->nb_rd == 0 && v->offset!=-2) {
576 optim(buf[0],
"unread", NULL);
579 }
else if(
po_buf_match( buf[0],
" LD (*), *", var, op) && vars_ok(var)) {
581 if(v->nb_rd == 0 && v->offset!=-2) {
583 optim(buf[0],
"unread", NULL);
591 ||
po_buf_match( buf[0],
" *: DEFW ", var) )
if(vars_ok(var)) {
593 if(v->nb_rd==0 && 0<v->size && v->size<=4 && 0==(v->flags &
NO_REMOVE) && v->offset!=-2) {
594 optim(buf[0],
"unread",NULL);
602static void out(FILE *f,
POBuffer _buf) {
605 while(*s==
' ' || *s==
'\t') {
tab = 1; ++s;}
606 if(
tab) fputs(
"\t", f);
611static void fixes_indexed_syntax(
POBuffer buf) {
615 if(!_eq(
' ', *s))
return;
618 do ++s;
while(*s && _eq(
' ', *s));
624 while(*s && !_eq(
' ', *s)) ++s;
628 do ++s;
while(*s && _eq(
' ', *s));
632 do ++s;
while(*s && !_eq(
' ', *s));
641 FILE * fileOptimized;
653 adiline2(
"POP:0:%d:%d", peephole_pass, kind );
678 fileAsm = fopen( _environment->
asmFileName,
"rt" );
679 if(fileAsm == NULL) {
684 fileOptimized = fopen( fileNameOptimized,
"wt" );
685 if(fileOptimized == NULL) {
686 perror(fileNameOptimized);
696 while( still_to_go ) {
698 if ( line >=
LOOK_AHEAD ) out(fileOptimized, buf[0]);
715 sourceLine = atoi( ln->
str );
726 }
while(!feof(fileAsm));
730 basic_peephole(buf, zA, zB);
733 if(change == 0) vars_scan(buf);
737 vars_remove(_environment, buf);
755 fprintf(fileOptimized,
"; peephole: pass %d, %d change%s.\n", peephole_pass,
756 change, change>1 ?
"s":
"");
760 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s removed.\n", peephole_pass,
761 num_unread, num_unread>1 ?
"s":
"");
765 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s moved to dp, %d var%s inlined.\n", peephole_pass,
766 num_dp, num_dp>1 ?
"s":
"",
767 num_inlined, num_inlined>1 ?
"s":
"");
774 (void)fclose(fileAsm);
775 (void)fclose(fileOptimized);
795 while(optim_pass(_environment, buf,
PEEPHOLE)&&optimization_limit_count) {
796 --optimization_limit_count;
798 optim_pass(_environment, buf,
DEADVARS);
799 }
while(change&&optimization_limit_count);
828 fileAsm = fopen( _environment->
asmFileName,
"rb" );
829 if(fileAsm == NULL) {
835 if(fileListing == NULL) {
840 while( !feof(fileAsm) && !feof(fileListing)) {
848 sourceLine = atoi( ln->
str );
859 *bufferListing->
str = 0;
860 int pos = ftell( fileListing );
862 while( !feof(fileListing) && (strstr( bufferListing->
str, bufferAsm->
str ) == NULL) ) {
867 if ( feof(fileListing) ) {
870 pos = ftell( fileListing );
871 char * bufferAsmEscaped = strdup( bufferAsm->
str );
872 for(
int i=0, c=strlen(bufferAsmEscaped); i<c; ++i ) {
873 if ( bufferAsmEscaped[i] ==
':' ) {
874 bufferAsmEscaped[i] = 6;
876 if ( bufferAsmEscaped[i] == 9 ) {
877 bufferAsmEscaped[i] =
' ';
880 if (
po_buf_match( bufferListing,
"* * * ", bufferLine, bufferAddress, bufferBytes ) ) {
887 fseek( fileListing, pos, SEEK_SET );
896 (void)fclose(fileListing);
897 (void)fclose(fileAsm);
char * get_temporary_filename(Environment *_environment)
struct @110344003176124301103124235173106120065272160135::var * tab
void target_finalize(Environment *_environment)
void target_peephole_optimizer(Environment *_environment)
struct var * vars_get(POBuffer _name)
int isAComment(POBuffer buf)
POBuffer po_buf_match(POBuffer _buf, const char *_pattern,...)
POBuffer po_buf_new(int size)
POBuffer po_buf_printf(POBuffer buf, const char *fmt,...)
int po_buf_strcmp(POBuffer _s, POBuffer _t)
POBuffer po_buf_cpy(POBuffer buf, char *string)
POBuffer po_buf_del(POBuffer buf)
POBuffer po_buf_add(POBuffer buf, char c)
int po_buf_trim(POBuffer buf)
POBuffer po_buf_vprintf(POBuffer buf, const char *fmt, va_list ap)
POBuffer po_buf_cat(POBuffer buf, char *string)
POBuffer po_buf_fgets(POBuffer buf, FILE *f)
int currentSourceLineAnalyzed
FILE * additionalInfoFile
int peepholeOptimizationLimit
#define adiline4(s, a, b, c, d)
#define MAX_TEMPORARY_STORAGE
enum _PeepHoleOptimizationKind PeepHoleOptimizationKind
struct _POBuffer * POBuffer
struct _Environment Environment
Structure of compilation environment.
#define adiline3(s, a, b, c)
#define BUILD_SAFE_MOVE(_environment, source, destination)
#define adiline2(s, a, b)