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 "(CLRS,LDD)->(LDD)", NULL );
962 optim(buf[0],
RULE "(LDD#0000)->(CLRA, CLRB)",
"\tCLRD" );
968 optim(buf[0],
RULE "(LDD#,LDB#)->(LDA)",
"\tLDA #$%2.2x", (
unsigned char)(atoi( v1->
str ) >> 8 ) );
974 optim(buf[0],
RULE "(LDD#,CLRB)->(LDA)",
"\tLDA #$%2.2x", (
unsigned char)(atoi( v1->
str ) >> 8 ) );
980 optim(buf[0],
RULE "(CLRB,LDD)->(LDD)", NULL );
986 optim(buf[0],
RULE "(CLRA,LDD)->(LDD)", NULL );
993 optim(buf[0],
RULE "(LDB#,LDD#)->(LDD)", NULL );
1005 && ( strcmp(v5->
str,
"ANDB" ) != 0 && strcmp(v5->
str,
"ORB" ) != 0 && strcmp(v5->
str,
"EORB" ) != 0 )
1010 if ( strstr(buf[1]->str,
"DECB") ) {
1011 if (strcmp(v5->
str,
"TSTB") == 0) {
1013 }
if (strstr(buf[3]->str,
"CMPB #$ff")) {
1015 }
else if ( strstr(v5->
str,
"COMB") ) {
1018 }
else if ( strstr(buf[1]->str,
"INCB") ) {
1019 if (strcmp(v5->
str,
"TSTB") == 0) {
1021 }
if (strstr(buf[3]->str,
"CMPB #$00")) {
1023 }
if (strstr(buf[3]->str,
"STB")) {
1025 }
else if ( strstr(v5->
str,
"COMB") ) {
1030 optim(buf[0],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1031 optim(buf[1],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1032 optim(buf[2],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1033 optim(buf[3],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)", NULL );
1036 char conditional[4];
1037 if ( strcmp( v1->
str,
"CC") == 0 ) {
1040 else if ( strcmp( v1->
str,
"CS" ) == 0 ) {
1042 }
else if ( strcmp( v1->
str,
"EQ" ) == 0 ) {
1045 else if ( strcmp( v1->
str,
"GE" ) == 0 ) {
1048 else if ( strcmp( v1->
str,
"GT" ) == 0 ) {
1051 else if ( strcmp( v1->
str,
"HI" ) == 0 ) {
1054 else if ( strcmp( v1->
str,
"HS" ) == 0 ) {
1057 else if ( strcmp( v1->
str,
"LE" ) == 0 ) {
1060 else if ( strcmp( v1->
str,
"LO" ) == 0 ) {
1063 else if ( strcmp( v1->
str,
"LS" ) == 0 ) {
1066 else if ( strcmp( v1->
str,
"LT" ) == 0 ) {
1069 else if ( strcmp( v1->
str,
"MI" ) == 0 ) {
1072 else if ( strcmp( v1->
str,
"NE" ) == 0 ) {
1075 else if ( strcmp( v1->
str,
"PL" ) == 0 ) {
1078 else if ( strcmp( v1->
str,
"RA" ) == 0 ) {
1081 else if ( strcmp( v1->
str,
"RN" ) == 0 ) {
1084 else if ( strcmp( v1->
str,
"VC" ) == 0 ) {
1087 else if ( strcmp( v1->
str,
"VS" ) == 0 ) {
1094 optim(buf[5],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)",
" LB%s %s", conditional, v3->
str );
1095 optim(buf[7],
RULE "(B?,DECB,TSTB/STB,[L]B)->([L]B)",
" B%s %s", conditional, v4->
str );
1097 optim(buf[5],
RULE "(B,DECB,TSTB/STB,[L]B)->([L]B)",
" LB%s %s", v1->
str, v3->
str );
1098 optim(buf[7],
RULE "(B?,DECB,TSTB/STB,[L]B)->([L]B)",
" B%s %s", v1->
str, v4->
str );
1113 optim(buf[0],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" LDX %s", v3->
str );
1114 optim(buf[1],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" LDB %s", v1->
str );
1115 optim(buf[2],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" ABX" );
1116 optim(buf[3],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)",
" STX %s", v5->
str );
1117 optim(buf[4],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)", NULL );
1118 optim(buf[5],
RULE "(CLRA,LDB,STD,LDD,ADD,STD)->(CLRA,LDB)", NULL );
1142 (xxyy[0]==
'-' || xxyy[0]==value->
str[0]) &&
1143 (xxyy[1]==
'-' || xxyy[1]==value->
str[1]) &&
1144 (xxyy[2]==
'-' || xxyy[2]==value->
str[2]) &&
1145 (xxyy[3]==
'-' || xxyy[3]==value->
str[3]) ? buf : NULL;
1152 for(s = buf->
str; !_eol(*s) && *s!=
','; ++s);
1177 if(
po_buf_match(buf,
" TFR ") && s[0]==
',' && (s[1]==
'A' || s[1]==
'D'))
return 1;
1186 for(s = buf->
str; !_eol(*s) && *s!=
','; ++s);
1210 if(
po_buf_match(buf,
" TFR ") && s[0]==
',' && (s[1]==
'B' || s[1]==
'D'))
return 1;
1225 optim( buf[0],
RULE "[A=0](CLRA)->()", NULL);
1228 optim( buf[0],
RULE "[A=0](LDA#ff)->(DECA)",
"\tDECA");
1231 optim( buf[0],
RULE "[A=0](LDA#1)->(INCA)",
"\tINCA");
1237 optim( buf[0],
RULE "[A=0](TAB)->(CLRB)",
"\tCLRB");
1239 }
else if (peephole_pass>2
1243 optim(buf[1],
RULE "[A=0](STA*,LDB*)->(CLRB)",
"\tCLRB");
1246 optim(buf[0],
RULE "[D=0](ADD)->(LDD)",
"\tLDD %s", v1->
str);
1253 optim(buf[0],
"(unsafe, presumed dead)", NULL);
1256 optim(buf[2],
RULE "[D=0](STD*,LDX,CMPX*)->(LDX)", NULL);
1258 }
else if(can_nzA(buf[0])) {
1273 optim( buf[0],
RULE "[B=0](CLRB)->()", NULL);
1276 optim( buf[0],
RULE "[B=0](LDB#ff)->(DECB)",
"\tDECB");
1279 optim( buf[0],
RULE "[B=0](LDB#1)->(INCB)",
"\tINCB");
1281 }
else if ( chkLDD( buf[0],
"--00", v1) ) {
1282 optim( buf[0],
RULE "[B=0](LDB#xx00)->(LDA#xx)",
"\tLDA #$%c%c", v1->
str[0], v1->
str[1]);
1285 optim( buf[0],
RULE "[B=0](TBA)->(CLRA)",
"\tCLRA");
1287 }
else if(can_nzB(buf[0])) {
1304 optim(buf[0],
RULE "(LDB#,STB,CLRA)->(LDD#,STB)",
"\tLDD #$00%s", v1->
str);
1305 optim(buf[2], NULL, NULL);
1335static void vars_clear(
void) {
1337 for(i=0; i<vars.size; ++i) {
1338 struct var *v = &vars.tab[i];
1340 if(v->init)
free(v->init);
1349 struct var *ret = NULL;
1352 char *s=strchr(
name,
'+');
1355 for(i=0; i<vars.size ; ++i) {
1356 if(strcmp(vars.tab[i].name,
name)==0) {
1361 if(vars.size == vars.capacity) {
1362 vars.capacity += 16;
1363 vars.tab = realloc(vars.tab,
sizeof(*vars.tab)*vars.capacity);
1365 ret = &vars.tab[vars.size++];
1366 ret->name = strdup(
name);
1392 ||
po_buf_match( buf[0],
" * <*", NULL, arg) )
if(vars_ok(arg)) {
1400 )
if(vars_ok(arg)) {
1406 ||
po_buf_match( buf[0],
" ST* *", tmp, arg) )
if(vars_ok(arg)) {
1433 )
if(vars_ok(arg)) {
1460 )
if(vars_ok(arg)) {
1466 ||
po_buf_match(buf[0],
" * [*]", tmp, arg) )
if(vars_ok(arg)) {
1468 if ( v->offset != -3 ) {
1473 if(
po_buf_match( buf[0],
"* rzb *", tmp, arg) && vars_ok(tmp)) {
1475 v->size = atoi(arg->
str);
1476 v->init = strdup(
"1-1");
1479 if(
po_buf_match(buf[0],
"* fcb *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
1482 v->init = strdup(isZero(arg->
str) ?
"1-1" : arg->
str);
1485 if(
po_buf_match(buf[0],
"* fdb *", tmp, arg) && vars_ok(tmp) && strchr(buf[0]->str,
',')==NULL) {
1488 v->init = strdup(arg->
str);
1509 if ( v->offset == -1 ) {
1518 && (*tmp->
str!=
'_' || tmp->
str[1]==
'T')) {
1519 int v = strtol(arg->
str, NULL, 16);
1520 if (v >= vars.page0_max) vars.page0_max = v+2;
1525static int vars_cmp(
const void *_a,
const void *_b) {
1526 const struct var *a = _a;
1527 const struct var *b = _b;
1529 int diff = ((a->nb_rd + a->nb_wr) - (b->nb_rd + b->nb_wr));
1531 return -(diff!=0 ? diff : strcmp(a->name, b->name));
1535static void vars_prepare_relocation(
void) {
1541 qsort(vars.tab, vars.size,
sizeof(*vars.tab), vars_cmp);
1543 for(i = 0; i<vars.size; ++i) {
1544 struct var *v = &vars.tab[i];
1547 if(v->size == 0)
continue;
1550 if(v->nb_rd == 0)
continue;
1557 if(v->offset == -1 && v->size>2) v->offset = 0;
1560 if(v->offset == -1) {
1563 int dp_cost = (3+v->size)*(v->nb_rd + v->nb_wr);
1564 int inline_cost = (4+v->size)*(v->nb_rd + v->nb_wr - 1)+(1+v->size);
1566 if( (v->init==NULL || isZero(v->init) || 0==strcmp(
"1-1", v->init)) && dp_cost < inline_cost ) {
1572 && 0==(v->flags &&
NO_DP)
1574 && vars.page0_max + v->size <= 256
1577 if ( vars.page0_max == 0xd8 )
1579 if ( vars.page0_max == 0xa3 )
1581 if ( vars.page0_max == 0xd5 )
1583 if ( vars.page0_max == 0xe3 )
1585 if ( vars.page0_max == 0xef )
1587 while ( vars.page0_max < 0xf0 )
1589 if ( vars.page0_max == 0xf0 )
1591 if ( vars.page0_max == 0xf1 )
1593 if ( vars.page0_max == 0xf2 )
1595 if ( vars.page0_max == 0xf6 )
1598 v->offset = vars.page0_max;
1599 vars.page0_max += v->size;
1614 if(
po_buf_match( buf[0],
" ST* *", op, var) && vars_ok(var)) {
1616 if(v->nb_rd == 0 && v->offset!=-2) {
1620 if(*op->
str==
'X') rep =
"\tLEAX ,X";
1623 sprintf(tst,
"\tTST%c", *op->
str);
1627 optim(buf[0],
"unread1", rep != NULL ?
"%s" : NULL, rep);
1632 if(
po_buf_match( buf[0],
" NEG *", var) && vars_ok(var)) {
1634 if(v->nb_rd == 0 && v->offset!=-2) {
1638 if(*op->
str==
'X') rep =
"\tLEAX ,X";
1641 sprintf(tst,
"\tTST%c", *op->
str);
1645 optim(buf[0],
"unread1", rep != NULL ?
"%s" : NULL, rep);
1653 ||
po_buf_match( buf[0],
"* fdb ", var) )
if(vars_ok(var)) {
1655 if(v->nb_rd==0 && 0<v->size && v->size<=4 && 0==(v->flags &
NO_REMOVE) && v->offset!=-2) {
1657 optim(buf[0],
"unread2",NULL);
1672 if(
po_buf_match( buf[0],
" * *", op, var) && vars_ok(var) ) {
1676 optim(buf[0],
"direct-page1",
"\t%s <(%s)", op->
str, var->
str);
1677 }
else if(v->offset == -1 && chg_reg(buf[0], REG)
1678 && ((strchr(
"DXYU", *REG->
str)!=NULL && v->size==2) || v->size==1) ) {
1679 if ( strstr( var->
str,
"+" ) == NULL && v->bank_read == 0 ) {
1682 optim(buf[0],
"inlined1",
"\t%s #%s%s\n%s equ *-%d", op->
str,
1683 v->init==NULL ?
"*" : v->init,
1684 v->init==NULL ? (v->size==2 ?
"" :
"&255") :
"",
1701 if(
po_buf_match( buf[0],
" * #*", op, var) && vars_ok(var) ) {
1703 if(v->offset > 0 && strstr(var->
str,
"+$")==NULL) {
1704 optim(buf[0],
"direct-page3",
"\t%s #%s+$%04x", op->
str, var->
str,
DIRECT_PAGE);
1711 ||
po_buf_match( buf[0],
"* fdb ", var) )
if(vars_ok(var)) {
1714 optim(buf[0],
"direct-page4",
"%s equ $%02x", var->
str, v->offset);
1716 }
else if(v->offset == -2 && v->bank_read == 0 ) {
1717 optim(buf[0],
"inlined3", NULL);
1725static void out(FILE *f,
POBuffer _buf) {
1726 char *s = _buf->
str;
1728 while(*s==
' ' || *s==
'\t') {
tab = 1; ++s;}
1729 if(
tab) fputs(
"\t", f);
1734static void fixes_indexed_syntax(
POBuffer buf) {
1738 if(!_eq(
' ', *s))
return;
1741 do ++s;
while(*s && _eq(
' ', *s));
1747 while(*s && !_eq(
' ', *s)) ++s;
1751 do ++s;
while(*s && _eq(
' ', *s));
1755 do ++s;
while(*s && !_eq(
' ', *s));
1761 do ++t;
while(*t && _eq(
' ', *t));
1762 switch(_toUpper(*t)) {
1763 case 'X':
case 'Y':
case 'U':
case 'S':
1778 FILE * fileOptimized;
1785 int sourceLine = -1;
1790 adiline2(
"POP:0:%d:%d", peephole_pass, kind );
1803 vars_prepare_relocation();
1815 fileAsm = fopen( _environment->
asmFileName,
"rt" );
1816 if(fileAsm == NULL) {
1821 fileOptimized = fopen( fileNameOptimized,
"wt" );
1822 if(fileOptimized == NULL) {
1823 perror(fileNameOptimized);
1833 while( still_to_go ) {
1835 if ( line >=
LOOK_AHEAD ) out(fileOptimized, buf[0]);
1852 sourceLine = atoi( ln->
str );
1865 }
while(!feof(fileAsm));
1870 basic_peephole(_environment, buf, zA, zB);
1871 optim_zAB(_environment, buf, &zA, &zB);
1881 vars_remove(_environment, buf);
1887 vars_relocate(_environment, buf);
1902 fprintf(fileOptimized,
"; peephole: pass %d, %d change%s.\n", peephole_pass,
1903 change, change>1 ?
"s":
"");
1907 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s removed.\n", peephole_pass,
1908 num_unread, num_unread>1 ?
"s":
"");
1912 fprintf(fileOptimized,
"; peephole: pass %d, %d var%s moved to dp, %d var%s inlined.\n", peephole_pass,
1913 num_dp, num_dp>1 ?
"s":
"",
1914 num_inlined, num_inlined>1 ?
"s":
"");
1921 (void)fclose(fileAsm);
1922 (void)fclose(fileOptimized);
1935 struct _UnusedSymbol *
next;
1939static void optim_remove_unused_temporary(
Environment * _environment ) {
1956 FILE * fileOptimized;
1960 fileAsm = fopen( _environment->
asmFileName,
"rt" );
1961 if(fileAsm == NULL) {
1966 fileOptimized = fopen( fileNameOptimized,
"wt" );
1967 if(fileOptimized == NULL) {
1968 perror(fileNameOptimized);
1979 while( !feof(fileAsm) ) {
1989 s->
next = currentlyUnusedSymbols;
1990 currentlyUnusedSymbols = s;
1995 s->
next = currentlySymbols;
1996 currentlySymbols = s;
2001 s->
next = currentlyUnusedSymbolsQ;
2002 currentlyUnusedSymbolsQ = s;
2007 s->
next = currentlySymbolsQ;
2008 currentlySymbolsQ = s;
2019 fseek( fileAsm, vspPointer, SEEK_SET );
2021 while( !feof(fileAsm) ) {
2026 if ( ! result ) result =
po_buf_match(bufLine,
"* equ **-2", v2, v1 );
2027 if ( ! result ) result =
po_buf_match(bufLine,
" ADC* [*]", v2, v1 );
2028 if ( ! result ) result =
po_buf_match( bufLine,
" ADD* [*]", v2, v1);
2029 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* [*]", v2, v1);
2030 if ( ! result ) result =
po_buf_match( bufLine,
" AND* [*]", v2, v1);
2031 if ( ! result ) result =
po_buf_match( bufLine,
" CMP* [*]", v2, v1);
2032 if ( ! result ) result =
po_buf_match( bufLine,
" EOR* [*]", 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,
" ST* [*]", v2, v1);
2037 if ( ! result ) result =
po_buf_match( bufLine,
" SUB* [*]", v2, v1);
2038 if ( ! result ) result =
po_buf_match( bufLine,
" ASL [*]", v1);
2039 if ( ! result ) result =
po_buf_match( bufLine,
" ASR [*]", v1);
2040 if ( ! result ) result =
po_buf_match( bufLine,
" TST [*]", v1);
2041 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* *", v2, v1);
2042 if ( ! result ) result =
po_buf_match( bufLine,
" ADD* *", v2, v1);
2043 if ( ! result ) result =
po_buf_match( bufLine,
" ADC* *", v2, v1);
2044 if ( ! result ) result =
po_buf_match( bufLine,
" AND* *", v2, v1);
2045 if ( ! result ) result =
po_buf_match( bufLine,
" CMP* *", v2, v1);
2046 if ( ! result ) result =
po_buf_match( bufLine,
" EOR* *", v2, v1);
2047 if ( ! result ) result =
po_buf_match( bufLine,
" LD* #*", v2, v1);
2048 if ( ! result ) result =
po_buf_match( bufLine,
" LD* *", v2, v1);
2049 if ( ! result ) result =
po_buf_match( bufLine,
" LD* *", v2, v1);
2050 if ( ! result ) result =
po_buf_match( bufLine,
" OR* *", v2, v1);
2051 if ( ! result ) result =
po_buf_match( bufLine,
" SBC* *", v2, v1);
2052 if ( ! result ) result =
po_buf_match( bufLine,
" SUB* *", v2, v1);
2053 if ( ! result ) result =
po_buf_match( bufLine,
" ASL *", v1);
2054 if ( ! result ) result =
po_buf_match( bufLine,
" ASR *", v1);
2055 if ( ! result ) result =
po_buf_match( bufLine,
" TST *", v1);
2057 char * realVarName = strdup( v1->
str );
2058 char * c = strstr( realVarName,
"+" );
2062 c = strstr( realVarName,
"#" );
2066 c = strstr( realVarName,
"<(" );
2070 c = strstr( realVarName,
")" );
2077 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2081 currentlyUnusedSymbols = tmp->
next;
2089 tmp = currentlyUnusedSymbolsQ;
2092 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2096 currentlyUnusedSymbolsQ = tmp->
next;
2119 fseek( fileAsm, vspPointer, SEEK_SET );
2129 while( !feof(fileAsm) ) {
2131 int endOfSection = 0;
2133 if ( line >= 2 ) out(fileOptimized, buf[0]);
2139 while(
isAComment( buf[4] ) && !endOfSection && !feof( fileAsm ) ) {
2164 char * realVarName = strdup( v4->
str );
2165 char * c = strstr( realVarName,
"+" );
2169 c = strstr( realVarName,
"<(" );
2173 c = strstr( realVarName,
")" );
2180 char * realVarName2 = strdup( v6->
str );
2181 c = strstr( realVarName2,
"+" );
2185 c = strstr( realVarName2,
"<(" );
2189 c = strstr( realVarName2,
")" );
2198 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2205 if ( strcmp( realVarName2, tmp2->
realName ) == 0 ) {
2212 if ( strcmp( realVarName2, tmp3->
realName ) == 0 ) {
2217 if ( tmp && ( tmp2 || tmp3 ) ) {
2221 optim( buf[0],
RULE "unused temporary",
"\tST%s %s", v1->
str, v6->
str );
2222 optim( buf[1],
RULE "unused temporary", NULL );
2223 optim( buf[2],
RULE "unused temporary", NULL );
2232 char * realVarName = strdup( v2->
str );
2233 char * c = strstr( realVarName,
"+" );
2237 c = strstr( realVarName,
"<(" );
2241 c = strstr( realVarName,
")" );
2251 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2260 optim( buf[1],
RULE "unused temporary", NULL );
2268 ( strcmp( v5->
str,
"A" ) == 0 || strcmp( v5->
str,
"B" ) == 0 )
2273 char * realVarName = strdup( v4->
str );
2274 char * c = strstr( realVarName,
"+" );
2278 c = strstr( realVarName,
"<(" );
2282 c = strstr( realVarName,
")" );
2289 char * realVarName2 = strdup( v6->
str );
2290 c = strstr( realVarName2,
"+" );
2294 c = strstr( realVarName2,
"<(" );
2298 c = strstr( realVarName2,
")" );
2307 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2314 if ( strcmp( realVarName2, tmp2->
realName ) == 0 ) {
2321 if ( strcmp( realVarName2, tmp3->
realName ) == 0 ) {
2326 if ( tmp && ( tmp2 || tmp3 ) ) {
2330 optim( buf[0],
RULE "unused temporary",
"\tST%s %s", v5->
str, v6->
str );
2331 optim( buf[1],
RULE "unused temporary", NULL );
2332 optim( buf[2],
RULE "unused temporary", NULL );
2341 char * realVarName = strdup( v2->
str );
2342 char * c = strstr( realVarName,
"+" );
2346 c = strstr( realVarName,
"<(" );
2350 c = strstr( realVarName,
")" );
2360 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2369 optim( buf[1],
RULE "unused temporary", NULL );
2380 char * realVarName = strdup( v2->
str );
2381 char * c = strstr( realVarName,
"+" );
2385 c = strstr( realVarName,
"<(" );
2389 c = strstr( realVarName,
")" );
2396 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2404 optim( buf[1],
RULE "unused temporary", NULL );
2414 char * realVarName = strdup( v2->
str );
2415 char * c = strstr( realVarName,
"+" );
2419 c = strstr( realVarName,
"<(" );
2423 c = strstr( realVarName,
")" );
2433 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2443 optim( buf[1],
RULE "unused temporary", NULL );
2454 char * realVarName = strdup( v2->
str );
2455 char * c = strstr( realVarName,
"+" );
2459 c = strstr( realVarName,
"<(" );
2463 c = strstr( realVarName,
")" );
2473 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2483 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2492 char * realVarName = strdup( v2->
str );
2493 char * c = strstr( realVarName,
"+" );
2497 c = strstr( realVarName,
"<(" );
2501 c = strstr( realVarName,
")" );
2511 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2521 optim( buf[1],
RULE "unused temporary", NULL );
2532 char * realVarName = strdup( v2->
str );
2533 char * c = strstr( realVarName,
"+" );
2537 c = strstr( realVarName,
"<(" );
2541 c = strstr( realVarName,
")" );
2551 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2561 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2571 char * realVarName = strdup( v2->
str );
2572 char * c = strstr( realVarName,
"+" );
2576 c = strstr( realVarName,
"<(" );
2580 c = strstr( realVarName,
")" );
2590 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2600 optim( buf[1],
RULE "unused temporary", NULL );
2611 char * realVarName = strdup( v2->
str );
2612 char * c = strstr( realVarName,
"+" );
2616 c = strstr( realVarName,
"<(" );
2620 c = strstr( realVarName,
")" );
2630 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2640 optim( buf[2],
RULE "unused temporary",
"\tTST%s", v1->
str );
2653 char * realVarName = strdup( v2->
str );
2654 char * c = strstr( realVarName,
"+" );
2658 c = strstr( realVarName,
"<(" );
2662 c = strstr( realVarName,
")" );
2669 if ( strcmp( realVarName, tmp->
realName ) == 0 ) {
2676 optim( buf[0],
RULE "unused temporary", NULL );
2681 if ( endOfSection ) {
2682 out(fileOptimized, buf[0]);
2683 out(fileOptimized, buf[1]);
2684 out(fileOptimized, buf[2]);
2685 out(fileOptimized, buf[3]);
2686 out(fileOptimized, buf[4]);
2697 vspPointer = ftell( fileAsm );
2701 currentlyUnusedSymbols = NULL;
2702 currentlyUnusedSymbolsQ = NULL;
2708 fseek( fileAsm, vspPointer, SEEK_SET );
2710 while( !feof(fileAsm) ) {
2714 out(fileOptimized, bufLine);
2718 (void)fclose(fileAsm);
2719 (void)fclose(fileOptimized);
2727static void optim_remove_comments(
Environment * _environment ) {
2735 FILE * fileOptimized;
2739 fileAsm = fopen( _environment->
asmFileName,
"rt" );
2740 if(fileAsm == NULL) {
2745 fileOptimized = fopen( fileNameOptimized,
"wt" );
2746 if(fileOptimized == NULL) {
2747 perror(fileNameOptimized);
2751 while( !feof(fileAsm) ) {
2756 out( fileOptimized, bufLine );
2761 (void)fclose(fileAsm);
2762 (void)fclose(fileOptimized);
2776 optim_remove_unused_temporary( _environment );
2789 while(optim_pass(_environment, buf,
PEEPHOLE)&&optimization_limit_count) {
2790 --optimization_limit_count;
2792 optim_pass(_environment, buf,
DEADVARS);
2793 optim_remove_unused_temporary( _environment );
2794 }
while(change&&optimization_limit_count);
2803 optim_remove_unused_temporary( _environment );
2806 optim_remove_comments(_environment);
2824 int sourceLine = -1;
2831 fileAsm = fopen( _environment->
asmFileName,
"rb" );
2832 if(fileAsm == NULL) {
2838 if(fileListing == NULL) {
2843 while( !feof(fileAsm) && !feof(fileListing)) {
2851 sourceLine = atoi( ln->
str );
2862 *bufferListing->
str = 0;
2863 int pos = ftell( fileListing );
2864 while( !feof(fileListing) && (strstr( bufferListing->
str, bufferAsm->
str ) == NULL) ) {
2869 if ( feof(fileListing) ) {
2870 fseek( fileListing, pos, SEEK_SET );
2872 char * bufferAsmEscaped = strdup( bufferAsm->
str );
2873 for(
int i=0, c=strlen(bufferAsmEscaped); i<c; ++i ) {
2874 if ( bufferAsmEscaped[i] ==
':' ) {
2875 bufferAsmEscaped[i] = 6;
2877 if ( bufferAsmEscaped[i] == 9 ) {
2878 bufferAsmEscaped[i] =
' ';
2882 if (
po_buf_match( bufferListing,
"* * *", bufferAddress, bufferBytes, bufferVersion ) ) {
2883 if ( bufferAddress->
len == 4 ) {
2885 for( i=0; i<bufferBytes->
len; ++i ) {
2886 if ( !isxdigit(bufferBytes->
str[i]) )
2889 if ( i<bufferBytes->len ) {
2907 (void)fclose(fileListing);
2908 (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)