1 2 /* 3 4 z80opc.h 5 6 This file contains the full collection of 7 opcodes, which will be directly included 8 into z80.c. 9 10 */ 11 12 /* ----- Z80 macros ----- */ 13 /* these are the real gb-z80-opcodes */ 14 15 #ifndef Z80OPC_INCLUDED 16 #define Z80OPC_INCLUDED 17 18 /* 19 This might help to save memory on some machines. 20 */ 21 #ifndef Z80OPC_GAMEBOYC_SKIP 22 23 #define M_INCB(reg) { Z80_REG.B.F&=FLAG_C; \ 24 Z80_REG.B.F|=++reg == 0 ? FLAG_Z : 0; \ 25 Z80_REG.B.F|=(reg & 0x0F) == 0 ? FLAG_H :0; } 26 27 #define M_DECB(reg) { Z80_REG.B.F&=FLAG_C; \ 28 Z80_REG.B.F|=--reg == 0 ? FLAG_Z|FLAG_N : FLAG_N; \ 29 Z80_REG.B.F|=(reg & 0x0F) == 0x0F ? 0 : FLAG_H; } 30 31 #define M_RLCA { Z80_REG.B.F=(Z80_REG.B.A & 0x80) >> 3; \ 32 Z80_REG.B.A=(Z80_REG.B.A<<1)|(Z80_REG.B.A>>7); } 33 34 #define M_RRCA { Z80_REG.B.F=(Z80_REG.B.A & 0x01) << 4; \ 35 Z80_REG.B.A=(Z80_REG.B.A>>1)|(Z80_REG.B.A<<7); } 36 37 #define M_RLA { Z80_REG.B.F|=Z80_REG.B.A>>7; \ 38 Z80_REG.B.A<<=1; \ 39 Z80_REG.B.A|=(Z80_REG.B.F & FLAG_C)>>4; \ 40 Z80_REG.B.F=(Z80_REG.B.F & 0x01)<<4; } 41 42 #define M_RRA { Z80_REG.B.F|=Z80_REG.B.A & 0x01; \ 43 Z80_REG.B.A>>=1; \ 44 Z80_REG.B.A|=(Z80_REG.B.F & FLAG_C)<<3; \ 45 Z80_REG.B.F=(Z80_REG.B.F & 0x01)<<4; } 46 47 #define M_ADDHL(wreg) { Z80_REG.B.F&=FLAG_Z|FLAG_N|FLAG_H; \ 48 Z80_REG.B.F|=(((ulong)Z80_REG.W.HL+(ulong)wreg) \ 49 &0x10000)>>12; \ 50 Z80_REG.W.HL=Z80_REG.W.HL+wreg; } 51 52 #define M_JR { Z80_REG.W.PC+=1+(signed char)GetByteAt(Z80_REG.W.PC);\ 53 Z80_TICKS+=Z80CLKS_JR[DBLSPEED]; } 54 55 #define M_DAA { if ((Z80_REG.B.F & FLAG_N)==0) { \ 56 if (((Z80_REG.B.A & 0x0F)>9)|| \ 57 ((Z80_REG.B.F & FLAG_H)>0)) { \ 58 Z80_REG.B.A+=6; \ 59 Z80_REG.B.F|=(Z80_REG.B.A & 0xF0)==0 ? \ 60 FLAG_C|FLAG_H : FLAG_H; \ 61 } \ 62 if (((Z80_REG.B.A & 0xF0)>0x90)|| \ 63 ((Z80_REG.B.F & FLAG_C)>0)) { \ 64 Z80_REG.B.A+=0x60; \ 65 Z80_REG.B.F|=FLAG_C; \ 66 } \ 67 } else { \ 68 if (((Z80_REG.B.A & 0x0F)>9)|| \ 69 ((Z80_REG.B.F & FLAG_H)>0)) { \ 70 Z80_REG.B.A-=6; \ 71 Z80_REG.B.F|=(Z80_REG.B.A & 0xF0)==0xF0 ? \ 72 FLAG_C|FLAG_H : FLAG_H; \ 73 } \ 74 if (((Z80_REG.B.A & 0xF0)>0x90)|| \ 75 ((Z80_REG.B.F & FLAG_C)>0)) { \ 76 Z80_REG.B.A-=0x60; \ 77 Z80_REG.B.F|=FLAG_C; \ 78 } \ 79 } \ 80 Z80_REG.B.F= Z80_REG.B.A==0 ? Z80_REG.B.F | FLAG_Z : \ 81 Z80_REG.B.F & (0xFF-FLAG_Z); \ 82 } 83 84 #define M_ADD(reg) { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)+(reg & 0x0F)) \ 85 & 0x10) << 1)| \ 86 ((((uint)Z80_REG.B.A+ \ 87 (uint)reg)& 0x100) >> 4)| \ 88 ((Z80_REG.B.A=(Z80_REG.B.A+reg))==0 ? \ 89 FLAG_Z : 0); \ 90 } 91 92 #define M_ADC(reg) { DUMMY_F=(Z80_REG.B.F & FLAG_C)>0 ? 1 :0; \ 93 Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)+(reg & 0x0F) \ 94 +DUMMY_F) & 0x10) << 1)| \ 95 ((((uint)Z80_REG.B.A+ \ 96 (uint)reg+(uint)DUMMY_F)&0x100)>> 4)| \ 97 ((Z80_REG.B.A=(Z80_REG.B.A+reg+DUMMY_F)) \ 98 ==0 ? FLAG_Z : 0); \ 99 } 100 101 #define M_SUB(reg) { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F)) \ 102 & 0x10) << 1)| \ 103 ((((uint)Z80_REG.B.A- \ 104 (uint)reg)& 0x100) >> 4)| \ 105 ((Z80_REG.B.A=(Z80_REG.B.A-reg))==0 ? \ 106 FLAG_Z|FLAG_N : FLAG_N); } 107 108 #define M_SBC(reg) { DUMMY_F=(Z80_REG.B.F & FLAG_C)>0 ? 1 :0; \ 109 Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F) \ 110 -DUMMY_F) & 0x10) << 1)| \ 111 ((((uint)Z80_REG.B.A- \ 112 (uint)reg-(uint)DUMMY_F)&0x100)>> 4)| \ 113 ((Z80_REG.B.A=(Z80_REG.B.A-reg-DUMMY_F)) \ 114 ==0 ? FLAG_Z|FLAG_N : FLAG_N); } 115 116 #define M_AND(reg) { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A & reg))==0) ? \ 117 FLAG_H | FLAG_Z : FLAG_H; } 118 119 #define M_XOR(reg) { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A ^ reg))==0) ? \ 120 FLAG_Z : 0; } 121 122 #define M_OR(reg) { Z80_REG.B.F=((Z80_REG.B.A=(Z80_REG.B.A | reg))==0) ? \ 123 FLAG_Z : 0; } 124 125 #define M_CP(reg) { Z80_REG.B.F=((((Z80_REG.B.A & 0x0F)-(reg & 0x0F)) \ 126 & 0x10) << 1)| \ 127 ((((uint)Z80_REG.B.A- \ 128 (uint)reg)& 0x100) >> 4)| \ 129 (Z80_REG.B.A==reg ? \ 130 FLAG_Z|FLAG_N : FLAG_N); } 131 132 #define M_RET { Z80_REG.W.PC=GetWordAt(Z80_REG.W.SP); \ 133 Z80_REG.W.SP+=2; \ 134 Z80_TICKS+=Z80CLKS_RET[DBLSPEED]; } 135 136 #define M_POPW(wreg) { wreg=GetWordAt(Z80_REG.W.SP); \ 137 Z80_REG.W.SP+=2; } 138 139 #define M_JP { Z80_REG.W.PC=GetWordAt(Z80_REG.W.PC); \ 140 Z80_TICKS+=Z80CLKS_JP[DBLSPEED]; } 141 142 #define M_CALL { Z80_REG.W.SP-=2; \ 143 SetWordAt(Z80_REG.W.SP,Z80_REG.W.PC+2); \ 144 Z80_REG.W.PC=GetWordAt(Z80_REG.W.PC); \ 145 Z80_TICKS+=Z80CLKS_CALL[DBLSPEED]; } 146 147 #define M_PUSHW(wreg) { Z80_REG.W.SP-=2; \ 148 SetWordAt(Z80_REG.W.SP,wreg); } 149 150 #endif /* Z80OPC_GAMEBOYC_SKIP */ 151 152 #define M_RST(addr) { Z80_REG.W.SP-=2; \ 153 SetWordAt(Z80_REG.W.SP,Z80_REG.W.PC); \ 154 Z80_REG.W.PC=addr; } 155 156 #ifndef Z80OPC_GAMEBOYC_SKIP 157 158 #define M_ADDSPN { DUMMY_F=GetByteAt(Z80_REG.W.PC++); \ 159 if ((DUMMY_F & 0x80)==0) { \ 160 Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)+(DUMMY_F & 0x0F)) \ 161 & 0x10) << 1)| \ 162 ((((ulong)Z80_REG.W.SP+ \ 163 (ulong)DUMMY_F)& 0x10000) >> 12); \ 164 Z80_REG.W.SP=Z80_REG.W.SP+DUMMY_F; \ 165 } else { \ 166 Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)- \ 167 ((signed char)DUMMY_F & 0x0F)) \ 168 & 0x10) << 1)| \ 169 ((((ulong)Z80_REG.W.SP+ \ 170 (signed char)DUMMY_F) \ 171 & 0x10000) >> 12); \ 172 Z80_REG.W.SP=Z80_REG.W.SP+(signed char)DUMMY_F; \ 173 } \ 174 } 175 176 #define M_LDHLSPN { DUMMY_F=GetByteAt(Z80_REG.W.PC++); \ 177 if ((DUMMY_F & 0x80)==0) { \ 178 Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)+(DUMMY_F & 0x0F)) \ 179 & 0x10) << 1)| \ 180 ((((Z80_REG.W.SP & 0xFF)+ \ 181 (uint)DUMMY_F)& 0x100) >> 4); \ 182 Z80_REG.W.HL=Z80_REG.W.SP+DUMMY_F; \ 183 } else { \ 184 Z80_REG.B.F=((((Z80_REG.W.SP & 0x0F)- \ 185 ((signed char)DUMMY_F & 0x0F)) \ 186 & 0x10) << 1)| \ 187 ((((Z80_REG.W.SP & 0xFF)+ \ 188 (signed char)DUMMY_F) \ 189 & 0x100) >> 4); \ 190 Z80_REG.W.HL=Z80_REG.W.SP+(signed char)DUMMY_F; \ 191 } \ 192 } 193 194 195 /* ----- Z80 macros with CB prefix ----- 196 NOTE: RLCA != RLC A etc. !!! 197 DON'T USE DUMMY_F HERE !! */ 198 199 #define M_CBRLC(reg) { Z80_REG.B.F=(reg & 0x80) >> 3; \ 200 Z80_REG.B.F|=(reg=((reg << 1)|(reg >> 7)))==0 \ 201 ? FLAG_Z : 0; } 202 203 #define M_CBRRC(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \ 204 Z80_REG.B.F|=(reg=((reg >> 1)|(reg << 7)))==0 \ 205 ? FLAG_Z : 0; } 206 207 #define M_CBRL(reg) { Z80_REG.B.F|=reg >> 7; \ 208 reg<<=1;reg|=(Z80_REG.B.F & FLAG_C)>>4; \ 209 Z80_REG.B.F=(reg==0 ? FLAG_Z : 0)| \ 210 (Z80_REG.B.F & 0x01)<<4; } 211 212 #define M_CBRR(reg) { Z80_REG.B.F|=reg & 0x01; \ 213 reg>>=1;reg|=(Z80_REG.B.F & FLAG_C)<<3; \ 214 Z80_REG.B.F=(reg==0 ? FLAG_Z : 0)| \ 215 (Z80_REG.B.F & 0x01)<<4; } 216 217 #define M_CBSLA(reg) { Z80_REG.B.F=(reg & 0x80) >> 3; \ 218 Z80_REG.B.F|=(reg=(reg << 1))==0 \ 219 ? FLAG_Z : 0; } 220 221 #define M_CBSRA(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \ 222 Z80_REG.B.F|=(reg=((reg >> 1)|(reg & 0x80)))==0 \ 223 ? FLAG_Z : 0; } 224 225 #define M_CBSWAP(reg) { Z80_REG.B.F=(reg=((reg >> 4)|(reg << 4)))==0 ? \ 226 FLAG_Z : 0; \ 227 } 228 229 #define M_CBSRL(reg) { Z80_REG.B.F=(reg & 0x01) << 4; \ 230 Z80_REG.B.F|=(reg=(reg >> 1))==0 \ 231 ? FLAG_Z : 0; } 232 233 #define M_CBBIT(n,reg) { Z80_REG.B.F=(Z80_REG.B.F & FLAG_C) | FLAG_H | \ 234 ((reg >> n)&1 ? 0 : FLAG_Z); } 235 236 #define M_CBRES(n,reg) { reg&=(1 << n)^0xFF; } 237 #define M_CBSET(n,reg) { reg|=1 << n; } 238 239 #define M_EXECCB(cmd,reg) \ 240 { \ 241 switch (cmd) { \ 242 case 0x00:M_CBRLC(reg); break; \ 243 case 0x01:M_CBRRC(reg); break; \ 244 case 0x02:M_CBRL(reg); break; \ 245 case 0x03:M_CBRR(reg); break; \ 246 case 0x04:M_CBSLA(reg); break; \ 247 case 0x05:M_CBSRA(reg); break; \ 248 case 0x06:M_CBSWAP(reg);break; \ 249 case 0x07:M_CBSRL(reg); break; \ 250 case 0x08: \ 251 case 0x09: \ 252 case 0x0A: \ 253 case 0x0B: \ 254 case 0x0C: \ 255 case 0x0D: \ 256 case 0x0E: \ 257 case 0x0F: \ 258 M_CBBIT((cmd & 7),reg);break;\ 259 case 0x10: \ 260 case 0x11: \ 261 case 0x12: \ 262 case 0x13: \ 263 case 0x14: \ 264 case 0x15: \ 265 case 0x16: \ 266 case 0x17: \ 267 M_CBRES((cmd & 7),reg);break; \ 268 case 0x18: \ 269 case 0x19: \ 270 case 0x1A: \ 271 case 0x1B: \ 272 case 0x1C: \ 273 case 0x1D: \ 274 case 0x1E: \ 275 case 0x1F: \ 276 M_CBSET((cmd & 7),reg);break; \ 277 } \ 278 } 279 280 #define M_PREFIXCB(opc) \ 281 { \ 282 switch (opc & 0x07) { \ 283 case 0:M_EXECCB((opc >> 3),Z80_REG.B.B);break; \ 284 case 1:M_EXECCB((opc >> 3),Z80_REG.B.C);break; \ 285 case 2:M_EXECCB((opc >> 3),Z80_REG.B.D);break; \ 286 case 3:M_EXECCB((opc >> 3),Z80_REG.B.E);break; \ 287 case 4:M_EXECCB((opc >> 3),Z80_REG.B.H);break; \ 288 case 5:M_EXECCB((opc >> 3),Z80_REG.B.L);break; \ 289 case 6: \ 290 DUMMY_F=GetByteAt(Z80_REG.W.HL); \ 291 M_EXECCB((opc >> 3),DUMMY_F); \ 292 if ((opc>>6)!=1) \ 293 SetByteAt(Z80_REG.W.HL,DUMMY_F); \ 294 Z80_TICKS+=Z80CLKS_PREFIXCBINDHL[DBLSPEED]; \ 295 break; \ 296 case 7:M_EXECCB((opc >> 3),Z80_REG.B.A);break; \ 297 } \ 298 Z80_TICKS+=Z80CLKS_PREFIXCB[DBLSPEED]; \ 299 } 300 301 #endif /* Z80OPC_GAMEBOYC_SKIP */ 302 303 #endif /* Z80OPC_INCLUDED */ 304