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: