z80if.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2007-2010
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include <stddef.h>
  9. #include "pico_int.h"
  10. #include "memory.h"
  11. uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT];
  12. uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT];
  13. #ifdef _USE_DRZ80
  14. struct DrZ80 drZ80;
  15. static u32 drz80_sp_base;
  16. static void drz80_load_pcsp(u32 pc, u32 sp)
  17. {
  18. drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT];
  19. if (drZ80.Z80PC_BASE & (1<<31)) {
  20. elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad PC: %04x", pc);
  21. drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0];
  22. } else {
  23. drZ80.Z80PC_BASE <<= 1;
  24. drZ80.Z80PC = drZ80.Z80PC_BASE + pc;
  25. }
  26. drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT];
  27. if (drZ80.Z80SP_BASE & (1<<31)) {
  28. elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad SP: %04x", sp);
  29. drZ80.Z80SP_BASE = z80_read_map[0];
  30. drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT);
  31. } else {
  32. drZ80.Z80SP_BASE <<= 1;
  33. drZ80.Z80SP = drZ80.Z80SP_BASE + sp;
  34. }
  35. }
  36. // called only if internal xmap rebase fails
  37. static unsigned int dz80_rebase_pc(unsigned short pc)
  38. {
  39. elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_pc: fail on %04x", pc);
  40. drZ80.Z80PC_BASE = z80_read_map[0] << 1;
  41. return drZ80.Z80PC_BASE;
  42. }
  43. static unsigned int dz80_rebase_sp(unsigned short sp)
  44. {
  45. elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_sp: fail on %04x", sp);
  46. drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
  47. return drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT) - 0x100;
  48. }
  49. #endif
  50. void z80_init(void)
  51. {
  52. #ifdef _USE_DRZ80
  53. memset(&drZ80, 0, sizeof(drZ80));
  54. drZ80.z80_rebasePC = dz80_rebase_pc;
  55. drZ80.z80_rebaseSP = dz80_rebase_sp;
  56. drZ80.z80_read8 = (void *)z80_read_map;
  57. drZ80.z80_read16 = NULL;
  58. drZ80.z80_write8 = (void *)z80_write_map;
  59. drZ80.z80_write16 = NULL;
  60. drZ80.z80_irq_callback = NULL;
  61. #endif
  62. #ifdef _USE_CZ80
  63. memset(&CZ80, 0, sizeof(CZ80));
  64. Cz80_Init(&CZ80);
  65. Cz80_Set_ReadB(&CZ80, NULL); // unused (hacked in)
  66. Cz80_Set_WriteB(&CZ80, NULL);
  67. #endif
  68. }
  69. void z80_reset(void)
  70. {
  71. #ifdef _USE_DRZ80
  72. drZ80.Z80I = 0;
  73. drZ80.Z80IM = 0;
  74. drZ80.Z80IF = 0;
  75. drZ80.z80irqvector = 0xff0000; // RST 38h
  76. drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1;
  77. // others not changed, undefined on cold boot
  78. /*
  79. drZ80.Z80F = (1<<2); // set ZFlag
  80. drZ80.Z80F2 = (1<<2); // set ZFlag
  81. drZ80.Z80IX = 0xFFFF << 16;
  82. drZ80.Z80IY = 0xFFFF << 16;
  83. */
  84. // drZ80 is locked in single bank
  85. drz80_sp_base = (PicoAHW & PAHW_SMS) ? 0xc000 : 0x0000;
  86. drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
  87. if (PicoAHW & PAHW_SMS)
  88. drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS
  89. // XXX: since we use direct SP pointer, it might make sense to force it to RAM,
  90. // but we'll rely on built-in stack protection for now
  91. #endif
  92. #ifdef _USE_CZ80
  93. Cz80_Reset(&CZ80);
  94. if (PicoAHW & PAHW_SMS)
  95. Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0);
  96. #endif
  97. }
  98. /* save state stuff */
  99. static int z80_unpack_legacy(const void *data)
  100. {
  101. #if defined(_USE_DRZ80)
  102. if (*(int *)data == 0x015A7244) { // "DrZ" v1 save?
  103. u32 pc, sp;
  104. memcpy(&drZ80, data+4, 0x54);
  105. pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff;
  106. sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff;
  107. // update bases
  108. drz80_load_pcsp(pc, sp);
  109. return 0;
  110. }
  111. #elif defined(_USE_CZ80)
  112. if (*(int *)data == 0x00007a43) { // "Cz" save?
  113. memcpy(&CZ80, data+8, offsetof(cz80_struc, BasePC));
  114. Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4));
  115. return 0;
  116. }
  117. #endif
  118. return -1;
  119. }
  120. struct z80sr_main {
  121. u8 a, f;
  122. u8 b, c;
  123. u8 d, e;
  124. u8 h, l;
  125. };
  126. struct z80_state {
  127. char magic[4];
  128. // regs
  129. struct z80sr_main m; // main regs
  130. struct z80sr_main a; // alt (') regs
  131. u8 i, r;
  132. u16 ix, iy;
  133. u16 sp;
  134. u16 pc;
  135. // other
  136. u8 halted;
  137. u8 iff1, iff2;
  138. u8 im; // irq mode
  139. u8 irq_pending; // irq line level, 1 if active
  140. u8 irq_vector[3]; // up to 3 byte vector for irq mode0 handling
  141. u8 reserved[8];
  142. };
  143. void z80_pack(void *data)
  144. {
  145. struct z80_state *s = data;
  146. memset(data, 0, Z80_STATE_SIZE);
  147. strcpy(s->magic, "Z80");
  148. #if defined(_USE_DRZ80)
  149. #define DRR8(n) (drZ80.Z80##n >> 24)
  150. #define DRR16(n) (drZ80.Z80##n >> 16)
  151. #define DRR16H(n) (drZ80.Z80##n >> 24)
  152. #define DRR16L(n) ((drZ80.Z80##n >> 16) & 0xff)
  153. s->m.a = DRR8(A); s->m.f = DRR8(F);
  154. s->m.b = DRR16H(BC); s->m.c = DRR16L(BC);
  155. s->m.d = DRR16H(DE); s->m.e = DRR16L(DE);
  156. s->m.h = DRR16H(HL); s->m.l = DRR16L(HL);
  157. s->a.a = DRR8(A2); s->a.f = DRR8(F2);
  158. s->a.b = DRR16H(BC2); s->a.c = DRR16L(BC2);
  159. s->a.d = DRR16H(DE2); s->a.e = DRR16L(DE2);
  160. s->a.h = DRR16H(HL2); s->a.l = DRR16L(HL2);
  161. s->i = DRR8(I); s->r = drZ80.spare;
  162. s->ix = DRR16(IX); s->iy = DRR16(IY);
  163. s->sp = drZ80.Z80SP - drZ80.Z80SP_BASE;
  164. s->pc = drZ80.Z80PC - drZ80.Z80PC_BASE;
  165. s->halted = !!(drZ80.Z80IF & 4);
  166. s->iff1 = !!(drZ80.Z80IF & 1);
  167. s->iff2 = !!(drZ80.Z80IF & 2);
  168. s->im = drZ80.Z80IM;
  169. s->irq_pending = !!drZ80.Z80_IRQ;
  170. s->irq_vector[0] = drZ80.z80irqvector >> 16;
  171. s->irq_vector[1] = drZ80.z80irqvector >> 8;
  172. s->irq_vector[2] = drZ80.z80irqvector;
  173. #elif defined(_USE_CZ80)
  174. {
  175. const cz80_struc *CPU = &CZ80;
  176. s->m.a = zA; s->m.f = zF;
  177. s->m.b = zB; s->m.c = zC;
  178. s->m.d = zD; s->m.e = zE;
  179. s->m.h = zH; s->m.l = zL;
  180. s->a.a = zA2; s->a.f = zF2;
  181. s->a.b = CZ80.BC2.B.H; s->a.c = CZ80.BC2.B.L;
  182. s->a.d = CZ80.DE2.B.H; s->a.e = CZ80.DE2.B.L;
  183. s->a.h = CZ80.HL2.B.H; s->a.l = CZ80.HL2.B.L;
  184. s->i = zI; s->r = zR;
  185. s->ix = zIX; s->iy = zIY;
  186. s->sp = Cz80_Get_Reg(&CZ80, CZ80_SP);
  187. s->pc = Cz80_Get_Reg(&CZ80, CZ80_PC);
  188. s->halted = !!Cz80_Get_Reg(&CZ80, CZ80_HALT);
  189. s->iff1 = !!zIFF1;
  190. s->iff2 = !!zIFF2;
  191. s->im = zIM;
  192. s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE);
  193. s->irq_vector[0] = 0xff;
  194. }
  195. #endif
  196. }
  197. int z80_unpack(const void *data)
  198. {
  199. const struct z80_state *s = data;
  200. if (strcmp(s->magic, "Z80") != 0) {
  201. if (z80_unpack_legacy(data) != 0)
  202. goto fail;
  203. elprintf(EL_STATUS, "legacy z80 state");
  204. return 0;
  205. }
  206. #if defined(_USE_DRZ80)
  207. #define DRW8(n, v) drZ80.Z80##n = (u32)(v) << 24
  208. #define DRW16(n, v) drZ80.Z80##n = (u32)(v) << 16
  209. #define DRW16HL(n, h, l) drZ80.Z80##n = ((u32)(h) << 24) | ((u32)(l) << 16)
  210. DRW8(A, s->m.a); DRW8(F, s->m.f);
  211. DRW16HL(BC, s->m.b, s->m.c);
  212. DRW16HL(DE, s->m.d, s->m.e);
  213. DRW16HL(HL, s->m.h, s->m.l);
  214. DRW8(A2, s->a.a); DRW8(F2, s->a.f);
  215. DRW16HL(BC2, s->a.b, s->a.c);
  216. DRW16HL(DE2, s->a.d, s->a.e);
  217. DRW16HL(HL2, s->a.h, s->a.l);
  218. DRW8(I, s->i); drZ80.spare = s->r;
  219. DRW16(IX, s->ix); DRW16(IY, s->iy);
  220. drz80_load_pcsp(s->pc, s->sp);
  221. drZ80.Z80IF = 0;
  222. if (s->halted) drZ80.Z80IF |= 4;
  223. if (s->iff1) drZ80.Z80IF |= 1;
  224. if (s->iff2) drZ80.Z80IF |= 2;
  225. drZ80.Z80IM = s->im;
  226. drZ80.Z80_IRQ = s->irq_pending;
  227. drZ80.z80irqvector = ((u32)s->irq_vector[0] << 16) |
  228. ((u32)s->irq_vector[1] << 8) | s->irq_vector[2];
  229. return 0;
  230. #elif defined(_USE_CZ80)
  231. {
  232. cz80_struc *CPU = &CZ80;
  233. zA = s->m.a; zF = s->m.f;
  234. zB = s->m.b; zC = s->m.c;
  235. zD = s->m.d; zE = s->m.e;
  236. zH = s->m.h; zL = s->m.l;
  237. zA2 = s->a.a; zF2 = s->a.f;
  238. CZ80.BC2.B.H = s->a.b; CZ80.BC2.B.L = s->a.c;
  239. CZ80.DE2.B.H = s->a.d; CZ80.DE2.B.L = s->a.e;
  240. CZ80.HL2.B.H = s->a.h; CZ80.HL2.B.L = s->a.l;
  241. zI = s->i; zR = s->r;
  242. zIX = s->ix; zIY = s->iy;
  243. Cz80_Set_Reg(&CZ80, CZ80_SP, s->sp);
  244. Cz80_Set_Reg(&CZ80, CZ80_PC, s->pc);
  245. Cz80_Set_Reg(&CZ80, CZ80_HALT, s->halted);
  246. Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1);
  247. Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2);
  248. zIM = s->im;
  249. Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE);
  250. return 0;
  251. }
  252. #endif
  253. fail:
  254. elprintf(EL_STATUS|EL_ANOMALY, "z80_unpack failed");
  255. z80_reset();
  256. z80_int();
  257. return -1;
  258. }
  259. void z80_exit(void)
  260. {
  261. }
  262. void z80_debug(char *dstr)
  263. {
  264. #if defined(_USE_DRZ80)
  265. sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE);
  266. #elif defined(_USE_CZ80)
  267. sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", (unsigned int)(CZ80.PC - CZ80.BasePC), CZ80.SP.W);
  268. #endif
  269. }