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.
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 }}
Generated on Wed Jul 13 2022 16:07:28 by 1.7.2