84#define DIRECT_PAGE 0x2100
87#define KEEP_COMMENTS 1
89#define DO_DIRECT_PAGE 1
94static inline char _toUpper(
char a) {
95 return (a>=
'a' && a<=
'z') ? a-
'a'+
'A' : a;
99static inline int _eol(
char c) {
100 return c==
'\0' || c==
'\n';
104static inline int _eq(
char pat,
char txt) {
105 return (pat<=
' ') ? (txt<=
' ') : (_toUpper(pat)==_toUpper(txt));
110 char * _buffer = buf->
str;
115 if ( *_buffer ==
'\r' || *_buffer ==
'\n' ) {
119 if ( *_buffer ==
' ' || *_buffer ==
'\t' ) {
121 }
else if ( *_buffer ==
';' ) {
145static int sets_flag(
POBuffer buf,
char REG) {
148 if(chg_reg(buf, tmp) && _toUpper(*tmp->
str)==REG)
return 1;
149 if(
po_buf_match(buf,
" ASL*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
150 if(
po_buf_match(buf,
" ASR*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
151 if(
po_buf_match(buf,
" COM*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
152 if(
po_buf_match(buf,
" DEC*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
153 if(
po_buf_match(buf,
" INC*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
154 if(
po_buf_match(buf,
" LSL*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
155 if(
po_buf_match(buf,
" LSR*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
156 if(
po_buf_match(buf,
" ROL*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
157 if(
po_buf_match(buf,
" ROR*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
158 if(
po_buf_match(buf,
" TST*", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
159 if(
po_buf_match(buf,
" ST* ", tmp) && _toUpper(*tmp->
str)==REG)
return 1;
165static int isConditionnal(
POBuffer buf) {
203 return isConditionnal(buf);
207static int change = 0;
208static int peephole_pass = 0;
209static int num_dp = 0;
210static int num_inlined = 0;
211static int num_unread = 0;
214static void optim(
POBuffer buf,
const char *rule,
const char *repl, ...)
215 __attribute__ ((format (printf, 3, 4)));
220#define RULE "r" R_(__LINE__) " "
224static void optim(
POBuffer buf,
const char *rule,
const char *repl, ...) {
233 if(rule)
po_buf_printf(tmp,
"; peephole(%d): %s\n", peephole_pass, rule);
239 if ( (s = strchr(buf->
str,
'\n')) != NULL) *s =
'\0';
262static int isZero(
char *s) {
264 while(*s ==
'0') ++s;
268 return buf!=NULL && isZero(buf->
str);
282 if(
name->str[0]==
'_')
return 1;
329 optim( buf[1],
RULE "(CLEAR*,?,AND*)->(CLEAR*)", NULL);
334 if( (
po_buf_match(buf[0],
" LDB *", v1) ||
po_buf_match(buf[0],
" STB *", v1)) && !strchr(
"AD$", v1->
str[0]) && strstr(v1->
str,
"BASE_SEGMENT" ) == NULL
335 && sets_flag(buf[1],
'A')
339 if(!
po_buf_match(buf[x+1],
" IF ") && !isConditionnal(buf[x+1])) {
341 for(i=0; i<x; ++i)
po_buf_cpy(buf[i], buf[i+1]->str);
348 && strchr(v1->
str,
'+')==NULL
349 && strchr(v2->
str,
'+')==NULL
353 if(!
po_buf_match(buf[x+1],
" IF ") && !isConditionnal(buf[x+1])) {
355 for(i=0; i<x; ++i)
po_buf_cpy(buf[i], buf[i+1]->str);
358 printf(
"XXX %s", buf[x+1]->str);
364 optim( buf[0],
RULE "(LDB, LDB)->(LDB)", NULL);
372 optim( buf[0],
RULE "(CLRA,CLRB,LDA)->(CLRB,LDA)", NULL);
380 optim( buf[0],
RULE "(LDB,LDX,LDB)->(LDX,LDB)", NULL);
389 optim( buf[0],
RULE "(STAx,CLRB,LDAx)->(CLRB)", NULL);
390 optim( buf[1], NULL, NULL);
391 optim( buf[2], NULL,
"\tCLRB");
407 && strchr( v1->
str,
'(' ) == NULL && strchr( v2->
str,
'(' ) == NULL ) {
408 optim( buf[0],
RULE "(LDA,LDB)->(LDD)", NULL);
409 optim( buf[1], NULL,
"\tLDD #((%s)&255)*256+((%s)&255)", v1->
str, v2->
str);
420 fmt = *v1->
str==
'X' ?
"\tLEAX ,X" :
"\tTST%c";
421 optim( buf[0],
"(unsafe, presumed dead)", fmt, _toUpper(*v1->
str));
425 optim( buf[0],
"(unsafe, presumed dead)", NULL);
429 if ( !
po_buf_match(v2,
"_Ttmp") && strcmp( v2->
str,
"BASE_SEGMENT+$C1") && strcmp( v2->
str,
"$FFDE") && strcmp( v2->
str,
"$FFDF")
431 strcmp( v4->
str,
"BASE_SEGMENT+$C1") && strcmp( v4->
str,
"$FFDE") && strcmp( v4->
str,
"$FFDF") ) {
432 optim( buf[1],
RULE "(STORE*,LOAD*)->(STORE*)", NULL);
440 optim( buf[0],
RULE "(LDD, LDD)->(LDD)", NULL);
451 optim( buf[2],
RULE "(ST*, CLR, LD*)->(STD*, CLR)", NULL);
457 && strchr(
"AB", _toUpper(*v2->
str))
459 optim( buf[0],
RULE "(CLEAR*,?,STORE*)->(?,STORE*)", NULL);
464 && strchr(
"AB", _toUpper(*v1->
str))
467 optim(buf[0],
RULE "(LOAD#0)->(CLEAR)",
"\tCLR%c", _toUpper(*v1->
str));
471 && strchr(
"AB", _toUpper(*v1->
str)) ) {
472 optim(buf[0],
RULE "(EOR#$FF)->(COM)",
"\tCOM%c", _toUpper(*v1->
str));
478 && ( strcmp(v1->
str,
"A")!=0 && strcmp(v1->
str,
"B")!=0 && strcmp(v3->
str,
"D")!=0 ) ) {
479 optim(buf[0],
RULE "(LOAD/CLR,LOAD)->(LOAD)", NULL);
486 && !strchr( buf[0]->str,
'+' )
488 optim( buf[2],
RULE "(LOAD*,STORE,LOAD*)->(LOAD*,STORE)", NULL);
496 optim( buf[3],
RULE "(LOAD*,STORE,STORE,LOAD*)->(LOAD*,STORE,STORE)", NULL);
505 optim( buf[4],
RULE "(LOAD*,STORE,STORE,STORE,LOAD*)->(LOAD*,STORE,STORE,STORE)", NULL);
512 && ( !strchr(v1->
str,
'+') && !strchr(v2->
str,
'+') )
515 optim(buf[0],
RULE "(STORE*,LOAD,STORE*)->(LOAD,STORE*)", NULL);
529 && ( (strstr( buf[0]->str,
"++" ) == NULL) && (strstr( buf[0]->str,
"--" ) == NULL) )
531 optim(buf[0],
RULE "(STORE*,STORE*)->(STORE*)", NULL);
536 && strchr(buf[0]->str,
'+')==NULL
537 && strchr(buf[1]->str,
'+')==NULL
540 optim(buf[0],
RULE "(STORE*,?,STORE*)->(?,STORE*)", NULL);
547 &&
po_buf_strcmp(buf[3], buf[0])==0 && strcmp(v2->
str,
"BASE_SEGMENT+$E5")==0 ) {
548 optim(buf[0],
RULE "(STORE*,?,?,STORE*)->(?,?,STORE*)", NULL);
554 && ( (strcmp( v1->
str,
"D" ) == 0) && (strcmp( v1->
str,
"X" ) == 0) && (strcmp( v1->
str,
"Y" ) == 0) )
557 optim(buf[1],
RULE "(LOAD/STORE(8 bit),CMP#0)->(LOAD/STORE)", NULL);
563 && ( !strcmp( v1->
str,
"D" ) || !strcmp( v1->
str,
"X" ) || !strcmp( v1->
str,
"Y" ) )
574 optim(buf[1],
RULE "(LOAD/STORE(16 bit),CMP#0,!check carry)->(LOAD/STORE)", NULL);
584 && strstr( v1->
str,
"X" ) == NULL) {
586 optim(buf[0],
RULE "(LDD+,STD*,LDX,CMPX*)->(LDX,CMP+)", NULL);
588 optim(buf[1],
"(unsafe, presumed dead)", NULL);
590 optim(buf[4], NULL,
"\tCMPX %s", v1->
str);
592 optim(buf[4],
RULE "(LDD+,STD*,LDX,CMPX*)->(LDD+,STD*,LDX,CMPX+)",
"\tCMPX %s", v1->
str);
602 optim(buf[0],
RULE "(LDD+,STD*,LDD,ADDD*)->(LDD,ADD+)", NULL);
604 optim(buf[1],
"(unsafe, presumed dead)", NULL);
606 optim(buf[3], NULL,
"\tADDD %s", v1->
str);
608 optim(buf[3],
RULE "(LDD+,STD*,LDD,ADDD*)->(LDD+,STD*,LDD,ADD+)",
"\tADDD %s", v1->
str);
616 optim(buf[1],
RULE "(STD*,LDX*)->(STD*,TDX)",
"\tTFR D,X");
623 optim(buf[0],
"(unsafe, presumed dead)", NULL);
626 optim(buf[1],
RULE "(STD,LDB+1)->()", NULL);
633 && !vars_ok(v2) && !vars_ok(v1) ) {
634 optim(buf[0],
RULE "(LDD#,ADD#)->(LDD#)",
"\tLDD #(%s+%s)", v1->
str, v2->
str);
635 optim(buf[1], NULL, NULL);
643 optim(buf[0],
RULE "(STX*,CLRA,LDX*)->(CLRA,STX*)", NULL);
644 optim(buf[2], NULL,
"\tSTX %s", v1->
str);
663 optim(buf[0],
"(unsafe, presumed dead)", NULL);
666 optim(buf[1],
RULE "(STB*,LDB+,ORB/ANDB/EORB/ADDB*)->(STB*,ORB/ANDB/EORB/ADDB+)", NULL);
667 optim(buf[2], NULL,
"\t%sB %s", v3->
str, v2->
str);
675 optim(buf[1],
RULE "(STD,LDD[])->(TDX,LOAD*X)",
"\tTFR D,X\n\tLD%c ,X", _toUpper(*v2->
str));
679 && sets_flag(buf[0], *v1->
str)) {
680 optim(buf[1],
RULE "(FLAG-SET,TST)->(FLAG-SET)", NULL);
686 &&
po_buf_match(buf[2],
" JSR CPUMATHMUL16BITTO32*", NULL)) {
687 optim(buf[0],
RULE "(MUL#1)->(NOP)",
"\tLDD %s", v1->
str);
688 optim(buf[1], NULL,
"\tLDX #0");
689 optim(buf[2], NULL, NULL);
700 optim(buf[2],
RULE "(STB*,STA,LDA*,STA+)->(STB*,STA,STB+)", NULL);
701 optim(buf[3], NULL,
"\tSTB %s", v3->
str);
710 optim(buf[0],
RULE "(STD*,LDD,LDX*)->(TDX,LDD)",
"\tTFR D,X");
711 optim(buf[2], NULL, NULL);
719 optim(buf[0],
RULE "(STAa,LDAa,STAb)->(STAb)", NULL );
720 optim(buf[1], NULL, NULL);
733 optim(buf[0],
RULE "(STBa,LDBa,STBb)->(STBb)", NULL );
734 optim(buf[1], NULL, NULL);
738 optim(buf[1],
RULE "(STBa,LDBa,STBb)->(STBb)", NULL );
747 optim(buf[1],
RULE "(STDa,LDDa,STDb)->(STDb)", NULL );
755 optim(buf[1],
RULE "(STDa,LDDa,STBb)->(STBb)", NULL );
764 optim(buf[1],
RULE "(STDa,LDDa,STAb)->(STBb)", NULL );
774 optim(buf[0],
RULE "(LDD*,STD+,TDX)->(LDX*,STX+)",
"\tLDX %s", v1->
str);
775 optim(buf[1], NULL,
"\tSTX %s", v2->
str);
776 optim(buf[2], NULL, NULL);
785 && strchr((
const char*)v2 ,
'+')==NULL) {
786 optim(buf[2],
RULE "(STD*,ST?,LDD*)->(STD*,ST?)", NULL);
795 optim(buf[0],
RULE "(STD*,LSLB,ROLA,STD*)->(LSLB,ROLA,STD*)", NULL);
804 optim(buf[0],
RULE "(STD*,ADDD,STD*)->(ADDD,STD*)", NULL);
815 optim(buf[0],
RULE "(unsafe, presumed dead) (STD,LOAD,STORE[])->(TDX,LOAD,STORE*X)",
"\tTFR D,X");
817 optim(buf[0],
RULE "(STD,LOAD,STORE[])",
"\tSTD _Ttmp%s\n\tTFR D,X", v1->
str);
818 optim(buf[2], NULL,
"\tST%c ,X", *v2->str);
824 optim(buf[1],
RULE "(STD,LDB+1)", NULL);
831 optim(buf[2],
RULE "(STD,?,LDB+1)", NULL);
839 optim(buf[3],
RULE "(STD,?,?,LDB+1)", NULL);
846 optim(buf[1],
RULE "(ST*a,LD*a)->(ST*a)", NULL );
856 optim(buf[1],
RULE "(STD,LDD#,ADD,STD)->(LDD,ADD#,STD)",
" LDD %s", v1->
str );
857 optim(buf[2],
RULE "(STD,LDD#,ADD,STD)->(LDD,ADD#,STD)",
" ADDD #$%s", v2->str );
858 optim(buf[3],
RULE "(STD,LDD#,ADD,STD)->(LDD,ADD#,STD)",
" STD %s", v1->
str );
865 long int vi1 = strtol(v1->
str, NULL, 16);
866 long int vi2 = strtol(v2->str, NULL, 16);
867 optim(buf[0],
RULE "(ADD#,ADD#)->(ADD#)",
" ADDD #$%4.4x", (
int)(vi1+vi2) );
868 optim(buf[1],
RULE "(ADD#,ADD#)->(ADD#)", NULL );
879 optim(buf[0],
RULE "(LDD#0,STD,LDB,ADDD,STD)->(CLRA,LDB,STD)", NULL );
880 optim(buf[1],
RULE "(LDD#0,STD,LDB,ADDD,STD)->(CLRA,LDB,STD)",
" CLRA" );
881 optim(buf[3],
RULE "(LDD#0,STD,LDB,ADDD,STD)->(CLRA,LDB,STD)", NULL );
893 optim(buf[2],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
894 optim(buf[3],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
895 optim(buf[4],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
907 optim(buf[2],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
908 optim(buf[3],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
909 optim(buf[4],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
916 optim(buf[0],
RULE "(BANKREAD1,BANWRITE1)->(BANKREADWRITE1)", NULL );
922 && strstr( v2->str,
"," ) == NULL
924 optim(buf[0],
RULE "(LDB,LDB)->(LDB)", NULL );
931 long address = strtol( v1->
str, NULL, 16 );
932 long offset = strtol( v2->str, NULL, 16 );
933 optim(buf[0],
RULE "(LDY#,LEAY+)->(LDY#+)",
"\tLDY #$%4.4x", (
unsigned int)(address+
offset) );
934 optim(buf[1],
RULE "(LDY#,LEAY+)->(LDY#+)", NULL );
943 optim(buf[0],
RULE "(LD#0,STD,LDB,ADD)->(CLRA,LDB)",
" CLRA" );
944 optim(buf[1],
RULE "(LD#0,STD,LDB,ADD)->(CLRA,LDB)", NULL );
949 optim(buf[0],
RULE "(LDD,LDD)->(LDD)", NULL );
953 optim(buf[0],
RULE "(CLRA,CLRB,LDD)->(LDD)", NULL );
954 optim(buf[1],
RULE "(CLRA,CLRB,LDD)->(LDD)", NULL );
958 optim(buf[0],
RULE "(LDD#0000)->(CLRA, CLRB)",
"\tCLRA\n\tCLRB" );
964 optim(buf[0],
RULE "(LDD#,LDB#)->(LDA)",
"\tLDA #$%2.2x", (
unsigned char)(atoi( v1->
str ) >> 8 ) );
970 optim(buf[0],
RULE "(LDD#,CLRB)->(LDA)",
"\tLDA #$%2.2x", (
unsigned char)(atoi( v1->
str ) >> 8 ) );
976 optim(buf[0],
RULE "(CLRB,LDD)->(LDD)", NULL );
982 optim(buf[0],
RULE "(CLRA,LDD)->(LDD)", NULL );
989 optim(buf[0],
RULE "(LDB#,LDD#)->(LDD)", NULL );
1001 && ( strcmp(v5->
str,
"ANDB" ) != 0 && strcmp(v5->
str,
"ORB" ) != 0 && strcmp(v5->
str,
"EORB" ) != 0 )
1006 if ( strstr(buf[1]->str,
"DECB") ) {
1007 if (strcmp(v5->
str,
"TSTB") == 0) {
1009 }
if (strstr(buf[3]->str,
"CMPB #$ff")) {
1011 }
else if ( strstr(v5->
str,
"COMB") ) {
1014 }
else if ( strstr(buf[1]->str,
"INCB") ) {
1015 if (strcmp(v5->
str,
"TSTB") == 0) {
1017 }
if (strstr(buf[3]->str,
"CMPB #$00")) {
1019 }
if (strstr(buf[3]->str,
"STB")) {
1021 }
else if ( strstr(v5->
str,
"COMB") ) {
1026 optim(buf[0],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1027 optim(buf[1],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1028 optim(buf[2],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1029 optim(buf[3],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1032 char conditional[4];
1033 if ( strcmp( v1->
str,
"CC") == 0 ) {
1036 else if ( strcmp( v1->
str,
"CS" ) == 0 ) {
1038 }
else if ( strcmp( v1->
str,
"EQ" ) == 0 ) {
1041 else if ( strcmp( v1->
str,
"GE" ) == 0 ) {
1044 else if ( strcmp( v1->
str,
"GT" ) == 0 ) {
1047 else if ( strcmp( v1->
str,
"HI" ) == 0 ) {
1050 else if ( strcmp( v1->
str,
"HS" ) == 0 ) {
1053 else if ( strcmp( v1->
str,
"LE" ) == 0 ) {
1056 else if ( strcmp( v1->
str,
"LO" ) == 0 ) {
1059 else if ( strcmp( v1->
str,
"LS" ) == 0 ) {
1062 else if ( strcmp( v1->
str,
"LT" ) == 0 ) {
1065 else if ( strcmp( v1->
str,
"MI" ) == 0 ) {
1068 else if ( strcmp( v1->
str,
"NE" ) == 0 ) {
1071 else if ( strcmp( v1->
str,
"PL" ) == 0 ) {
1074 else if ( strcmp( v1->
str,
"RA" ) == 0 ) {
1077 else if ( strcmp( v1->
str,
"RN" ) == 0 ) {
1080 else if ( strcmp( v1->
str,
"VC" ) == 0 ) {
1083 else if ( strcmp( v1->
str,
"VS" ) == 0 ) {
1090 optim(buf[5],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)",
" LB%s %s", conditional, v3->
str );
1091 optim(buf[7],
RULE "(B?,DECB,TSTB/STB,[L]B)->([L]B)",
" B%s %s", conditional, v4->
str );
1093 optim(buf[5],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)",
" LB%s %s", v1->
str, v3->
str );
1094 optim(buf[7],
RULE "(B?,DECB,TSTB/STB,[L]B)->([L]B)",
" B%s %s", v1->
str, v4->
str );
1109 optim(buf[0],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" LDX %s", v3->
str );
1110 optim(buf[1],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" LDB %s", v1->
str );
1111 optim(buf[2],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" ABX" );
1112 optim(buf[3],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" STX %s", v5->
str );
1113 optim(buf[4],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)", NULL );
1114 optim(buf[5],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)", NULL );
1138 (xxyy[0]==
'-' || xxyy[0]==value->
str[0]) &&
1139 (xxyy[1]==
'-' || xxyy[1]==value->
str[1]) &&
1140 (xxyy[2]==
'-' || xxyy[2]==value->
str[2]) &&
1141 (xxyy[3]==
'-' || xxyy[3]==value->
str[3]) ? buf : NULL;
1148 for(s = buf->
str; !_eol(*s) && *s!=
','; ++s);
1173 if(
po_buf_match(buf,
" TFR ") && s[0]==
',' && (s[1]==
'A' || s[1]==
'D'))
return 1;
1182 for(s = buf->
str; !_eol(*s) && *s!=
','; ++s);
1206 if(
po_buf_match(buf,
" TFR ") && s[0]==
',' && (s[1]==
'B' || s[1]==
'D'))
return 1;
1221 optim( buf[0],
RULE "[A=0](CLRA)->()", NULL);
1224 optim( buf[0],
RULE "[A=0](LDA#ff)->(DECA)",
"\tDECA");
1227 optim( buf[0],
RULE "[A=0](LDA#1)->(INCA)",
"\tINCA");
1233 optim( buf[0],
RULE "[A=0](TAB)->(CLRB)",
"\tCLRB");
1235 }
else if (peephole_pass>2
1239 optim(buf[1],
RULE "[A=0](STA*,LDB*)->(CLRB)",
"\tCLRB");
1242 optim(buf[0],
RULE "[D=0](ADD)->(LDD)",
"\tLDD %s", v1->
str);
1249 optim(buf[0],
"(unsafe, presumed dead)", NULL);
1252 optim(buf[2],
RULE "[D=0](STD*,LDX,CMPX*)->(LDX)", NULL);
1254 }
else if(can_nzA(buf[0])) {
1263 optim( buf[0],
RULE "[B=0](CLRB)->()", NULL);
1266 optim( buf[0],
RULE "[B=0](LDB#ff)->(DECB)",
"\tDECB");
1269 optim( buf[0],
RULE "[B=0](LDB#1)->(INCB)",
"\tINCB");
1271 }
else if ( chkLDD( buf[0],
"--00", v1) ) {
1272 optim( buf[0],
RULE "[B=0](LDB#xx00)->(LDA#xx)",
"\tLDA #$%c%c", v1->
str[0], v1->
str[1]);
1275 optim( buf[0],
RULE "[B=0](TBA)->(CLRA)",
"\tCLRA");
1277 }
else if(can_nzB(buf[0])) {
1288 optim(buf[0],
RULE "(LDB#,STB,CLRA)->(LDD#,STB)",
"\tLDD #$00%s", v1->
str);
1289 optim(buf[2], NULL, NULL);
1319static void vars_clear(
void) {
1321 for(i=0; i<vars.size; ++i) {
1322 struct var *v = &vars.tab[i];
1324 if(v->init)
free(v->init);
1333 struct var *ret = NULL;
1336 char *s=strchr(
name,
'+');
1339 for(i=0; i<vars.size ; ++i) {
1340 if(strcmp(vars.tab[i].name,
name)==0) {
1345 if(vars.size == vars.capacity) {
1346 vars.capacity += 16;
1347 vars.tab = realloc(vars.tab,
sizeof(*vars.tab)*vars.capacity);
1349 ret = &vars.tab[vars.size++];
1350 ret->name = strdup(
name);
1387 )
if(vars_ok(arg)) {
1393 ||
po_buf_match( buf[0],
" ST* *", tmp, arg) )
if(vars_ok(arg)) {
1417 )
if(vars_ok(arg)) {
1444 )
if(vars_ok(arg)) {
1450 ||
po_buf_match(buf[0],
" * [*]", tmp, arg) )
if(vars_ok(arg)) {
1452 if ( v->offset != -3 ) {
1457 if(
po_buf_match( buf[0],
"* rzb *", tmp, arg) && vars_ok(tmp)) {
1459 v->size = atoi(arg->
str);
1460 v->init = strdup(
"1-1");
1463 if(
po_buf_match(buf[0],
"* fcb *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
1466 v->init = strdup(isZero(arg->
str) ?
"1-1" : arg->
str);
1469 if(
po_buf_match(buf[0],
"* fdb *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
1472 v->init = strdup(arg->
str);
1493 if ( v->offset == -1 ) {
1502 && (*tmp->
str!=
'_' || tmp->
str[1]==
'T')) {
1503 int v = strtol(arg->
str, NULL, 16);
1504 if (v >= vars.page0_max) vars.page0_max = v+2;
1509static int vars_cmp(
const void *_a,
const void *_b) {
1510 const struct var *a = _a;
1511 const struct var *b = _b;
1513 int diff = ((a->nb_rd + a->nb_wr) - (b->nb_rd + b->nb_wr));
1515 return -(diff!=0 ? diff : strcmp(a->name, b->name));
1519static void vars_prepare_relocation(
void) {
1525 qsort(vars.tab, vars.size,
sizeof(*vars.tab), vars_cmp);
1527 for(i = 0; i<vars.size; ++i) {
1528 struct var *v = &vars.tab[i];
1531 if(v->size == 0)
continue;
1534 if(v->nb_rd == 0)
continue;
1541 if(v->offset == -1 && v->size>2) v->offset = 0;
1544 if(v->offset == -1) {
1547 int dp_cost = (3+v->size)*(v->nb_rd + v->nb_wr);
1548 int inline_cost = (4+v->size)*(v->nb_rd + v->nb_wr - 1)+(1+v->size);
1550 if( (v->init==NULL || isZero(v->init) || 0==strcmp(
"1-1", v->init)) && dp_cost < inline_cost ) {
1556 && 0==(v->flags &&
NO_DP)
1558 && vars.page0_max + v->size <= 256
1561 if ( vars.page0_max == 0xd8 )
1563 if ( vars.page0_max == 0xa3 )
1565 if ( vars.page0_max == 0xd5 )
1567 if ( vars.page0_max == 0xe3 )
1569 if ( vars.page0_max == 0xef )
1571 while ( vars.page0_max < 0xf0 )
1573 if ( vars.page0_max == 0xf0 )
1575 if ( vars.page0_max == 0xf1 )
1577 if ( vars.page0_max == 0xf2 )
1579 if ( vars.page0_max == 0xf6 )
1582 v->offset = vars.page0_max;
1583 vars.page0_max += v->size;
1598 if(
po_buf_match( buf[0],
" ST* *", op, var) && vars_ok(var)) {
1600 if(v->nb_rd == 0 && v->offset!=-2) {
1604 if(*op->
str==
'X') rep =
"\tLEAX ,X";
1607 sprintf(tst,
"\tTST%c", *op->
str);
1611 optim(buf[0],
"unread1", rep != NULL ?
"%s" : NULL, rep);
1616 if(
po_buf_match( buf[0],
" NEG *", var) && vars_ok(var)) {
1618 if(v->nb_rd == 0 && v->offset!=-2) {
1622 if(*op->
str==
'X') rep =
"\tLEAX ,X";
1625 sprintf(tst,
"\tTST%c", *op->
str);
1629 optim(buf[0],
"unread1", rep != NULL ?
"%s" : NULL, rep);
1637 ||
po_buf_match( buf[0],
"* fdb ", var) )
if(vars_ok(var)) {
1639 if(v->nb_rd==0 && 0<v->size && v->size<=4 && 0==(v->flags &
NO_REMOVE) && v->offset!=-2) {
1641 optim(buf[0],
"unread2",NULL);
1656 if(
po_buf_match( buf[0],
" * *", op, var) && vars_ok(var) ) {
1660 optim(buf[0],
"direct-page1",
"\t%s <(%s)", op->
str, var->
str);
1661 }
else if(v->offset == -1 && chg_reg(buf[0], REG)
1662 && ((strchr(
"DXYU", *REG->
str)!=NULL && v->size==2) || v->size==1) ) {
1663 if ( strstr( var->
str,
"+" ) == NULL && v->bank_read == 0 ) {
1666 optim(buf[0],
"inlined1",
"\t%s #%s%s\n%s equ *-%d", op->
str,
1667 v->init==NULL ?
"*" : v->init,
1668 v->init==NULL ? (v->size==2 ?
"" :
"&255") :
"",
1685 if(
po_buf_match( buf[0],
" * #*", op, var) && vars_ok(var) ) {
1687 if(v->offset > 0 && strstr(var->
str,
"+$")==NULL) {
1688 optim(buf[0],
"direct-page3",
"\t%s #%s+$%04x", op->
str, var->
str,
DIRECT_PAGE);
1695 ||
po_buf_match( buf[0],
"* fdb ", var) )
if(vars_ok(var)) {
1698 optim(buf[0],
"direct-page4",
"%s equ $%02x", var->
str, v->offset);
1700 }
else if(v->offset == -2 && v->bank_read == 0 ) {
1701 optim(buf[0],
"inlined3", NULL);
1709static void out(FILE *f,
POBuffer _buf) {
1710 char *s = _buf->
str;
1712 while(*s==
' ' || *s==
'\t') {
tab = 1; ++s;}
1713 if(
tab) fputs(
"\t", f);
1718static void fixes_indexed_syntax(
POBuffer buf) {
1722 if(!_eq(
' ', *s))
return;
1725 do ++s;
while(*s && _eq(
' ', *s));
1731 while(*s && !_eq(
' ', *s)) ++s;
1735 do ++s;
while(*s && _eq(
' ', *s));
1739 do ++s;
while(*s && !_eq(
' ', *s));
1745 do ++t;
while(*t && _eq(
' ', *t));
1746 switch(_toUpper(*t)) {
1747 case 'X':
case 'Y':
case 'U':
case 'S':
1762 FILE * fileOptimized;
1769 int sourceLine = -1;
1774 adiline2(
"POP:0:%d:%d", peephole_pass, kind );
1787 vars_prepare_relocation();
1799 fileAsm = fopen( _environment->
asmFileName,
"rt" );
1800 if(fileAsm == NULL) {
1805 fileOptimized = fopen( fileNameOptimized,
"wt" );
1806 if(fileOptimized == NULL) {
1807 perror(fileNameOptimized);
1817 while( still_to_go ) {
1819 if ( line >=
LOOK_AHEAD ) out(fileOptimized, buf[0]);
1836 sourceLine = atoi( ln->
str );
1849 }
while(!feof(fileAsm));
1854 basic_peephole(_environment, buf, zA, zB);
1855 optim_zAB(_environment, buf, &zA, &zB);
1865 vars_remove(_environment, buf);
1871 vars_relocate(_environment, buf);
1886 fprintf(fileOptimized,
"; peephole: pass %d, %d change%s.\n", peephole_pass,
1887 change, change>1 ?
"s":
"");
1891 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s removed.\n", peephole_pass,
1892 num_unread, num_unread>1 ?
"s":
"");
1896 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s moved to dp, %d var%s inlined.\n", peephole_pass,
1897 num_dp, num_dp>1 ?
"s":
"",
1898 num_inlined, num_inlined>1 ?
"s":
"");
1905 (void)fclose(fileAsm);
1906 (void)fclose(fileOptimized);
1919 struct _UnusedSymbol *
next;
1923static void optim_remove_unused_temporary(
Environment * _environment ) {
1940 FILE * fileOptimized;
1944 fileAsm = fopen( _environment->
asmFileName,
"rt" );
1945 if(fileAsm == NULL) {
1950 fileOptimized = fopen( fileNameOptimized,
"wt" );
1951 if(fileOptimized == NULL) {
1952 perror(fileNameOptimized);
1963 while( !feof(fileAsm) ) {
1973 s->
next = currentlyUnusedSymbols;
1974 currentlyUnusedSymbols = s;
1979 s->
next = currentlySymbols;
1980 currentlySymbols = s;
1985 s->
next = currentlyUnusedSymbolsQ;
1986 currentlyUnusedSymbolsQ = s;
1991 s->
next = currentlySymbolsQ;
1992 currentlySymbolsQ = s;
2003 fseek( fileAsm, vspPointer, SEEK_SET );
2005 while( !feof(fileAsm) ) {
2010 if ( ! result ) result =
po_buf_match(bufLine,
"* equ **-2", v2, v1 );
2011 if ( ! result ) result =
po_buf_match(bufLine,
" ADC* [*]", v2, v1 );
2012 if ( ! result ) result =
po_buf_match( bufLine,
" ADD* [*]", v2, v1);
2013 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* [*]", v2, v1);
2014 if ( ! result ) result =
po_buf_match( bufLine,
" AND* [*]", v2, v1);
2015 if ( ! result ) result =
po_buf_match( bufLine,
" CMP* [*]", v2, v1);
2016 if ( ! result ) result =
po_buf_match( bufLine,
" EOR* [*]", v2, v1);
2017 if ( ! result ) result =
po_buf_match( bufLine,
" LD* [*]", v2, v1);
2018 if ( ! result ) result =
po_buf_match( bufLine,
" OR* [*]", v2, v1);
2019 if ( ! result ) result =
po_buf_match( bufLine,
" SBC* [*]", v2, v1);
2020 if ( ! result ) result =
po_buf_match( bufLine,
" ST* [*]", v2, v1);
2021 if ( ! result ) result =
po_buf_match( bufLine,
" SUB* [*]", v2, v1);
2022 if ( ! result ) result =
po_buf_match( bufLine,
" ASL [*]", v1);
2023 if ( ! result ) result =
po_buf_match( bufLine,
" ASR [*]", v1);
2024 if ( ! result ) result =
po_buf_match( bufLine,
" TST [*]", v1);
2025 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* *", v2, v1);
2026 if ( ! result ) result =
po_buf_match( bufLine,
" ADD* *", v2, v1);
2027 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* *", v2, v1);
2028 if ( ! result ) result =
po_buf_match( bufLine,
" AND* *", v2, v1);
2029 if ( ! result ) result =
po_buf_match( bufLine,
" CMP* *", v2, v1);
2030 if ( ! result ) result =
po_buf_match( bufLine,
" EOR* *", v2, v1);
2031 if ( ! result ) result =
po_buf_match( bufLine,
" LD* #*", v2, v1);
2032 if ( ! result ) result =
po_buf_match( bufLine,
" LD* *", v2, v1);
2033 if ( ! result ) result =
po_buf_match( bufLine,
" LD* *", v2, v1);
2034 if ( ! result ) result =
po_buf_match( bufLine,
" OR* *", v2, v1);
2035 if ( ! result ) result =
po_buf_match( bufLine,
" SBC* *", v2, v1);
2036 if ( ! result ) result =
po_buf_match( bufLine,
" SUB* *", v2, v1);
2037 if ( ! result ) result =
po_buf_match( bufLine,
" ASL *", v1);
2038 if ( ! result ) result =
po_buf_match( bufLine,
" ASR *", v1);
2039 if ( ! result ) result =
po_buf_match( bufLine,
" TST *", v1);
2041 char * realVarName = strdup( v1->
str );
2042 char * c = strstr( realVarName,
"+" );
2046 c = strstr( realVarName,
"#" );
2050 c = strstr( realVarName,
"<(" );
2054 c = strstr( realVarName,
")" );
2061 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2065 currentlyUnusedSymbols = tmp->
next;
2073 tmp = currentlyUnusedSymbolsQ;
2076 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2080 currentlyUnusedSymbolsQ = tmp->
next;
2103 fseek( fileAsm, vspPointer, SEEK_SET );
2113 while( !feof(fileAsm) ) {
2115 int endOfSection = 0;
2117 if ( line >= 2 ) out(fileOptimized, buf[0]);
2123 while(
isAComment( buf[4] ) && !endOfSection && !feof( fileAsm ) ) {
2148 char * realVarName = strdup( v4->
str );
2149 char * c = strstr( realVarName,
"+" );
2153 c = strstr( realVarName,
"<(" );
2157 c = strstr( realVarName,
")" );
2164 char * realVarName2 = strdup( v6->
str );
2165 c = strstr( realVarName2,
"+" );
2169 c = strstr( realVarName2,
"<(" );
2173 c = strstr( realVarName2,
")" );
2182 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2189 if ( strcmp( realVarName2, tmp2->
realName ) == 0 ) {
2196 if ( strcmp( realVarName2, tmp3->
realName ) == 0 ) {
2201 if ( tmp && ( tmp2 || tmp3 ) ) {
2205 optim( buf[0],
RULE "unused temporary",
"\tST%s %s", v1->
str, v6->
str );
2206 optim( buf[1],
RULE "unused temporary", NULL );
2207 optim( buf[2],
RULE "unused temporary", NULL );
2216 char * realVarName = strdup( v2->
str );
2217 char * c = strstr( realVarName,
"+" );
2221 c = strstr( realVarName,
"<(" );
2225 c = strstr( realVarName,
")" );
2235 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2244 optim( buf[1],
RULE "unused temporary", NULL );
2252 ( strcmp( v5->
str,
"A" ) == 0 || strcmp( v5->
str,
"B" ) == 0 )
2257 char * realVarName = strdup( v4->
str );
2258 char * c = strstr( realVarName,
"+" );
2262 c = strstr( realVarName,
"<(" );
2266 c = strstr( realVarName,
")" );
2273 char * realVarName2 = strdup( v6->
str );
2274 c = strstr( realVarName2,
"+" );
2278 c = strstr( realVarName2,
"<(" );
2282 c = strstr( realVarName2,
")" );
2291 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2298 if ( strcmp( realVarName2, tmp2->
realName ) == 0 ) {
2305 if ( strcmp( realVarName2, tmp3->
realName ) == 0 ) {
2310 if ( tmp && ( tmp2 || tmp3 ) ) {
2314 optim( buf[0],
RULE "unused temporary",
"\tST%s %s", v5->
str, v6->
str );
2315 optim( buf[1],
RULE "unused temporary", NULL );
2316 optim( buf[2],
RULE "unused temporary", NULL );
2325 char * realVarName = strdup( v2->
str );
2326 char * c = strstr( realVarName,
"+" );
2330 c = strstr( realVarName,
"<(" );
2334 c = strstr( realVarName,
")" );
2344 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2353 optim( buf[1],
RULE "unused temporary", NULL );
2364 char * realVarName = strdup( v2->
str );
2365 char * c = strstr( realVarName,
"+" );
2369 c = strstr( realVarName,
"<(" );
2373 c = strstr( realVarName,
")" );
2380 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2388 optim( buf[1],
RULE "unused temporary", NULL );
2398 char * realVarName = strdup( v2->
str );
2399 char * c = strstr( realVarName,
"+" );
2403 c = strstr( realVarName,
"<(" );
2407 c = strstr( realVarName,
")" );
2417 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2427 optim( buf[1],
RULE "unused temporary", NULL );
2438 char * realVarName = strdup( v2->
str );
2439 char * c = strstr( realVarName,
"+" );
2443 c = strstr( realVarName,
"<(" );
2447 c = strstr( realVarName,
")" );
2457 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2467 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2476 char * realVarName = strdup( v2->
str );
2477 char * c = strstr( realVarName,
"+" );
2481 c = strstr( realVarName,
"<(" );
2485 c = strstr( realVarName,
")" );
2495 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2505 optim( buf[1],
RULE "unused temporary", NULL );
2516 char * realVarName = strdup( v2->
str );
2517 char * c = strstr( realVarName,
"+" );
2521 c = strstr( realVarName,
"<(" );
2525 c = strstr( realVarName,
")" );
2535 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2545 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2555 char * realVarName = strdup( v2->
str );
2556 char * c = strstr( realVarName,
"+" );
2560 c = strstr( realVarName,
"<(" );
2564 c = strstr( realVarName,
")" );
2574 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2584 optim( buf[1],
RULE "unused temporary", NULL );
2595 char * realVarName = strdup( v2->
str );
2596 char * c = strstr( realVarName,
"+" );
2600 c = strstr( realVarName,
"<(" );
2604 c = strstr( realVarName,
")" );
2614 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2624 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2635 char * realVarName = strdup( v2->
str );
2636 char * c = strstr( realVarName,
"+" );
2640 c = strstr( realVarName,
"<(" );
2644 c = strstr( realVarName,
")" );
2651 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2658 optim( buf[0],
RULE "unused temporary", NULL );
2663 if ( endOfSection ) {
2664 out(fileOptimized, buf[0]);
2665 out(fileOptimized, buf[1]);
2666 out(fileOptimized, buf[2]);
2667 out(fileOptimized, buf[3]);
2668 out(fileOptimized, buf[4]);
2679 vspPointer = ftell( fileAsm );
2683 currentlyUnusedSymbols = NULL;
2684 currentlyUnusedSymbolsQ = NULL;
2690 fseek( fileAsm, vspPointer, SEEK_SET );
2692 while( !feof(fileAsm) ) {
2696 out(fileOptimized, bufLine);
2700 (void)fclose(fileAsm);
2701 (void)fclose(fileOptimized);
2709static void optim_remove_comments(
Environment * _environment ) {
2717 FILE * fileOptimized;
2721 fileAsm = fopen( _environment->
asmFileName,
"rt" );
2722 if(fileAsm == NULL) {
2727 fileOptimized = fopen( fileNameOptimized,
"wt" );
2728 if(fileOptimized == NULL) {
2729 perror(fileNameOptimized);
2733 while( !feof(fileAsm) ) {
2738 out( fileOptimized, bufLine );
2743 (void)fclose(fileAsm);
2744 (void)fclose(fileOptimized);
2758 optim_remove_unused_temporary( _environment );
2771 while(optim_pass(_environment, buf,
PEEPHOLE)&&optimization_limit_count) {
2772 --optimization_limit_count;
2774 optim_pass(_environment, buf,
DEADVARS);
2775 optim_remove_unused_temporary( _environment );
2776 }
while(change&&optimization_limit_count);
2785 optim_remove_unused_temporary( _environment );
2788 optim_remove_comments(_environment);
2806 int sourceLine = -1;
2813 fileAsm = fopen( _environment->
asmFileName,
"rb" );
2814 if(fileAsm == NULL) {
2820 if(fileListing == NULL) {
2825 while( !feof(fileAsm) && !feof(fileListing)) {
2833 sourceLine = atoi( ln->
str );
2844 *bufferListing->
str = 0;
2845 int pos = ftell( fileListing );
2846 while( !feof(fileListing) && (strstr( bufferListing->
str, bufferAsm->
str ) == NULL) ) {
2851 if ( feof(fileListing) ) {
2852 fseek( fileListing, pos, SEEK_SET );
2854 char * bufferAsmEscaped = strdup( bufferAsm->
str );
2855 for(
int i=0, c=strlen(bufferAsmEscaped); i<c; ++i ) {
2856 if ( bufferAsmEscaped[i] ==
':' ) {
2857 bufferAsmEscaped[i] = 6;
2859 if ( bufferAsmEscaped[i] == 9 ) {
2860 bufferAsmEscaped[i] =
' ';
2864 if (
po_buf_match( bufferListing,
"* * *", bufferAddress, bufferBytes, bufferVersion ) ) {
2865 if ( bufferAddress->
len == 4 ) {
2867 for( i=0; i<bufferBytes->
len; ++i ) {
2868 if ( !isxdigit(bufferBytes->
str[i]) )
2871 if ( i<bufferBytes->len ) {
2889 (void)fclose(fileListing);
2890 (void)fclose(fileAsm);
char * get_temporary_filename(Environment *_environment)
struct _UnusedSymbol UnusedSymbol
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)
int po_buf_cmp(POBuffer a, POBuffer b)
POBuffer po_buf_fgets(POBuffer buf, FILE *f)
int currentSourceLineAnalyzed
FILE * additionalInfoFile
int peepholeOptimizationLimit
VestigialConfig vestigialConfig
struct _UnusedSymbol * next
#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)
char * strcopy(char *_dest, char *_source)