2014.8.3

前へ
次へ
ホームページトップへ戻る

MYCPU80でCP/Mを!
超巨大基板の8080互換HCMOS・CPUでCP/Mを走らせてしまおうという、なんとも狂気なプロジェクトです!


[第9回]


●Z80 to 8080コンバートプログラム

前回はZ80ニーモニックで書かれたソースプログラムと、それをコンバートプログラムによって8080ニーモニックにコンバートしたソースプログラムリストをお見せしました。
単純にZ80ニーモニックをその命令に対応する8080ニーモニックに置き換えたものです。
Z80には8080にはなかった多くの命令が追加されています。
当然のことながらそういう命令はそのままでは8080の命令に置き換えることはできませんから、その行の先頭に「?」をつけて示しました。
前回の8080プログラムリストでは後半の部分にそれほど多くはありませんが「?」がついているところがあります。
思ったより「?」が少ないのは、このプログラム(ZMON1M.TXT)が基本的なBIOSルーチンでZB3BASICの初期の雛形ともいうべき昔のプログラムからそれほど形を変えずに今日まで生き残っているプログラムだからです。
うんと初期のころはZ80ニーモニックではなくて8080ニーモニックを使ってプログラミングをしていましたので、それがZ80に置き換わってもZ80固有の命令を新たに使うことは、このプログラムについては余りなかったのです。

それはともかく、「?」のついた命令はそのままでは使い物になりませんから8080で実行できる命令に置き換えなくてはなりません。
その作業についてはのちほど説明いたします。
今回はZ80ニーモニックで書かれたソースプログラムを読み込んで、それを8080ニーモニックのファイルに変換して出力するコンバートプログラムをお見せします。
見ていただければわかりますように、特別のテクニックなどは何も使っていません。
読み込んだ命令行を解析してその行の中で変換が必要なところだけ新しい字句に置き換えているだけです。
Borland C++で書きました。

// translate from zilog to 8080 mnemonic
//14/6/6 6/7 6/8
/// 6/12 6/13 6/15
//
#include <stdio.h>
#include <string.h>


        FILE *rfp;
        FILE *wfp;
        char inbf[256];
        char rfname[50];
        char wfname[50];
        char rline[300];
        char wkline[300];
        char wline[310];
        char mesline[300];
        int l;
        int i;
        int j;
        int ii;
        int wi;
        int rfsize;
        int eqmk;
        int rmk;
//
        void repz(char* s,int r);
        void repz2(char* s,int r);
        void repz3(char* s,int r);
        void repz4(char* s,int r1,int r2,int r3);
        int hexck(int r);
