Mercurial > repos > blastem
comparison z80inst.c @ 200:d3066ceb29d1
Add support for EXTD group 2-byte Z80 instructions in decoder
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 20 Jan 2013 21:32:13 -0800 |
parents | 69585e7d474f |
children | 2d2fa345e1fc |
comparison
equal
deleted
inserted
replaced
199:69585e7d474f | 200:d3066ceb29d1 |
---|---|
1 #include "z80inst.h" | 1 #include "z80inst.h" |
2 #include <string.h> | 2 #include <string.h> |
3 #include <stdio.h> | 3 #include <stdio.h> |
4 | 4 |
5 #define NOP {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0} | |
6 | |
5 z80inst z80_tbl_a[256] = { | 7 z80inst z80_tbl_a[256] = { |
6 //0 | 8 //0 |
7 {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | 9 NOP, |
8 {Z80_LD, Z80_BC, Z80_IMMED, Z80_UNUSED, 0}, | 10 {Z80_LD, Z80_BC, Z80_IMMED, Z80_UNUSED, 0}, |
9 {Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_BC, 0}, | 11 {Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_BC, 0}, |
10 {Z80_INC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, | 12 {Z80_INC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, |
11 {Z80_INC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, | 13 {Z80_INC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, |
12 {Z80_DEC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, | 14 {Z80_DEC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, |
275 {0, 0, 0, 0, 0},//IY Prefix | 277 {0, 0, 0, 0, 0},//IY Prefix |
276 {Z80_CP, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, | 278 {Z80_CP, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, |
277 {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x38} | 279 {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x38} |
278 }; | 280 }; |
279 | 281 |
282 z80inst z80_tbl_extd[0xC0-0x40] = { | |
283 //4 | |
284 {Z80_IN, Z80_B, Z80_REG_INDIRECT, Z80_C, 0}, | |
285 {Z80_OUT, Z80_B, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
286 {Z80_SBC, Z80_HL, Z80_REG, Z80_BC, 0}, | |
287 {Z80_LD, Z80_BC, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, | |
288 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
289 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
290 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, | |
291 {Z80_LD, Z80_I, Z80_REG, Z80_A, 0}, | |
292 {Z80_IN, Z80_C, Z80_REG_INDIRECT, Z80_C, 0}, | |
293 {Z80_OUT, Z80_C, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
294 {Z80_ADC, Z80_HL, Z80_REG, Z80_BC, 0}, | |
295 {Z80_LD, Z80_BC, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, | |
296 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
297 {Z80_RETI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
298 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 3},//Set undocumented mode 0/1 | |
299 {Z80_LD, Z80_R, Z80_REG, Z80_A, 0}, | |
300 //5 | |
301 {Z80_IN, Z80_D, Z80_REG_INDIRECT, Z80_C, 0}, | |
302 {Z80_OUT, Z80_D, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
303 {Z80_SBC, Z80_HL, Z80_REG, Z80_DE, 0}, | |
304 {Z80_LD, Z80_DE, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, | |
305 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
306 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
307 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 1}, | |
308 {Z80_LD, Z80_A, Z80_REG, Z80_I, 0}, | |
309 {Z80_IN, Z80_E, Z80_REG_INDIRECT, Z80_C, 0}, | |
310 {Z80_OUT, Z80_E, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
311 {Z80_ADC, Z80_HL, Z80_REG, Z80_DE, 0}, | |
312 {Z80_LD, Z80_DE, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, | |
313 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
314 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
315 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 2}, | |
316 {Z80_LD, Z80_A, Z80_REG, Z80_R, 0}, | |
317 //6 | |
318 {Z80_IN, Z80_H, Z80_REG_INDIRECT, Z80_C, 0}, | |
319 {Z80_OUT, Z80_H, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
320 {Z80_SBC, Z80_HL, Z80_REG, Z80_HL, 0}, | |
321 {Z80_LD, Z80_HL, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, | |
322 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
323 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
324 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, | |
325 {Z80_RRD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
326 {Z80_IN, Z80_L, Z80_REG_INDIRECT, Z80_C, 0}, | |
327 {Z80_OUT, Z80_L, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
328 {Z80_ADC, Z80_HL, Z80_REG, Z80_HL, 0}, | |
329 {Z80_LD, Z80_HL, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, | |
330 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
331 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
332 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 3},//Set undocumented mode 0/1 | |
333 {Z80_RLD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
334 //7 | |
335 {Z80_IN, Z80_UNUSED, Z80_REG_INDIRECT, Z80_C, 0}, | |
336 {Z80_OUT, Z80_USE_IMMED, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
337 {Z80_SBC, Z80_HL, Z80_REG, Z80_SP, 0}, | |
338 {Z80_LD, Z80_SP, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, | |
339 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
340 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
341 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 1}, | |
342 NOP, | |
343 {Z80_IN, Z80_A, Z80_REG_INDIRECT, Z80_C, 0}, | |
344 {Z80_OUT, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, | |
345 {Z80_ADC, Z80_HL, Z80_REG, Z80_SP, 0}, | |
346 {Z80_LD, Z80_SP, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, | |
347 {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, | |
348 {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
349 {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 2}, | |
350 NOP, | |
351 //8 | |
352 NOP, | |
353 NOP, | |
354 NOP, | |
355 NOP, | |
356 NOP, | |
357 NOP, | |
358 NOP, | |
359 NOP, | |
360 NOP, | |
361 NOP, | |
362 NOP, | |
363 NOP, | |
364 NOP, | |
365 NOP, | |
366 NOP, | |
367 NOP, | |
368 //9 | |
369 NOP, | |
370 NOP, | |
371 NOP, | |
372 NOP, | |
373 NOP, | |
374 NOP, | |
375 NOP, | |
376 NOP, | |
377 NOP, | |
378 NOP, | |
379 NOP, | |
380 NOP, | |
381 NOP, | |
382 NOP, | |
383 NOP, | |
384 NOP, | |
385 //A | |
386 {Z80_LDI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
387 {Z80_CPI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
388 {Z80_INI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
389 {Z80_OUTI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
390 NOP, | |
391 NOP, | |
392 NOP, | |
393 NOP, | |
394 {Z80_LDD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
395 {Z80_CPD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
396 {Z80_IND, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
397 {Z80_OUTD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
398 NOP, | |
399 NOP, | |
400 NOP, | |
401 NOP, | |
402 //B | |
403 {Z80_LDIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
404 {Z80_CPIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
405 {Z80_INIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
406 {Z80_OTIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
407 NOP, | |
408 NOP, | |
409 NOP, | |
410 NOP, | |
411 {Z80_LDDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
412 {Z80_CPDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
413 {Z80_INDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
414 {Z80_OTDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, | |
415 NOP, | |
416 NOP, | |
417 NOP, | |
418 NOP | |
419 }; | |
420 | |
280 uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) | 421 uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) |
281 { | 422 { |
282 if (*istream == 0xCB) { | 423 if (*istream == 0xCB) { |
283 } else if (*istream == 0xDD) { | 424 } else if (*istream == 0xDD) { |
284 } else if (*istream == 0xED) { | 425 } else if (*istream == 0xED) { |
426 istream++; | |
427 if (*istream < 0x40 || *istream >= 0xC0) { | |
428 memcpy(decoded, z80_tbl_extd + 0xBF, sizeof(z80inst)); | |
429 } else { | |
430 memcpy(decoded, z80_tbl_extd + *istream-0x40, sizeof(z80inst)); | |
431 } | |
285 } else if (*istream == 0xFD) { | 432 } else if (*istream == 0xFD) { |
286 } else { | 433 } else { |
287 memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); | 434 memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); |
288 if (decoded->addr_mode == Z80_IMMED && decoded->op != Z80_RST) { | 435 |
289 decoded->immed = *(++istream); | 436 } |
290 if (decoded->reg >= Z80_BC) { | 437 if ((decoded->addr_mode & 0xF) == Z80_IMMED && decoded->op != Z80_RST && decoded->op != Z80_IM) { |
291 decoded->immed |= *(++istream) << 8; | 438 decoded->immed = *(++istream); |
292 } else if (decoded->immed & 0x80) { | 439 if (decoded->reg >= Z80_BC && decoded->reg < Z80_USE_IMMED) { |
293 decoded->immed |= 0xFF00; | 440 decoded->immed |= *(++istream) << 8; |
294 } | 441 } else if (decoded->immed & 0x80) { |
295 } else if (decoded->addr_mode == Z80_IMMED_INDIRECT) { | 442 decoded->immed |= 0xFF00; |
296 decoded->immed = *(++istream); | |
297 if (decoded->op != Z80_OUT && decoded->op != Z80_IN) { | |
298 decoded->immed |= *(++istream) << 8; | |
299 } | |
300 } else if (decoded->reg == Z80_USE_IMMED) { | |
301 decoded->immed = *(++istream); | |
302 } | 443 } |
444 } else if ((decoded->addr_mode & 0xF) == Z80_IMMED_INDIRECT) { | |
445 decoded->immed = *(++istream); | |
446 if (decoded->op != Z80_OUT && decoded->op != Z80_IN) { | |
447 decoded->immed |= *(++istream) << 8; | |
448 } | |
449 } else if (decoded->reg == Z80_USE_IMMED) { | |
450 decoded->immed = *(++istream); | |
303 } | 451 } |
304 return istream+1; | 452 return istream+1; |
305 } | 453 } |
306 | 454 |
307 char *z80_mnemonics[Z80_OTDR+1] = { | 455 char *z80_mnemonics[Z80_OTDR+1] = { |
361 "retn", | 509 "retn", |
362 "rst", | 510 "rst", |
363 "in", | 511 "in", |
364 "ini", | 512 "ini", |
365 "inir", | 513 "inir", |
514 "ind", | |
366 "indr", | 515 "indr", |
367 "out", | 516 "out", |
368 "outi", | 517 "outi", |
369 "otir", | 518 "otir", |
370 "outd", | 519 "outd", |
378 "e", | 527 "e", |
379 "h", | 528 "h", |
380 "l", | 529 "l", |
381 "", | 530 "", |
382 "a", | 531 "a", |
532 "i", | |
533 "r", | |
383 "bc", | 534 "bc", |
384 "de", | 535 "de", |
385 "hl", | 536 "hl", |
386 "sp", | 537 "sp", |
387 "af", | 538 "af", |
400 | 551 |
401 int z80_disasm(z80inst * decoded, char * dst) | 552 int z80_disasm(z80inst * decoded, char * dst) |
402 { | 553 { |
403 int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]); | 554 int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]); |
404 if (decoded->addr_mode & Z80_DIR) { | 555 if (decoded->addr_mode & Z80_DIR) { |
405 switch (decoded->addr_mode) | 556 switch (decoded->addr_mode & 0xF) |
406 { | 557 { |
407 case Z80_REG: | 558 case Z80_REG: |
408 len += sprintf(dst+len, " %s", z80_regs[decoded->ea_reg]); | 559 len += sprintf(dst+len, " %s", z80_regs[decoded->ea_reg]); |
409 break; | 560 break; |
410 case Z80_REG_INDIRECT: | 561 case Z80_REG_INDIRECT: |