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.
z80/z80.h@0:806c2f2a7d47, 2011-06-29 (annotated)
- Committer:
- gertk
- Date:
- Wed Jun 29 14:25:56 2011 +0000
- Revision:
- 0:806c2f2a7d47
preliminary version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gertk | 0:806c2f2a7d47 | 1 | /* z81/xz81, Linux console and X ZX81/ZX80 emulators. |
gertk | 0:806c2f2a7d47 | 2 | * Copyright (C) 1994 Ian Collier. z81 changes (C) 1995-2001 Russell Marks. |
gertk | 0:806c2f2a7d47 | 3 | * |
gertk | 0:806c2f2a7d47 | 4 | * This program is free software; you can redistribute it and/or modify |
gertk | 0:806c2f2a7d47 | 5 | * it under the terms of the GNU General Public License as published by |
gertk | 0:806c2f2a7d47 | 6 | * the Free Software Foundation; either version 2 of the License, or |
gertk | 0:806c2f2a7d47 | 7 | * (at your option) any later version. |
gertk | 0:806c2f2a7d47 | 8 | * |
gertk | 0:806c2f2a7d47 | 9 | * This program is distributed in the hope that it will be useful, |
gertk | 0:806c2f2a7d47 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
gertk | 0:806c2f2a7d47 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
gertk | 0:806c2f2a7d47 | 12 | * GNU General Public License for more details. |
gertk | 0:806c2f2a7d47 | 13 | * |
gertk | 0:806c2f2a7d47 | 14 | * You should have received a copy of the GNU General Public License |
gertk | 0:806c2f2a7d47 | 15 | * along with this program; if not, write to the Free Software |
gertk | 0:806c2f2a7d47 | 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
gertk | 0:806c2f2a7d47 | 17 | */ |
gertk | 0:806c2f2a7d47 | 18 | |
gertk | 0:806c2f2a7d47 | 19 | // I have made all Z80 registers global and volatile |
gertk | 0:806c2f2a7d47 | 20 | volatile bool iff1, iff2; |
gertk | 0:806c2f2a7d47 | 21 | unsigned char im; |
gertk | 0:806c2f2a7d47 | 22 | volatile unsigned char a, f, b, c, d, e, h, l; |
gertk | 0:806c2f2a7d47 | 23 | volatile unsigned char r, a1, f1, b1, c1, d1, e1, h1, l1, i; |
gertk | 0:806c2f2a7d47 | 24 | volatile unsigned short pc; |
gertk | 0:806c2f2a7d47 | 25 | volatile unsigned short ix, iy, sp; |
gertk | 0:806c2f2a7d47 | 26 | |
gertk | 0:806c2f2a7d47 | 27 | // some flags |
gertk | 0:806c2f2a7d47 | 28 | volatile bool intpend=0; |
gertk | 0:806c2f2a7d47 | 29 | volatile unsigned char new_ixoriy=0; |
gertk | 0:806c2f2a7d47 | 30 | volatile unsigned char ixoriy=0; |
gertk | 0:806c2f2a7d47 | 31 | |
gertk | 0:806c2f2a7d47 | 32 | |
gertk | 0:806c2f2a7d47 | 33 | #define Z80_quit 1 |
gertk | 0:806c2f2a7d47 | 34 | #define Z80_NMI 2 |
gertk | 0:806c2f2a7d47 | 35 | #define Z80_reset 3 |
gertk | 0:806c2f2a7d47 | 36 | #define Z80_load 4 |
gertk | 0:806c2f2a7d47 | 37 | #define Z80_save 5 |
gertk | 0:806c2f2a7d47 | 38 | #define Z80_log 6 |
gertk | 0:806c2f2a7d47 | 39 | |
gertk | 0:806c2f2a7d47 | 40 | #define parity(a) (partable[a]) |
gertk | 0:806c2f2a7d47 | 41 | unsigned char partable[256]={ |
gertk | 0:806c2f2a7d47 | 42 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 43 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 44 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 45 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 46 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 47 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 48 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 49 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 50 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 51 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 52 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 53 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 54 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, |
gertk | 0:806c2f2a7d47 | 55 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 56 | 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, |
gertk | 0:806c2f2a7d47 | 57 | 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4 |
gertk | 0:806c2f2a7d47 | 58 | }; |
gertk | 0:806c2f2a7d47 | 59 | |
gertk | 0:806c2f2a7d47 | 60 | |
gertk | 0:806c2f2a7d47 | 61 | #define fetch(x) (rdmem(x)) |
gertk | 0:806c2f2a7d47 | 62 | #define fetch2(x) ((fetch((x)+1)<<8)|fetch(x)) |
gertk | 0:806c2f2a7d47 | 63 | |
gertk | 0:806c2f2a7d47 | 64 | // store 8 bit value y at 16 bit location x |
gertk | 0:806c2f2a7d47 | 65 | #define store(x,y) (wrmem(x,(y))) |
gertk | 0:806c2f2a7d47 | 66 | |
gertk | 0:806c2f2a7d47 | 67 | #define store2b(x,hi,lo) do {wrmem(x,lo);wrmem(x+1,hi);}while(0) |
gertk | 0:806c2f2a7d47 | 68 | |
gertk | 0:806c2f2a7d47 | 69 | #define store2(x,y) store2b(x,(y)>>8,(y)&255) |
gertk | 0:806c2f2a7d47 | 70 | |
gertk | 0:806c2f2a7d47 | 71 | #define bc ((b<<8)|c) |
gertk | 0:806c2f2a7d47 | 72 | #define de ((d<<8)|e) |
gertk | 0:806c2f2a7d47 | 73 | #define hl ((h<<8)|l) |
gertk | 0:806c2f2a7d47 | 74 | |
gertk | 0:806c2f2a7d47 | 75 | #define instr(opcode,cycles) case opcode: { |
gertk | 0:806c2f2a7d47 | 76 | #define HLinstr(opcode) \ |
gertk | 0:806c2f2a7d47 | 77 | case opcode: {unsigned short addr; \ |
gertk | 0:806c2f2a7d47 | 78 | if(ixoriy==0)addr=hl; \ |
gertk | 0:806c2f2a7d47 | 79 | else addr=(ixoriy==1?ix:iy)+ \ |
gertk | 0:806c2f2a7d47 | 80 | (signed char)fetch(pc),\ |
gertk | 0:806c2f2a7d47 | 81 | pc++ |
gertk | 0:806c2f2a7d47 | 82 | #define endinstr }; break |
gertk | 0:806c2f2a7d47 | 83 | |
gertk | 0:806c2f2a7d47 | 84 | #define cy (f&1) |
gertk | 0:806c2f2a7d47 | 85 | |
gertk | 0:806c2f2a7d47 | 86 | #define xh (ixoriy==0?h:ixoriy==1?(ix>>8):(iy>>8)) |
gertk | 0:806c2f2a7d47 | 87 | #define xl (ixoriy==0?l:ixoriy==1?(ix&0xff):(iy&0xff)) |
gertk | 0:806c2f2a7d47 | 88 | |
gertk | 0:806c2f2a7d47 | 89 | #define setxh(x) (ixoriy==0?(h=(x)):ixoriy==1?(ix=(ix&0xff)|((x)<<8)):\ |
gertk | 0:806c2f2a7d47 | 90 | (iy=(iy&0xff)|((x)<<8))) |
gertk | 0:806c2f2a7d47 | 91 | #define setxl(x) (ixoriy==0?(l=(x)):ixoriy==1?(ix=(ix&0xff00)|(x)):\ |
gertk | 0:806c2f2a7d47 | 92 | (iy=(iy&0xff00)|(x))) |
gertk | 0:806c2f2a7d47 | 93 | |
gertk | 0:806c2f2a7d47 | 94 | #define inc(var) /* 8-bit increment */ ( var++,\ |
gertk | 0:806c2f2a7d47 | 95 | f=(f&1)|(var&0xa8)|\ |
gertk | 0:806c2f2a7d47 | 96 | ((!(var&15))<<4)|((!var)<<6)|\ |
gertk | 0:806c2f2a7d47 | 97 | ((var==128)<<2)\ |
gertk | 0:806c2f2a7d47 | 98 | ) |
gertk | 0:806c2f2a7d47 | 99 | #define dec(var) /* 8-bit decrement */ ( f=(f&1)|((!(var&15))<<4)|2,\ |
gertk | 0:806c2f2a7d47 | 100 | --var,\ |
gertk | 0:806c2f2a7d47 | 101 | f|=(var&0xa8)|((var==127)<<2)|\ |
gertk | 0:806c2f2a7d47 | 102 | ((!var)<<6)\ |
gertk | 0:806c2f2a7d47 | 103 | ) |
gertk | 0:806c2f2a7d47 | 104 | #define swap(x,y) {unsigned char t=x; x=y; y=t;} |
gertk | 0:806c2f2a7d47 | 105 | #define addhl(hi,lo) /* 16-bit add */ if(!ixoriy){\ |
gertk | 0:806c2f2a7d47 | 106 | unsigned short t;\ |
gertk | 0:806c2f2a7d47 | 107 | l=t=l+(lo);\ |
gertk | 0:806c2f2a7d47 | 108 | f=(f&0xc4)|(((t>>=8)+(h&0x0f)+((hi)&0x0f)>15)<<4);\ |
gertk | 0:806c2f2a7d47 | 109 | h=t+=h+(hi);\ |
gertk | 0:806c2f2a7d47 | 110 | f|=(h&0x28)|(t>>8);\ |
gertk | 0:806c2f2a7d47 | 111 | }\ |
gertk | 0:806c2f2a7d47 | 112 | else do{unsigned long t=(ixoriy==1?ix:iy);\ |
gertk | 0:806c2f2a7d47 | 113 | f=(f&0xc4)|(((t&0xfff)+((hi<<8)|lo)>0xfff)<<4);\ |
gertk | 0:806c2f2a7d47 | 114 | t+=(hi<<8)|lo;\ |
gertk | 0:806c2f2a7d47 | 115 | if(ixoriy==1)ix=t; else iy=t;\ |
gertk | 0:806c2f2a7d47 | 116 | f|=((t>>8)&0x28)|(t>>16);\ |
gertk | 0:806c2f2a7d47 | 117 | } while(0) |
gertk | 0:806c2f2a7d47 | 118 | |
gertk | 0:806c2f2a7d47 | 119 | #define adda(x,c) /* 8-bit add */ do{unsigned short y;\ |
gertk | 0:806c2f2a7d47 | 120 | unsigned char z=(x);\ |
gertk | 0:806c2f2a7d47 | 121 | y=a+z+(c);\ |
gertk | 0:806c2f2a7d47 | 122 | f=(y&0xa8)|(y>>8)|(((a&0x0f)+(z&0x0f)+(c)>15)<<4)|\ |
gertk | 0:806c2f2a7d47 | 123 | (((~a^z)&0x80&(y^a))>>5);\ |
gertk | 0:806c2f2a7d47 | 124 | a=y; \ |
gertk | 0:806c2f2a7d47 | 125 | f|=(!a)<<6;\ |
gertk | 0:806c2f2a7d47 | 126 | } while(0) |
gertk | 0:806c2f2a7d47 | 127 | #define suba(x,c) /* 8-bit subtract */ do{unsigned short y;\ |
gertk | 0:806c2f2a7d47 | 128 | unsigned char z=(x);\ |
gertk | 0:806c2f2a7d47 | 129 | y=(a-z-(c))&0x1ff;\ |
gertk | 0:806c2f2a7d47 | 130 | f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f)+(c))<<4)|\ |
gertk | 0:806c2f2a7d47 | 131 | (((a^z)&0x80&(y^a))>>5)|2;\ |
gertk | 0:806c2f2a7d47 | 132 | a=y; \ |
gertk | 0:806c2f2a7d47 | 133 | f|=(!a)<<6;\ |
gertk | 0:806c2f2a7d47 | 134 | } while(0) |
gertk | 0:806c2f2a7d47 | 135 | #define cpa(x) /* 8-bit compare */ do{unsigned short y;\ |
gertk | 0:806c2f2a7d47 | 136 | unsigned char z=(x);\ |
gertk | 0:806c2f2a7d47 | 137 | y=(a-z)&0x1ff;\ |
gertk | 0:806c2f2a7d47 | 138 | f=(y&0xa8)|(y>>8)|(((a&0x0f)<(z&0x0f))<<4)|\ |
gertk | 0:806c2f2a7d47 | 139 | (((a^z)&0x80&(y^a))>>5)|2|((!y)<<6);\ |
gertk | 0:806c2f2a7d47 | 140 | } while(0) |
gertk | 0:806c2f2a7d47 | 141 | #define anda(x) /* logical and */ do{\ |
gertk | 0:806c2f2a7d47 | 142 | a&=(x);\ |
gertk | 0:806c2f2a7d47 | 143 | f=(a&0xa8)|((!a)<<6)|0x10|parity(a);\ |
gertk | 0:806c2f2a7d47 | 144 | } while(0) |
gertk | 0:806c2f2a7d47 | 145 | #define xora(x) /* logical xor */ do{\ |
gertk | 0:806c2f2a7d47 | 146 | a^=(x);\ |
gertk | 0:806c2f2a7d47 | 147 | f=(a&0xa8)|((!a)<<6)|parity(a);\ |
gertk | 0:806c2f2a7d47 | 148 | } while(0) |
gertk | 0:806c2f2a7d47 | 149 | #define ora(x) /* logical or */ do{\ |
gertk | 0:806c2f2a7d47 | 150 | a|=(x);\ |
gertk | 0:806c2f2a7d47 | 151 | f=(a&0xa8)|((!a)<<6)|parity(a);\ |
gertk | 0:806c2f2a7d47 | 152 | } while(0) |
gertk | 0:806c2f2a7d47 | 153 | |
gertk | 0:806c2f2a7d47 | 154 | #define jr /* execute relative jump */ do{int j=(signed char)fetch(pc);\ |
gertk | 0:806c2f2a7d47 | 155 | pc+=j+1;\ |
gertk | 0:806c2f2a7d47 | 156 | } while(0) |
gertk | 0:806c2f2a7d47 | 157 | #define jp /* execute jump */ (pc=fetch2(pc)) |
gertk | 0:806c2f2a7d47 | 158 | #define call /* execute call */ do{\ |
gertk | 0:806c2f2a7d47 | 159 | push2(pc+2);\ |
gertk | 0:806c2f2a7d47 | 160 | jp;\ |
gertk | 0:806c2f2a7d47 | 161 | } while(0) |
gertk | 0:806c2f2a7d47 | 162 | #define ret /* execute return */ do{\ |
gertk | 0:806c2f2a7d47 | 163 | pop2(pc);\ |
gertk | 0:806c2f2a7d47 | 164 | } while(0) |
gertk | 0:806c2f2a7d47 | 165 | #define pop2(var) /* pop 16-bit register */ (var=fetch2(sp),sp+=2) |
gertk | 0:806c2f2a7d47 | 166 | #define pop1(v1,v2) /* pop register pair */ (v2=fetch(sp),\ |
gertk | 0:806c2f2a7d47 | 167 | v1=fetch(sp+1),sp+=2) |
gertk | 0:806c2f2a7d47 | 168 | #define push2(val) /* push 16-bit register */ do{sp-=2;store2(sp,(val));}\ |
gertk | 0:806c2f2a7d47 | 169 | while(0) |
gertk | 0:806c2f2a7d47 | 170 | #define push1(v1,v2) /* push register pair */ do{sp-=2;\ |
gertk | 0:806c2f2a7d47 | 171 | store2b(sp,v1,v2);\ |
gertk | 0:806c2f2a7d47 | 172 | }while(0) |
gertk | 0:806c2f2a7d47 | 173 |