//
void main()
{
        printf("infilename=");
        gets(rfname);
        strcat(rfname,".txt");
        printf("outfilename=");
        gets(wfname);
        strcat(wfname,".txt");
        rfp=fopen(rfname,"r");
        if(!rfp){printf("%s cannot open\n",rfname);return;}
        //printf("%s open\n",rfname);
        fseek(rfp,0,SEEK_END);rfsize=ftell(rfp);fseek(rfp,0,SEEK_SET);
        if (rfsize==0){printf("%s is empty\n",rfname);return;}
        wfp=fopen(wfname,"wb");
                if(!wfp){printf("%s cannot open\n",wfname);fclose(rfp);return;}
//
        while(1){
                if(!fgets(rline,250,rfp))break;
                l=strlen(rline);
                //printf("L=%d,%s",l,rline);
// skip TAB(09) & SPACE(20)
                i=0;
                while(i<l){
                if(rline[i]==0x09||rline[i]==0x20){i++;continue;}
                else break;
                }
                wi=i;
                j=0;
                eqmk=0;
                rmk=0;
                while(i<l){
                        wkline[j]=rline[i];
                        if(rline[i]==';')rmk=1;
                        if(rmk==1){i++;j++;continue;}
                        if(rline[i]==':'){
                                j=0;
                                wi=i+1;
                                for(ii=i+1;ii<l;ii++){
                                        wkline[j]=rline[ii];
                                        j++;
                                        }
                                break;
                                }
                        if(rline[i]=='=')eqmk=1;
                        i++;
                        j++;
                        }
                wkline[j]='\0';
                //printf("wkline=%s",wkline);//test
                if(eqmk==1) strcpy(wline,rline);
                else if(strncmp("DB",wkline,2)==0) strcpy(wline,rline);
                else if(strncmp("ORG",wkline,3)==0) strcpy(wline,rline);
                else if(strncmp(";",wkline,1)==0) strcpy(wline,rline);
                else if(strncmp("DW",wkline,2)==0) strcpy(wline,rline);
                else if(wkline[0]=='"') strcpy(wline,rline);
                else if(strncmp("DI",wkline,2)==0) strcpy(wline,rline);
                else if(strncmp("EI",wkline,2)==0) strcpy(wline,rline);
                else if(strncmp("DAA",wkline,3)==0) strcpy(wline,rline);
                else if(strncmp("NOP",wkline,3)==0) strcpy(wline,rline);
//
                else if(strncmp("LD A,I",wkline,6)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD A,R",wkline,6)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD I,A",wkline,6)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD R,A",wkline,6)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD A,(BC)",wkline,9)==0)repz("LDAX B",9);
                else if(strncmp("LD A,(DE)",wkline,9)==0)repz("LDAX D",9);
                else if(strncmp("LD A,(HL)",wkline,9)==0)repz("MOV A,M",9);
                else if(strncmp("LD A,(",wkline,6)==0)repz2("LDA ",6);
                else if(strncmp("LD (BC),A",wkline,9)==0)repz("STAX B",9);
                else if(strncmp("LD (DE),A",wkline,9)==0)repz("STAX D",9);
                else if(strncmp("LD (HL),",wkline,8)==0 && hexck(9)) repz("MVI M,",8);
                else if(strncmp("LD (HL),",wkline,8)==0)repz("MOV M,",8);
                else if(strncmp("LD A,",wkline,5)==0 && hexck(6)) repz("MVI A,",5);
                else if(strncmp("LD A,",wkline,5)==0)repz("MOV A,",5);
                else if(strncmp("LD B,(HL)",wkline,9)==0)repz("MOV B,M",9);
                else if(strncmp("LD B,",wkline,5)==0 && hexck(6)) repz("MVI B,",5);
                else if(strncmp("LD B,",wkline,5)==0)repz("MOV B,",5);
                else if(strncmp("LD C,(HL)",wkline,9)==0)repz("MOV C,M",9);
                else if(strncmp("LD C,",wkline,5)==0 && hexck(6)) repz("MVI C,",5);
                else if(strncmp("LD C,",wkline,5)==0)repz("MOV C,",5);
                else if(strncmp("LD D,(HL)",wkline,9)==0)repz("MOV D,M",9);
                else if(strncmp("LD D,",wkline,5)==0 && hexck(6)) repz("MVI D,",5);
                else if(strncmp("LD D,",wkline,5)==0)repz("MOV D,",5);
                else if(strncmp("LD E,(HL)",wkline,9)==0)repz("MOV E,M",9);
                else if(strncmp("LD E,",wkline,5)==0 && hexck(6)) repz("MVI E,",5);
                else if(strncmp("LD E,",wkline,5)==0)repz("MOV E,",5);
                else if(strncmp("LD H,(HL)",wkline,9)==0)repz("MOV H,M",9);
                else if(strncmp("LD H,",wkline,5)==0 && hexck(6)) repz("MVI H,",5);
                else if(strncmp("LD H,",wkline,5)==0)repz("MOV H,",5);
                else if(strncmp("LD L,(HL)",wkline,9)==0)repz("MOV L,M",9);
                else if(strncmp("LD L,",wkline,5)==0 && hexck(6)) repz("MVI L,",5);
                else if(strncmp("LD L,",wkline,5)==0)repz("MOV L,",5);
