BBC Basic in Z80 emulation on the mbed, USB serial terminal output only. LOAD and SAVE work on the local file system but there is no error signalling.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers edops.h Source File

edops.h

00001 /* Emulations of the ED operations of the Z80 instruction set.
00002  * Copyright (C) 1994 Ian Collier.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #define input(var) {  var=in(c);\
00020                      f=(f&1)|(var&0xa8)|((!var)<<6)|parity(var);\
00021                    }
00022 #define sbchl(x) {    unsigned short z=(x);\
00023                       unsigned long t=(hl-z-cy)&0x1ffff;\
00024                       f=((t>>8)&0xa8)|(t>>16)|2|\
00025                         (((hl&0xfff)<(z&0xfff)+cy)<<4)|\
00026                         (((hl^z)&(hl^t)&0x8000)>>13)|\
00027                         ((!(t&0xffff))<<6)|2;\
00028                       l=t;\
00029                       h=t>>8;\
00030                    }
00031 
00032 #define adchl(x) {    unsigned short z=(x);\
00033                       unsigned long t=hl+z+cy;\
00034                       f=((t>>8)&0xa8)|(t>>16)|\
00035                         (((hl&0xfff)+(z&0xfff)+cy>0xfff)<<4)|\
00036                         (((~hl^z)&(hl^t)&0x8000)>>13)|\
00037                         ((!(t&0xffff))<<6)|2;\
00038                       l=t;\
00039                       h=t>>8;\
00040                  }
00041 
00042 #define neg (a=-a,\
00043             f=(a&0xa8)|((!a)<<6)|(((a&15)>0)<<4)|((a==128)<<2)|2|(a>0))
00044 
00045 {
00046    unsigned char op=fetch(pc);
00047    pc++;
00048    
00049 // IN B,(C)   
00050    switch(op){
00051 instr(0x40,8);
00052    input(b);
00053 endinstr;
00054 
00055 // OUT (C),B
00056 instr(0x41,8);
00057    out(c,b);
00058 endinstr;
00059 
00060 // SBC HL,BC
00061 instr(0x42,11);
00062    sbchl(bc);
00063 endinstr;
00064 
00065 // LD (nn),BC
00066 instr(0x43,16);
00067    {unsigned short addr=fetch2(pc);
00068     pc+=2;
00069     store2b(addr,b,c);
00070    }
00071 endinstr;
00072 
00073 // NEG
00074 instr(0x44,4);
00075    neg;
00076 endinstr;
00077 
00078 // RETN
00079 instr(0x45,4);
00080    iff1=iff2;
00081    ret;
00082 endinstr;
00083 
00084 // IM 0
00085 instr(0x46,4);
00086    im=0;
00087 endinstr;
00088 
00089 // LD I,A
00090 instr(0x47,5);
00091    i=a;
00092 endinstr;
00093 
00094 // IN C,(C)
00095 instr(0x48,8);
00096    input(c);
00097 endinstr;
00098 
00099 // OUT (C),C
00100 instr(0x49,8);
00101    out(c,c);
00102 endinstr;
00103 
00104 // ADC HL,BC
00105 instr(0x4a,11);
00106    adchl(bc);
00107 endinstr;
00108 
00109 // LD BC,(nn)
00110 instr(0x4b,16);
00111    {unsigned short addr=fetch2(pc);
00112     pc+=2;
00113     c=fetch(addr);
00114     b=fetch(addr+1);
00115    }
00116 endinstr;
00117 
00118 // ?
00119 instr(0x4c,4);
00120    neg;
00121 endinstr;
00122 
00123 // RETI
00124 instr(0x4d,4);
00125    ret;
00126 endinstr;
00127 
00128 // ?
00129 instr(0x4e,4);
00130    im=1;
00131 endinstr;
00132 
00133 // ?
00134 instr(0x4f,5);
00135    r=a;
00136 endinstr;
00137 
00138 // IN D,(C)
00139 instr(0x50,8);
00140    input(d);
00141 endinstr;
00142 
00143 // OUT (C),D
00144 instr(0x51,8);
00145    out(c,d);
00146 endinstr;
00147 
00148 // SBC HL,DE
00149 instr(0x52,11);
00150    sbchl(de);
00151 endinstr;
00152 
00153 // LD (nn),DE
00154 instr(0x53,16);
00155    {unsigned short addr=fetch2(pc);
00156     pc+=2;
00157     store2b(addr,d,e);
00158    }
00159 endinstr;
00160 
00161 // ?
00162 instr(0x54,4);
00163    neg;
00164 endinstr;
00165 
00166 // my opcode for replacing the MOS routines
00167 instr(0x55,4);
00168    // printf("@ %04x Illegal opcode ED55 (MOS) \n\r",pc);
00169    do_mos(); // 
00170    ret;
00171 endinstr;
00172 
00173 // IM 1
00174 instr(0x56,4);
00175    im=1;
00176 endinstr;
00177 
00178 // LD A,I
00179 instr(0x57,5);
00180    a=i;
00181    f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
00182 endinstr;
00183 
00184 // IN E,(C)
00185 instr(0x58,8);
00186    input(e);
00187 endinstr;
00188 
00189 // OUT (C),E
00190 instr(0x59,8);
00191    out(c,e);
00192 endinstr;
00193 
00194 // ADC HL,DE
00195 instr(0x5a,11);
00196    adchl(de);
00197 endinstr;
00198 
00199 // LD DE,(nn)
00200 instr(0x5b,16);
00201    {unsigned short addr=fetch2(pc);
00202     pc+=2;
00203     e=fetch(addr);
00204     d=fetch(addr+1);
00205    }
00206 endinstr;
00207 
00208 // ?
00209 instr(0x5c,4);
00210    neg;
00211 endinstr;
00212 
00213 // ?
00214 instr(0x5d,4);
00215    ret;
00216 endinstr;
00217 
00218 // IM 2
00219 instr(0x5e,4);
00220    im=2;
00221 endinstr;
00222 
00223 // LDA A,R (unecessary on static memory)
00224 instr(0x5f,5);
00225    a=r;
00226    f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
00227 endinstr;
00228 
00229 // IN H,(C)
00230 instr(0x60,8);
00231    input(h);
00232 endinstr;
00233 
00234 // OUT (C),H
00235 instr(0x61,8);
00236    out(c,h);
00237 endinstr;
00238 
00239 // SBC HL,HL
00240 instr(0x62,11);
00241    sbchl(hl);
00242 endinstr;
00243 
00244 // ?
00245 instr(0x63,16);
00246    {unsigned short addr=fetch2(pc);
00247     pc+=2;
00248     store2b(addr,h,l);
00249    }
00250 endinstr;
00251 
00252 // ?
00253 instr(0x64,4);
00254    neg;
00255 endinstr;
00256 
00257 // ? illegal instruction ED65
00258 instr(0x65,4);
00259    ret;
00260 endinstr;
00261 
00262 // ?
00263 instr(0x66,4);
00264    ret; 
00265    //  was im=0;
00266 endinstr;
00267 
00268 // RRD
00269 instr(0x67,14);
00270    {unsigned char t=fetch(hl);
00271     unsigned char u=(a<<4)|(t>>4);
00272     a=(a&0xf0)|(t&0x0f);
00273     store(hl,u);
00274     f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
00275    }
00276 endinstr;
00277 
00278 // IN L,(C)
00279 instr(0x68,8);
00280    input(l);
00281 endinstr;
00282 
00283 // OUT (C),L
00284 instr(0x69,8);
00285    out(c,l);
00286 endinstr;
00287 
00288 // ADC HL,HL
00289 instr(0x6a,11);
00290    adchl(hl);
00291 endinstr;
00292 
00293 // ?
00294 instr(0x6b,16);
00295    {unsigned short addr=fetch2(pc);
00296     pc+=2;
00297     l=fetch(addr);
00298     h=fetch(addr+1);
00299    }
00300 endinstr;
00301 
00302 // ?
00303 instr(0x6c,4);
00304    neg;
00305 endinstr;
00306 
00307 // ?
00308 instr(0x6d,4);
00309    ret;
00310 endinstr;
00311 
00312 // ?
00313 instr(0x6e,4);
00314    // im=1;
00315    ret;
00316 endinstr;
00317 
00318 // RLD
00319 instr(0x6f,5);
00320    {unsigned char t=fetch(hl);
00321     unsigned char u=(a&0x0f)|(t<<4);
00322     a=(a&0xf0)|(t>>4);
00323     store(hl,u);
00324     f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
00325    }
00326 endinstr;
00327 
00328 // ?
00329 instr(0x70,8);
00330    {unsigned char x;input(x);}
00331 endinstr;
00332 
00333 // ?
00334 instr(0x71,8);
00335    out(c,0);
00336 endinstr;
00337 
00338 // SBC HL,SP
00339 instr(0x72,11);
00340    sbchl(sp);
00341 endinstr;
00342 
00343 // LD (nn),SP
00344 instr(0x73,16);
00345    {unsigned short addr=fetch2(pc);
00346     pc+=2;
00347     store2(addr,sp);
00348    }
00349 endinstr;
00350 
00351 // ?
00352 instr(0x74,4);
00353    neg;
00354 endinstr;
00355 
00356 // ?
00357 instr(0x75,4);
00358    ret;
00359 endinstr;
00360 
00361 // ?
00362 instr(0x76,4);
00363    im=2;
00364 endinstr;
00365 
00366 // IN A,(C)
00367 instr(0x78,8);
00368    input(a);
00369 endinstr;
00370 
00371 // OUT (C),A
00372 instr(0x79,8);
00373    out(c,a);
00374 endinstr;
00375 
00376 // ADC HL,SP
00377 instr(0x7a,11);
00378    adchl(sp);
00379 endinstr;
00380 
00381 // LD SP,(nn)
00382 instr(0x7b,16);
00383    {unsigned short addr=fetch2(pc);
00384     pc+=2;
00385     sp=fetch2(addr);
00386    }
00387 endinstr;
00388 
00389 // ?
00390 instr(0x7c,4);
00391    neg;
00392 endinstr;
00393 
00394 // ?
00395 instr(0x7d,4);
00396    ret;
00397 endinstr;
00398 
00399 // ?
00400 instr(0x7e,4);
00401    im=3;
00402 endinstr;
00403 
00404 // LDI
00405 instr(0xa0,12);
00406    {unsigned char x=fetch(hl);
00407     store(de,x);
00408     if(!++l)h++;
00409     if(!++e)d++;
00410     if(!c--)b--;
00411     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
00412    }
00413 endinstr;
00414 
00415 // CPI
00416 instr(0xa1,12);
00417    {unsigned char carry=cy;
00418     cpa(fetch(hl));
00419     if(!++l)h++;
00420     if(!c--)b--;
00421     f=(f&0xfa)|carry|(((b|c)>0)<<2);
00422    }
00423 endinstr;
00424 
00425 // INI
00426 instr(0xa2,12);
00427    {unsigned char t=in(c);
00428     store(hl,t);
00429     if(!++l)h++;
00430     b--;
00431     f=(b&0xa8)|((!b)<<6)|2|((parity(b)^c)&4);
00432     }
00433 endinstr;
00434 
00435 // OUTI
00436 instr(0xa3,12); /* I can't determine the correct flags outcome for the
00437                    block OUT instructions.  Spec says that the carry
00438                    flag is left unchanged and N is set to 1, but that
00439                    doesn't seem to be the case... */
00440    {unsigned char x=fetch(hl);
00441    // printf("OUTI %02x %02x\n\r",c,x);
00442     out(c,x);
00443     if(!++l)h++;
00444     b--;
00445     f=(f&1)|0x12|(b&0xa8)|((!b)<<6);
00446    // f=(f & 0xBF)|2|((b==0)<<6);
00447    
00448    }
00449 endinstr;
00450 
00451 // LDD
00452 instr(0xa8,12);
00453    {unsigned char x=fetch(hl);
00454     store(de,x);
00455     if(!l--)h--;
00456     if(!e--)d--;
00457     if(!c--)b--;
00458     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
00459    }
00460 endinstr;
00461 
00462 // CPD
00463 instr(0xa9,12);
00464    {unsigned char carry=cy;
00465     cpa(fetch(hl));
00466     if(!l--)h--;
00467     if(!c--)b--;
00468     f=(f&0xfa)|carry|(((b|c)>0)<<2);
00469    }
00470 endinstr;
00471 
00472 // IND
00473 instr(0xaa,12);
00474    {unsigned char t=in(c);
00475     store(hl,t);
00476     if(!l--)h--;
00477     b--;
00478 //    f=(f & 0xBF)|2|((!b)<<6);
00479 
00480     f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4);
00481    }
00482 endinstr;
00483 
00484 // OUTD
00485 instr(0xab,12);
00486    {unsigned char x=fetch(hl);
00487     out(c,x);
00488     if(!l--)h--;
00489     b--;
00490     f=(f&1)|0x12|(b&0xa8)|((!b)<<6);
00491    }
00492 endinstr;
00493 
00494 /* Note: the Z80 implements "*R" as "*" followed by JR -2.  No reason
00495    to change this... */
00496 
00497 // LDIR
00498 instr(0xb0,12);
00499    {unsigned char x=fetch(hl);
00500     store(de,x);
00501     if(!++l)h++;
00502     if(!++e)d++;
00503     if(!c--)b--;
00504     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
00505     if(b|c)pc-=2;
00506    }
00507 endinstr;
00508 
00509 // CPIR
00510 instr(0xb1,12);
00511    {unsigned char carry=cy;
00512     cpa(fetch(hl));
00513     if(!++l)h++;
00514     if(!c--)b--;
00515     f=(f&0xfa)|carry|(((b|c)>0)<<2);
00516     if((f&0x44)==4)pc-=2;
00517    }
00518 endinstr;
00519 
00520 // INIR
00521 instr(0xb2,12);
00522    {unsigned char t=in(c);
00523     store(hl,t);
00524     if(!++l)h++;
00525     b--;
00526     f=(b&0xa8)|((!b)<<6)|2|((parity(b)^c)&4);
00527    // f=(f & 0xBF)|2|((!b)<<6);
00528     if(b)pc-=2;
00529    }
00530 endinstr;
00531 
00532 // OTIR
00533 instr(0xb3,12);
00534    {unsigned char x=fetch(hl);
00535     out(c,x);
00536     if(!++l)h++;
00537     b--;
00538     f=(f&1)|0x12|(b&0xa8)|((!b)<<6);
00539     if(b)pc-=2;
00540    }
00541 endinstr;
00542 
00543 // LDDR
00544 instr(0xb8,12);
00545    {unsigned char x=fetch(hl);
00546     store(de,x);
00547     if(!l--)h--;
00548     if(!e--)d--;
00549     if(!c--)b--;
00550     f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
00551     if(b|c)pc-=2;
00552    }
00553 endinstr;
00554 
00555 // CPDR
00556 instr(0xb9,12);
00557    {unsigned char carry=cy;
00558     cpa(fetch(hl));
00559     if(!l--)h--;
00560     if(!c--)b--;
00561     f=(f&0xfa)|carry|(((b|c)>0)<<2);
00562     if((f&0x44)==4)pc-=2;
00563    }
00564 endinstr;
00565 
00566 // INDR
00567 instr(0xba,12);
00568    {unsigned char t=in(c);
00569     store(hl,t);
00570     if(!l--)h--;
00571     b--;
00572   f=(b&0xa8)|((!b)<<6)|2|((parity(b)^c^4)&4);
00573   // f=(f & 0xBF)|2|((!b)<<6);
00574 
00575     if(b)pc-=2;
00576    }
00577 endinstr;
00578 
00579 // OTDR
00580 instr(0xbb,12);
00581    {unsigned char x=fetch(hl);
00582     out(c,x);
00583     if(!l--)h--;
00584     b--;
00585     f=(f&1)|0x12|(b&0xa8)|((!b)<<6);
00586     if(b)pc-=2;
00587    }
00588 endinstr;
00589 
00590 }}