//
                else if(strncmp("LD BC,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD DE,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD BC",wkline,5)==0)repz("LXI B",5);
                else if(strncmp("LD DE",wkline,5)==0)repz("LXI D",5);
                else if(strncmp("LD HL,(",wkline,7)==0)repz2("LHLD ",7);
                else if(strncmp("LD HL",wkline,5)==0)repz("LXI H",5);
                else if(strncmp("LD SP,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("LD SP,HL;",wkline,9)==0)repz("SPHL",8);
                else if((strncmp("LD SP,HL",wkline,8)==0)&&(wkline[8]==0x0d))repz("SPHL",8);
                else if(strncmp("LD SP",wkline,5)==0)repz("LXI SP",5);
//
                else if(strncmp("PUSH BC",wkline,7)==0)repz("PUSH B",7);
                else if(strncmp("PUSH DE",wkline,7)==0)repz("PUSH D",7);
                else if(strncmp("PUSH HL",wkline,7)==0)repz("PUSH H",7);
                else if(strncmp("PUSH AF",wkline,7)==0)repz("PUSH PSW",7);
                else if(strncmp("POP BC",wkline,6)==0)repz("POP B",6);
                else if(strncmp("POP DE",wkline,6)==0)repz("POP D",6);
                else if(strncmp("POP HL",wkline,6)==0)repz("POP H",6);
                else if(strncmp("POP AF",wkline,6)==0)repz("POP PSW",6);
//
                else if(strncmp("EX DE,HL",wkline,8)==0)repz("XCHG",8);
                else if(strncmp("EX (SP),HL",wkline,10)==0)repz("XTHL",10);
//
                else if(strncmp("ADD A,(HL)",wkline,10)==0)repz("ADD M",10);
                else if(strncmp("ADD A,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("ADD A,",wkline,6)==0 && hexck(7)) repz("ADI ",6);
                else if(strncmp("ADD A,",wkline,6)==0)repz("ADD ",6);
                else if(strncmp("ADC A,(HL)",wkline,10)==0)repz("ADC M",10);
                else if(strncmp("ADC A,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("ADC A,",wkline,6)==0 && hexck(7)) repz("ACI ",6);
                else if(strncmp("ADC A,",wkline,6)==0)repz("ADC ",6);
                else if(strncmp("SUB (HL)",wkline,8)==0)repz("SUB M",8);
                else if(strncmp("SUB (",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("SUB ",wkline,4)==0 && hexck(5)) repz("SUI ",4);
                else if(strncmp("SUB ",wkline,4)==0) strcpy(wline,rline);
                else if(strncmp("SBC A,(HL)",wkline,10)==0)repz("SBB M",10);
                else if(strncmp("SBC A,(",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("SBC A,",wkline,6)==0 && hexck(7)) repz("SBI ",6);
                else if(strncmp("SBC A,",wkline,6)==0)repz("SBB ",6);
                else if(strncmp("AND (HL)",wkline,8)==0)repz("ANA M",8);
                else if(strncmp("AND (",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("AND ",wkline,4)==0 && hexck(5)) repz("ANI ",4);
                else if(strncmp("AND ",wkline,4)==0)repz("ANA ",4);
                else if(strncmp("OR (HL)",wkline,7)==0)repz("ORA M",7);
                else if(strncmp("OR (",wkline,4)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("OR ",wkline,3)==0 && hexck(4)) repz("ORI ",3);
                else if(strncmp("OR ",wkline,3)==0)repz("ORA ",3);
                else if(strncmp("XOR (HL)",wkline,8)==0)repz("XRA M",8);
                else if(strncmp("XOR (",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("XOR ",wkline,4)==0 && hexck(5)) repz("XRI ",4);
                else if(strncmp("XOR ",wkline,4)==0)repz("XRA ",4);
                else if(strncmp("CP (HL)",wkline,7)==0)repz("CMP M",7);
                else if(strncmp("CP (",wkline,4)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("CP ",wkline,3)==0 && hexck(4)) repz("CPI ",3);
                else if(strncmp("CP ",wkline,3)==0)repz("CMP ",3);
//
                else if(strncmp("CPL",wkline,3)==0)repz("CMA",3);
                else if(strncmp("CCF",wkline,3)==0)repz("CMC",3);
                else if(strncmp("SCF",wkline,3)==0)repz("STC",3);
                else if(strncmp("HALT",wkline,4)==0)repz("HLT",4);
//
                else if(strncmp("ADD HL,BC",wkline,9)==0)repz("DAD B",9);
                else if(strncmp("ADD HL,DE",wkline,9)==0)repz("DAD D",9);
                else if(strncmp("ADD HL,HL",wkline,9)==0)repz("DAD H",9);
                else if(strncmp("ADD HL,SP",wkline,9)==0)repz("DAD SP",9);
                else if(strncmp("INC BC",wkline,6)==0)repz("INX B",6);
                else if(strncmp("INC DE",wkline,6)==0)repz("INX D",6);
                else if(strncmp("INC HL",wkline,6)==0)repz("INX H",6);
                else if(strncmp("INC SP",wkline,6)==0)repz("INX SP",6);
                else if(strncmp("INC I",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("DEC BC",wkline,6)==0)repz("DCX B",6);
                else if(strncmp("DEC DE",wkline,6)==0)repz("DCX D",6);
                else if(strncmp("DEC HL",wkline,6)==0)repz("DCX H",6);
                else if(strncmp("DEC SP",wkline,6)==0)repz("DCX SP",6);
                else if(strncmp("DEC I",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
//
                else if(strncmp("INC (HL)",wkline,8)==0)repz("INR M",8);
                else if(strncmp("INC (",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("INC ",wkline,4)==0)repz("INR ",4);
                else if(strncmp("DEC (HL)",wkline,8)==0)repz("DCR M",8);
                else if(strncmp("DEC (",wkline,5)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("DEC ",wkline,4)==0)repz("DCR ",4);
//
                else if(strncmp("RRCA",wkline,4)==0)repz("RRC",4);
                else if(strncmp("RRA",wkline,3)==0)repz("RAR",3);
//
                else if(strncmp("RLCA",wkline,4)==0)repz("RLC",4);
                else if(strncmp("RLA",wkline,3)==0)repz("RAL",3);
                else if(strncmp("RRCA",wkline,4)==0)repz("RRC",4);
                else if(strncmp("RRA",wkline,3)==0)repz("RAR",3);
//
                else if(strncmp("JP NZ,",wkline,6)==0)repz("JNZ ",6);
                else if(strncmp("JP Z,",wkline,5)==0)repz("JZ ",5);
                else if(strncmp("JP NC,",wkline,6)==0)repz("JNC ",6);
                else if(strncmp("JP C,",wkline,5)==0)repz("JC ",5);
                else if(strncmp("JP PO,",wkline,6)==0)repz("JPO ",6);
                else if(strncmp("JP PE,",wkline,6)==0)repz("JPE ",6);
                else if(strncmp("JP P,",wkline,5)==0)repz("JP ",5);
                else if(strncmp("JP M,",wkline,5)==0)repz("JM ",5);
                else if(strncmp("JP (HL)",wkline,7)==0)repz("PCHL",7);
                else if(strncmp("JP ",wkline,3)==0)repz("JMP ",3);
//
                else if(strncmp("JR NZ,",wkline,6)==0){
                        if(wkline[6]=='*')repz("JNZ ",7);
                        else repz("JNZ ",6);}
                else if(strncmp("JR Z,",wkline,5)==0){
                        if(wkline[5]=='*')repz("JZ ",6);
                        else repz("JZ ",5);}
                else if(strncmp("JR NC,",wkline,6)==0){
                        if(wkline[6]=='*')repz("JNC ",7);
                        else repz("JNC ",6);}
                else if(strncmp("JR C,",wkline,5)==0){
                        if(wkline[5]=='*')repz("JC ",6);
                        else repz("JC ",5);}
                else if(strncmp("JR ",wkline,3)==0){
                        if(wkline[3]=='*')repz("JMP ",4);
                        else repz("JMP ",3);}
//
                else if(strncmp("CALL NZ,",wkline,8)==0)repz("CNZ ",8);
                else if(strncmp("CALL Z,",wkline,7)==0)repz("CZ ",7);
                else if(strncmp("CALL NC,",wkline,8)==0)repz("CNC ",8);
                else if(strncmp("CALL C,",wkline,7)==0)repz("CC ",7);
                else if(strncmp("CALL PO,",wkline,8)==0)repz("CPO ",8);
                else if(strncmp("CALL PE,",wkline,8)==0)repz("CPE ",8);
                else if(strncmp("CALL P,",wkline,7)==0)repz("CP ",7);
                else if(strncmp("CALL M,",wkline,7)==0)repz("CM ",7);
                else if(strncmp("CALL ",wkline,5)==0) strcpy(wline,rline);
                else if(strncmp("RST ",wkline,4)==0) strcpy(wline,rline);
//
                else if(strncmp("RET NZ",wkline,6)==0)repz("RNZ",6);
                else if(strncmp("RET Z",wkline,5)==0)repz("RZ",5);
                else if(strncmp("RET NC",wkline,6)==0)repz("RNC",6);
                else if(strncmp("RET C",wkline,5)==0)repz("RC",5);
                else if(strncmp("RET PO",wkline,6)==0)repz("RPO",6);
                else if(strncmp("RET PE",wkline,6)==0)repz("RPE",6);
                else if(strncmp("RET P",wkline,5)==0)repz("RP",5);
                else if(strncmp("RET M",wkline,5)==0)repz("RM",5);
                else if(strncmp("RET",wkline,3)==0) strcpy(wline,rline);
//
                else if(strncmp("IN A,(C)",wkline,8)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("IN A,(",wkline,6)==0)repz2("IN ",6);
                else if(strncmp("OUT (C)",wkline,7)==0){strcpy(wline,"? ");strcat(wline,rline);}
                else if(strncmp("OUT (",wkline,5)==0)repz3("OUT ",5);
//
// STA,SHLD check
//
                else if(strncmp("LD (",wkline,4)==0){
                        //strcpy(mesline,"s=");strcat(mesline,wkline);
                        //fputs(mesline,wfp);//test
                        for(i=wi+4;i<l;i++){
                                if(rline[i]==')')break;
                                }
                        if(rline[i+2]=='A')repz4("STA ",4,i,i+2);
                        else if(rline[i+2]=='H')repz4("SHLD ",4,i,i+3);
                        else  {strcpy(wline,"? ");strcat(wline,rline);}
                        }
//
                else {strcpy(wline,"? ");strcat(wline,rline);}//test
                l=strlen(wline);
                wline[l-1]=0x0d;
                wline[l]=0x0a;
                wline[l+1]='\0';
                //printf(">>L=%d,%s",j-1,wkline);
                if(!fputs(wline,wfp)){printf("wferr\n");break;}
                }
        fclose(rfp);
        fclose(wfp);
        printf("end\n");
}
//
void repz(char* s,int r){
        strcpy(wline,rline);
        wline[wi]='\0';
        strcat(wline,s);
        j=wi+strlen(s);
        for(i=wi+r;i<l;i++){
                wline[j]=rline[i];
                j++;
                }
        wline[j]='\0';
        return;
        }
//
// repz2 replace for IN
// cut ')'
// IN A,(xx) > IN xx
void repz2(char* s,int r){
        strcpy(wline,rline);
        wline[wi]='\0';
        strcat(wline,s);
        j=wi+strlen(s);
        for(i=wi+r;i<l;i++){
                if(rline[i]==')'){}
                else {wline[j]=rline[i];j++;}
                }
        wline[j]='\0';
        return;
        }
//
// repz3 replace for OUT
// cut '),A'
//
void repz3(char* s,int r){
        strcpy(wline,rline);
        wline[wi]='\0';
        strcat(wline,s);
        j=wi+strlen(s);
        for(i=wi+r;i<l;i++){
                if(rline[i]==')'){}
                else if(rline[i]==','){}
                else if(rline[i]=='A'){}
                else {wline[j]=rline[i];j++;}
                }
        wline[j]='\0';
        return;
        }
//
// repz4 replace for STA,SHLD
// cut "),A" or "),HL"

void repz4(char* s,int r1,int r2,int r3){
        strcpy(wline,rline);
        wline[wi]='\0';
        strcat(wline,s);
        j=wi+strlen(s);
        for(i=wi+r1;i<r2;i++){wline[j]=rline[i];j++;}
        for(i=r3+1;i<l;i++){wline[j]=rline[i];j++;}
        wline[j]='\0';
        return;
        }
//
int hexck(int r){
        if(wkline[r]<0x30)return 0;
        if(wkline[r]>0x39 && wkline[r]<0x41)return 0;
        if(wkline[r]>0x46)return 0;
        return 1;
        }
//


実際に実行してみるといくつかバグがみつかって、発見する都度プログラムを何回か修正しました。
あるいはまだ気が付かないバグが残っているかもしれませんが、前にも書きましたように、この先また出番があるプログラムとも思えませんので、ここまでできれば十分でありましょう。

MYCPU80でCP/Mを![第9回]
2014.8.3upload

前へ
次へ
ホームページトップへ戻る