Mercurial > repos > blastem
comparison 68kinst.c @ 630:47123183c336
Improve support for disassembling 68010+ binaries
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 08 Oct 2014 22:18:34 -0700 |
parents | 775802dab98f |
children | 4a6ec64acd79 |
comparison
equal
deleted
inserted
replaced
629:9089951a1994 | 630:47123183c336 |
---|---|
170 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 170 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
171 decoded->extra.size = OPSIZE_BYTE; | 171 decoded->extra.size = OPSIZE_BYTE; |
172 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); | 172 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); |
173 if (!istream) { | 173 if (!istream) { |
174 decoded->op = M68K_INVALID; | 174 decoded->op = M68K_INVALID; |
175 return start+1; | 175 break; |
176 } | 176 } |
177 if (decoded->dst.addr_mode == MODE_REG) { | 177 if (decoded->dst.addr_mode == MODE_REG) { |
178 decoded->extra.size = OPSIZE_LONG; | 178 decoded->extra.size = OPSIZE_LONG; |
179 } | 179 } |
180 } else if ((*istream & 0xF00) == 0x800) { | 180 } else if ((*istream & 0xF00) == 0x800) { |
200 decoded->src.params.immed = *(++istream) & 0xFF; | 200 decoded->src.params.immed = *(++istream) & 0xFF; |
201 decoded->extra.size = OPSIZE_BYTE; | 201 decoded->extra.size = OPSIZE_BYTE; |
202 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 202 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
203 if (!istream) { | 203 if (!istream) { |
204 decoded->op = M68K_INVALID; | 204 decoded->op = M68K_INVALID; |
205 return start+1; | 205 break; |
206 } | 206 } |
207 if (decoded->dst.addr_mode == MODE_REG) { | 207 if (decoded->dst.addr_mode == MODE_REG) { |
208 decoded->extra.size = OPSIZE_LONG; | 208 decoded->extra.size = OPSIZE_LONG; |
209 } | 209 } |
210 } else if ((*istream & 0xC0) == 0xC0) { | 210 } else if ((*istream & 0xC0) == 0xC0) { |
246 break; | 246 break; |
247 } | 247 } |
248 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 248 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
249 if (!istream) { | 249 if (!istream) { |
250 decoded->op = M68K_INVALID; | 250 decoded->op = M68K_INVALID; |
251 return start+1; | 251 break; |
252 } | 252 } |
253 } | 253 } |
254 break; | 254 break; |
255 case 1: | 255 case 1: |
256 //ANDI, ANDI to CCR, ANDI to SR | 256 //ANDI, ANDI to CCR, ANDI to SR |
285 break; | 285 break; |
286 } | 286 } |
287 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 287 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
288 if (!istream) { | 288 if (!istream) { |
289 decoded->op = M68K_INVALID; | 289 decoded->op = M68K_INVALID; |
290 return start+1; | 290 break; |
291 } | 291 } |
292 } | 292 } |
293 break; | 293 break; |
294 case 2: | 294 case 2: |
295 decoded->op = M68K_SUB; | 295 decoded->op = M68K_SUB; |
312 break; | 312 break; |
313 } | 313 } |
314 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 314 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
315 if (!istream) { | 315 if (!istream) { |
316 decoded->op = M68K_INVALID; | 316 decoded->op = M68K_INVALID; |
317 return start+1; | 317 break; |
318 } | 318 } |
319 break; | 319 break; |
320 case 3: | 320 case 3: |
321 decoded->op = M68K_ADD; | 321 decoded->op = M68K_ADD; |
322 decoded->variant = VAR_IMMEDIATE; | 322 decoded->variant = VAR_IMMEDIATE; |
338 break; | 338 break; |
339 } | 339 } |
340 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 340 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
341 if (!istream) { | 341 if (!istream) { |
342 decoded->op = M68K_INVALID; | 342 decoded->op = M68K_INVALID; |
343 return start+1; | 343 break; |
344 } | 344 } |
345 break; | 345 break; |
346 case 4: | 346 case 4: |
347 //BTST, BCHG, BCLR, BSET | 347 //BTST, BCHG, BCLR, BSET |
348 switch ((*istream >> 6) & 0x3) | 348 switch ((*istream >> 6) & 0x3) |
363 decoded->src.addr_mode = MODE_IMMEDIATE; | 363 decoded->src.addr_mode = MODE_IMMEDIATE; |
364 decoded->src.params.immed = *(++istream) & 0xFF; | 364 decoded->src.params.immed = *(++istream) & 0xFF; |
365 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); | 365 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); |
366 if (!istream) { | 366 if (!istream) { |
367 decoded->op = M68K_INVALID; | 367 decoded->op = M68K_INVALID; |
368 return start+1; | 368 break; |
369 } | 369 } |
370 break; | 370 break; |
371 case 5: | 371 case 5: |
372 //EORI, EORI to CCR, EORI to SR | 372 //EORI, EORI to CCR, EORI to SR |
373 if ((*istream & 0xFF) == 0x3C) { | 373 if ((*istream & 0xFF) == 0x3C) { |
401 break; | 401 break; |
402 } | 402 } |
403 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 403 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
404 if (!istream) { | 404 if (!istream) { |
405 decoded->op = M68K_INVALID; | 405 decoded->op = M68K_INVALID; |
406 return start+1; | 406 break; |
407 } | 407 } |
408 } | 408 } |
409 break; | 409 break; |
410 case 6: | 410 case 6: |
411 decoded->op = M68K_CMP; | 411 decoded->op = M68K_CMP; |
425 case OPSIZE_LONG: | 425 case OPSIZE_LONG: |
426 immed = *(++istream); | 426 immed = *(++istream); |
427 decoded->src.params.immed = (immed << 16) | *(++istream); | 427 decoded->src.params.immed = (immed << 16) | *(++istream); |
428 break; | 428 break; |
429 } | 429 } |
430 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 430 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
431 if (!istream) { | 431 if (!istream) { |
432 decoded->op = M68K_INVALID; | 432 decoded->op = M68K_INVALID; |
433 return start+1; | 433 break; |
434 } | 434 } |
435 break; | 435 break; |
436 case 7: | 436 case 7: |
437 | 437 #ifdef M68010 |
438 | 438 decoded->op = M68K_MOVES; |
439 decoded->extra.size = *istream >> 6 & 0x3; | |
440 immed = *(++istream); | |
441 reg = immed >> 12 & 0x7; | |
442 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG; | |
443 if (immed & 0x800) { | |
444 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->src)); | |
445 decoded->dst.addr_mode = opmode; | |
446 decoded->dst.params.regs.pri = reg; | |
447 } else { | |
448 decoded->src.addr_mode = opmode; | |
449 decoded->src.params.regs.pri = reg; | |
450 m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->dst)); | |
451 } | |
452 #endif | |
439 break; | 453 break; |
440 } | 454 } |
441 } | 455 } |
442 break; | 456 break; |
443 case MOVE_BYTE: | 457 case MOVE_BYTE: |
448 opmode = (*istream >> 6) & 0x7; | 462 opmode = (*istream >> 6) & 0x7; |
449 reg = m68k_reg_quick_field(*istream); | 463 reg = m68k_reg_quick_field(*istream); |
450 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 464 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
451 if (!istream) { | 465 if (!istream) { |
452 decoded->op = M68K_INVALID; | 466 decoded->op = M68K_INVALID; |
453 return start+1; | 467 break; |
454 } | 468 } |
455 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 469 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
456 if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) { | 470 if (!istream || decoded->dst.addr_mode == MODE_IMMEDIATE) { |
457 decoded->op = M68K_INVALID; | 471 decoded->op = M68K_INVALID; |
458 return start+1; | 472 break; |
459 } | 473 } |
460 break; | 474 break; |
461 case MISC: | 475 case MISC: |
462 | 476 |
463 if ((*istream & 0x1C0) == 0x1C0) { | 477 if ((*istream & 0x1C0) == 0x1C0) { |
466 decoded->dst.addr_mode = MODE_AREG; | 480 decoded->dst.addr_mode = MODE_AREG; |
467 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 481 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
468 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 482 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
469 if (!istream) { | 483 if (!istream) { |
470 decoded->op = M68K_INVALID; | 484 decoded->op = M68K_INVALID; |
471 return start+1; | 485 break; |
472 } | 486 } |
473 } else { | 487 } else { |
474 if (*istream & 0x100) { | 488 if (*istream & 0x100) { |
475 decoded->op = M68K_CHK; | 489 decoded->op = M68K_CHK; |
476 if ((*istream & 0x180) == 0x180) { | 490 if ((*istream & 0x180) == 0x180) { |
487 decoded->dst.addr_mode = MODE_REG; | 501 decoded->dst.addr_mode = MODE_REG; |
488 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 502 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
489 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 503 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
490 if (!istream) { | 504 if (!istream) { |
491 decoded->op = M68K_INVALID; | 505 decoded->op = M68K_INVALID; |
492 return start+1; | 506 break; |
493 } | 507 } |
494 } else { | 508 } else { |
495 opmode = (*istream >> 3) & 0x7; | 509 opmode = (*istream >> 3) & 0x7; |
496 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) { | 510 if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) { |
497 //TODO: Check for invalid modes that are dependent on direction | 511 //TODO: Check for invalid modes that are dependent on direction |
502 decoded->dst.addr_mode = MODE_REG; | 516 decoded->dst.addr_mode = MODE_REG; |
503 decoded->dst.params.immed = *(++istream); | 517 decoded->dst.params.immed = *(++istream); |
504 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); | 518 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); |
505 if (!istream) { | 519 if (!istream) { |
506 decoded->op = M68K_INVALID; | 520 decoded->op = M68K_INVALID; |
507 return start+1; | 521 break; |
508 } | 522 } |
509 if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) { | 523 if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) { |
510 //adjust displacement to account for extra instruction word | 524 //adjust displacement to account for extra instruction word |
511 decoded->src.params.regs.displacement += 2; | 525 decoded->src.params.regs.displacement += 2; |
512 } | 526 } |
514 decoded->src.addr_mode = MODE_REG; | 528 decoded->src.addr_mode = MODE_REG; |
515 decoded->src.params.immed = *(++istream); | 529 decoded->src.params.immed = *(++istream); |
516 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | 530 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); |
517 if (!istream) { | 531 if (!istream) { |
518 decoded->op = M68K_INVALID; | 532 decoded->op = M68K_INVALID; |
519 return start+1; | 533 break; |
520 } | 534 } |
521 } | 535 } |
522 } else { | 536 } else { |
523 optype = (*istream >> 9) & 0x7; | 537 optype = (*istream >> 9) & 0x7; |
524 size = (*istream >> 6) & 0x3; | 538 size = (*istream >> 6) & 0x3; |
534 } | 548 } |
535 decoded->extra.size = size; | 549 decoded->extra.size = size; |
536 istream= m68k_decode_op(istream, size, &(decoded->dst)); | 550 istream= m68k_decode_op(istream, size, &(decoded->dst)); |
537 if (!istream) { | 551 if (!istream) { |
538 decoded->op = M68K_INVALID; | 552 decoded->op = M68K_INVALID; |
539 return start+1; | 553 break; |
540 } | 554 } |
541 break; | 555 break; |
542 case 1: | 556 case 1: |
543 //MOVE from CCR or CLR | 557 //MOVE from CCR or CLR |
544 if (size == OPSIZE_INVALID) { | 558 if (size == OPSIZE_INVALID) { |
545 #ifdef M68010 | 559 #ifdef M68010 |
546 decoded->op = M68K_MOVE_FROM_CCR; | 560 decoded->op = M68K_MOVE_FROM_CCR; |
547 size = OPSIZE_WORD; | 561 size = OPSIZE_WORD; |
548 #else | 562 #else |
549 return istream+1; | 563 break; |
550 #endif | 564 #endif |
551 } else { | 565 } else { |
552 decoded->op = M68K_CLR; | 566 decoded->op = M68K_CLR; |
553 } | 567 } |
554 decoded->extra.size = size; | 568 decoded->extra.size = size; |
555 istream= m68k_decode_op(istream, size, &(decoded->dst)); | 569 istream= m68k_decode_op(istream, size, &(decoded->dst)); |
556 if (!istream) { | 570 if (!istream) { |
557 decoded->op = M68K_INVALID; | 571 decoded->op = M68K_INVALID; |
558 return start+1; | 572 break; |
559 } | 573 } |
560 break; | 574 break; |
561 case 2: | 575 case 2: |
562 //MOVE to CCR or NEG | 576 //MOVE to CCR or NEG |
563 if (size == OPSIZE_INVALID) { | 577 if (size == OPSIZE_INVALID) { |
564 decoded->op = M68K_MOVE_CCR; | 578 decoded->op = M68K_MOVE_CCR; |
565 size = OPSIZE_WORD; | 579 size = OPSIZE_WORD; |
566 istream= m68k_decode_op(istream, size, &(decoded->src)); | 580 istream= m68k_decode_op(istream, size, &(decoded->src)); |
567 if (!istream) { | 581 if (!istream) { |
568 decoded->op = M68K_INVALID; | 582 decoded->op = M68K_INVALID; |
569 return start+1; | 583 break; |
570 } | 584 } |
571 } else { | 585 } else { |
572 decoded->op = M68K_NEG; | 586 decoded->op = M68K_NEG; |
573 istream= m68k_decode_op(istream, size, &(decoded->dst)); | 587 istream= m68k_decode_op(istream, size, &(decoded->dst)); |
574 if (!istream) { | 588 if (!istream) { |
575 decoded->op = M68K_INVALID; | 589 decoded->op = M68K_INVALID; |
576 return start+1; | 590 break; |
577 } | 591 } |
578 } | 592 } |
579 decoded->extra.size = size; | 593 decoded->extra.size = size; |
580 break; | 594 break; |
581 case 3: | 595 case 3: |
584 decoded->op = M68K_MOVE_SR; | 598 decoded->op = M68K_MOVE_SR; |
585 size = OPSIZE_WORD; | 599 size = OPSIZE_WORD; |
586 istream= m68k_decode_op(istream, size, &(decoded->src)); | 600 istream= m68k_decode_op(istream, size, &(decoded->src)); |
587 if (!istream) { | 601 if (!istream) { |
588 decoded->op = M68K_INVALID; | 602 decoded->op = M68K_INVALID; |
589 return start+1; | 603 break; |
590 } | 604 } |
591 } else { | 605 } else { |
592 decoded->op = M68K_NOT; | 606 decoded->op = M68K_NOT; |
593 istream= m68k_decode_op(istream, size, &(decoded->dst)); | 607 istream= m68k_decode_op(istream, size, &(decoded->dst)); |
594 if (!istream) { | 608 if (!istream) { |
595 decoded->op = M68K_INVALID; | 609 decoded->op = M68K_INVALID; |
596 return start+1; | 610 break; |
597 } | 611 } |
598 } | 612 } |
599 decoded->extra.size = size; | 613 decoded->extra.size = size; |
600 break; | 614 break; |
601 case 4: | 615 case 4: |
646 decoded->op = M68K_NBCD; | 660 decoded->op = M68K_NBCD; |
647 decoded->extra.size = OPSIZE_BYTE; | 661 decoded->extra.size = OPSIZE_BYTE; |
648 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); | 662 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); |
649 if (!istream) { | 663 if (!istream) { |
650 decoded->op = M68K_INVALID; | 664 decoded->op = M68K_INVALID; |
651 return start+1; | 665 break; |
652 } | 666 } |
653 } else if((*istream & 0x1C0) == 0x40) { | 667 } else if((*istream & 0x1C0) == 0x40) { |
654 decoded->op = M68K_PEA; | 668 decoded->op = M68K_PEA; |
655 decoded->extra.size = OPSIZE_LONG; | 669 decoded->extra.size = OPSIZE_LONG; |
656 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); | 670 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); |
657 if (!istream) { | 671 if (!istream) { |
658 decoded->op = M68K_INVALID; | 672 decoded->op = M68K_INVALID; |
659 return start+1; | 673 break; |
660 } | 674 } |
661 } | 675 } |
662 } | 676 } |
663 break; | 677 break; |
664 case 5: | 678 case 5: |
676 decoded->op = M68K_TST; | 690 decoded->op = M68K_TST; |
677 decoded->extra.size = size; | 691 decoded->extra.size = size; |
678 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 692 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
679 if (!istream) { | 693 if (!istream) { |
680 decoded->op = M68K_INVALID; | 694 decoded->op = M68K_INVALID; |
681 return start+1; | 695 break; |
682 } | 696 } |
683 } | 697 } |
684 } | 698 } |
685 break; | 699 break; |
686 case 6: | 700 case 6: |
700 } | 714 } |
701 decoded->extra.size = OPSIZE_UNSIZED; | 715 decoded->extra.size = OPSIZE_UNSIZED; |
702 istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src)); | 716 istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src)); |
703 if (!istream) { | 717 if (!istream) { |
704 decoded->op = M68K_INVALID; | 718 decoded->op = M68K_INVALID; |
705 return start+1; | 719 break; |
706 } | 720 } |
707 } else { | 721 } else { |
708 //it would appear bit 6 needs to be set for it to be a valid instruction here | 722 //it would appear bit 6 needs to be set for it to be a valid instruction here |
709 switch((*istream >> 3) & 0x7) | 723 switch((*istream >> 3) & 0x7) |
710 { | 724 { |
781 } | 795 } |
782 break; | 796 break; |
783 case 7: | 797 case 7: |
784 //MOVEC | 798 //MOVEC |
785 #ifdef M68010 | 799 #ifdef M68010 |
800 decoded->op = M68K_MOVEC; | |
801 immed = *(++istream); | |
802 reg = immed >> 12 & 0x7; | |
803 opmode = immed & 0x8000 ? MODE_AREG : MODE_REG; | |
804 if (immed & 0x800) { | |
805 if (immed > MAX_HIGH_CR) { | |
806 decoded->op = M68K_INVALID; | |
807 break; | |
808 } else { | |
809 immed = immed - 0x800 + CR_USP; | |
810 } | |
811 } else { | |
812 if (immed > MAX_LOW_CR) { | |
813 decoded->op = M68K_INVALID; | |
814 break; | |
815 } | |
816 } | |
817 if (*start & 1) { | |
818 decoded->src.addr_mode = opmode; | |
819 decoded->src.params.regs.pri = reg; | |
820 decoded->dst.params.immed = immed; | |
821 } else { | |
822 decoded->dst.addr_mode = opmode; | |
823 decoded->dst.params.regs.pri = reg; | |
824 decoded->src.params.immed = immed; | |
825 } | |
786 #endif | 826 #endif |
787 break; | 827 break; |
788 } | 828 } |
789 } | 829 } |
790 break; | 830 break; |
814 decoded->op = M68K_SCC; | 854 decoded->op = M68K_SCC; |
815 decoded->extra.cond = (*istream >> 8) & 0xF; | 855 decoded->extra.cond = (*istream >> 8) & 0xF; |
816 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); | 856 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); |
817 if (!istream) { | 857 if (!istream) { |
818 decoded->op = M68K_INVALID; | 858 decoded->op = M68K_INVALID; |
819 return start+1; | 859 break; |
820 } | 860 } |
821 } | 861 } |
822 } else { | 862 } else { |
823 //ADDQ, SUBQ | 863 //ADDQ, SUBQ |
824 decoded->variant = VAR_QUICK; | 864 decoded->variant = VAR_QUICK; |
835 decoded->op = M68K_ADD; | 875 decoded->op = M68K_ADD; |
836 } | 876 } |
837 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 877 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
838 if (!istream) { | 878 if (!istream) { |
839 decoded->op = M68K_INVALID; | 879 decoded->op = M68K_INVALID; |
840 return start+1; | 880 break; |
841 } | 881 } |
842 } | 882 } |
843 break; | 883 break; |
844 case BRANCH: | 884 case BRANCH: |
845 m68k_decode_cond(*istream, decoded); | 885 m68k_decode_cond(*istream, decoded); |
863 decoded->src.params.immed = immed; | 903 decoded->src.params.immed = immed; |
864 break; | 904 break; |
865 case MOVEQ: | 905 case MOVEQ: |
866 if (*istream & 0x100) { | 906 if (*istream & 0x100) { |
867 decoded->op = M68K_INVALID; | 907 decoded->op = M68K_INVALID; |
868 return start+1; | 908 break; |
869 } | 909 } |
870 decoded->op = M68K_MOVE; | 910 decoded->op = M68K_MOVE; |
871 decoded->variant = VAR_QUICK; | 911 decoded->variant = VAR_QUICK; |
872 decoded->extra.size = OPSIZE_LONG; | 912 decoded->extra.size = OPSIZE_LONG; |
873 decoded->src.addr_mode = MODE_IMMEDIATE; | 913 decoded->src.addr_mode = MODE_IMMEDIATE; |
889 decoded->dst.addr_mode = MODE_REG; | 929 decoded->dst.addr_mode = MODE_REG; |
890 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; | 930 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; |
891 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 931 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
892 if (!istream || decoded->src.addr_mode == MODE_AREG) { | 932 if (!istream || decoded->src.addr_mode == MODE_AREG) { |
893 decoded->op = M68K_INVALID; | 933 decoded->op = M68K_INVALID; |
894 return start+1; | 934 break; |
895 } | 935 } |
896 break; | 936 break; |
897 case 4: | 937 case 4: |
898 decoded->op = M68K_SBCD; | 938 decoded->op = M68K_SBCD; |
899 decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG; | 939 decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG; |
914 decoded->dst.addr_mode = MODE_REG; | 954 decoded->dst.addr_mode = MODE_REG; |
915 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; | 955 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; |
916 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 956 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
917 if (!istream || decoded->src.addr_mode == MODE_AREG) { | 957 if (!istream || decoded->src.addr_mode == MODE_AREG) { |
918 decoded->op = M68K_INVALID; | 958 decoded->op = M68K_INVALID; |
919 return start+1; | 959 break; |
920 } | 960 } |
921 break; | 961 break; |
922 } | 962 } |
923 } else { | 963 } else { |
924 decoded->op = M68K_OR; | 964 decoded->op = M68K_OR; |
927 decoded->src.addr_mode = MODE_REG; | 967 decoded->src.addr_mode = MODE_REG; |
928 decoded->src.params.regs.pri = (*istream >> 9) & 0x7; | 968 decoded->src.params.regs.pri = (*istream >> 9) & 0x7; |
929 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 969 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
930 if (!istream) { | 970 if (!istream) { |
931 decoded->op = M68K_INVALID; | 971 decoded->op = M68K_INVALID; |
932 return start+1; | 972 break; |
933 } | 973 } |
934 } else { | 974 } else { |
935 decoded->dst.addr_mode = MODE_REG; | 975 decoded->dst.addr_mode = MODE_REG; |
936 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; | 976 decoded->dst.params.regs.pri = (*istream >> 9) & 0x7; |
937 istream = m68k_decode_op(istream, size, &(decoded->src)); | 977 istream = m68k_decode_op(istream, size, &(decoded->src)); |
938 if (!istream) { | 978 if (!istream) { |
939 decoded->op = M68K_INVALID; | 979 decoded->op = M68K_INVALID; |
940 return start+1; | 980 break; |
941 } | 981 } |
942 } | 982 } |
943 } | 983 } |
944 break; | 984 break; |
945 case SUB_SUBX: | 985 case SUB_SUBX: |
954 decoded->dst.addr_mode = MODE_AREG; | 994 decoded->dst.addr_mode = MODE_AREG; |
955 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 995 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
956 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); | 996 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); |
957 if (!istream) { | 997 if (!istream) { |
958 decoded->op = M68K_INVALID; | 998 decoded->op = M68K_INVALID; |
959 return start+1; | 999 break; |
960 } | 1000 } |
961 } else { | 1001 } else { |
962 decoded->extra.size = size; | 1002 decoded->extra.size = size; |
963 decoded->src.addr_mode = MODE_REG; | 1003 decoded->src.addr_mode = MODE_REG; |
964 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1004 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
965 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1005 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
966 if (!istream) { | 1006 if (!istream) { |
967 decoded->op = M68K_INVALID; | 1007 decoded->op = M68K_INVALID; |
968 return start+1; | 1008 break; |
969 } | 1009 } |
970 } | 1010 } |
971 } else { | 1011 } else { |
972 //SUBX | 1012 //SUBX |
973 decoded->op = M68K_SUBX; | 1013 decoded->op = M68K_SUBX; |
991 } | 1031 } |
992 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1032 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
993 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1033 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
994 if (!istream) { | 1034 if (!istream) { |
995 decoded->op = M68K_INVALID; | 1035 decoded->op = M68K_INVALID; |
996 return start+1; | 1036 break; |
997 } | 1037 } |
998 } | 1038 } |
999 break; | 1039 break; |
1000 case RESERVED: | 1040 case RESERVED: |
1001 break; | 1041 break; |
1009 decoded->dst.addr_mode = MODE_AREG; | 1049 decoded->dst.addr_mode = MODE_AREG; |
1010 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1050 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1011 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1051 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1012 if (!istream) { | 1052 if (!istream) { |
1013 decoded->op = M68K_INVALID; | 1053 decoded->op = M68K_INVALID; |
1014 return start+1; | 1054 break; |
1015 } | 1055 } |
1016 } else { | 1056 } else { |
1017 reg = m68k_reg_quick_field(*istream); | 1057 reg = m68k_reg_quick_field(*istream); |
1018 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1058 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1019 if (!istream) { | 1059 if (!istream) { |
1020 decoded->op = M68K_INVALID; | 1060 decoded->op = M68K_INVALID; |
1021 return start+1; | 1061 break; |
1022 } | 1062 } |
1023 decoded->extra.size = size; | 1063 decoded->extra.size = size; |
1024 if (decoded->dst.addr_mode == MODE_AREG) { | 1064 if (decoded->dst.addr_mode == MODE_AREG) { |
1025 //CMPM | 1065 //CMPM |
1026 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; | 1066 decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC; |
1044 } | 1084 } |
1045 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1085 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1046 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1086 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1047 if (!istream) { | 1087 if (!istream) { |
1048 decoded->op = M68K_INVALID; | 1088 decoded->op = M68K_INVALID; |
1049 return start+1; | 1089 break; |
1050 } | 1090 } |
1051 } | 1091 } |
1052 break; | 1092 break; |
1053 case AND_MUL_ABCD_EXG: | 1093 case AND_MUL_ABCD_EXG: |
1054 //page 575 for summary | 1094 //page 575 for summary |
1067 decoded->dst.addr_mode = MODE_REG; | 1107 decoded->dst.addr_mode = MODE_REG; |
1068 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1108 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1069 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 1109 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
1070 if (!istream) { | 1110 if (!istream) { |
1071 decoded->op = M68K_INVALID; | 1111 decoded->op = M68K_INVALID; |
1072 return start+1; | 1112 break; |
1073 } | 1113 } |
1074 } else if(!(*istream & 0xF0)) { | 1114 } else if(!(*istream & 0xF0)) { |
1075 decoded->op = M68K_ABCD; | 1115 decoded->op = M68K_ABCD; |
1076 decoded->extra.size = OPSIZE_BYTE; | 1116 decoded->extra.size = OPSIZE_BYTE; |
1077 decoded->src.params.regs.pri = *istream & 0x7; | 1117 decoded->src.params.regs.pri = *istream & 0x7; |
1098 decoded->src.addr_mode = MODE_REG; | 1138 decoded->src.addr_mode = MODE_REG; |
1099 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1139 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
1100 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); | 1140 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst)); |
1101 if (!istream) { | 1141 if (!istream) { |
1102 decoded->op = M68K_INVALID; | 1142 decoded->op = M68K_INVALID; |
1103 return start+1; | 1143 break; |
1104 } | 1144 } |
1105 } | 1145 } |
1106 } else { | 1146 } else { |
1107 if ((*istream & 0xC0) == 0xC0) { | 1147 if ((*istream & 0xC0) == 0xC0) { |
1108 decoded->op = M68K_MULU; | 1148 decoded->op = M68K_MULU; |
1110 decoded->dst.addr_mode = MODE_REG; | 1150 decoded->dst.addr_mode = MODE_REG; |
1111 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1151 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1112 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); | 1152 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src)); |
1113 if (!istream) { | 1153 if (!istream) { |
1114 decoded->op = M68K_INVALID; | 1154 decoded->op = M68K_INVALID; |
1115 return start+1; | 1155 break; |
1116 } | 1156 } |
1117 } else { | 1157 } else { |
1118 decoded->op = M68K_AND; | 1158 decoded->op = M68K_AND; |
1119 decoded->extra.size = (*istream >> 6) & 0x3; | 1159 decoded->extra.size = (*istream >> 6) & 0x3; |
1120 decoded->dst.addr_mode = MODE_REG; | 1160 decoded->dst.addr_mode = MODE_REG; |
1121 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1161 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1122 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1162 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1123 if (!istream) { | 1163 if (!istream) { |
1124 decoded->op = M68K_INVALID; | 1164 decoded->op = M68K_INVALID; |
1125 return start+1; | 1165 break; |
1126 } | 1166 } |
1127 } | 1167 } |
1128 } | 1168 } |
1129 break; | 1169 break; |
1130 case ADD_ADDX: | 1170 case ADD_ADDX: |
1139 decoded->dst.addr_mode = MODE_AREG; | 1179 decoded->dst.addr_mode = MODE_AREG; |
1140 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1180 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1141 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); | 1181 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src)); |
1142 if (!istream) { | 1182 if (!istream) { |
1143 decoded->op = M68K_INVALID; | 1183 decoded->op = M68K_INVALID; |
1144 return start+1; | 1184 break; |
1145 } | 1185 } |
1146 } else { | 1186 } else { |
1147 decoded->extra.size = size; | 1187 decoded->extra.size = size; |
1148 decoded->src.addr_mode = MODE_REG; | 1188 decoded->src.addr_mode = MODE_REG; |
1149 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); | 1189 decoded->src.params.regs.pri = m68k_reg_quick_field(*istream); |
1150 istream = m68k_decode_op(istream, size, &(decoded->dst)); | 1190 istream = m68k_decode_op(istream, size, &(decoded->dst)); |
1151 if (!istream) { | 1191 if (!istream) { |
1152 decoded->op = M68K_INVALID; | 1192 decoded->op = M68K_INVALID; |
1153 return start+1; | 1193 break; |
1154 } | 1194 } |
1155 } | 1195 } |
1156 } else { | 1196 } else { |
1157 //ADDX | 1197 //ADDX |
1158 decoded->op = M68K_ADDX; | 1198 decoded->op = M68K_ADDX; |
1176 } | 1216 } |
1177 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); | 1217 decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream); |
1178 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 1218 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
1179 if (!istream) { | 1219 if (!istream) { |
1180 decoded->op = M68K_INVALID; | 1220 decoded->op = M68K_INVALID; |
1181 return start+1; | 1221 break; |
1182 } | 1222 } |
1183 } | 1223 } |
1184 break; | 1224 break; |
1185 case SHIFT_ROTATE: | 1225 case SHIFT_ROTATE: |
1186 if ((*istream & 0x8C0) == 0xC0) { | 1226 if ((*istream & 0x8C0) == 0xC0) { |
1213 } | 1253 } |
1214 decoded->extra.size = OPSIZE_WORD; | 1254 decoded->extra.size = OPSIZE_WORD; |
1215 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); | 1255 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); |
1216 if (!istream) { | 1256 if (!istream) { |
1217 decoded->op = M68K_INVALID; | 1257 decoded->op = M68K_INVALID; |
1218 return start+1; | 1258 break; |
1219 } | 1259 } |
1220 } else if((*istream & 0xC0) != 0xC0) { | 1260 } else if((*istream & 0xC0) != 0xC0) { |
1221 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) | 1261 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) |
1222 { | 1262 { |
1223 case 0: | 1263 case 0: |
1267 } | 1307 } |
1268 break; | 1308 break; |
1269 case COPROC: | 1309 case COPROC: |
1270 //TODO: Implement me | 1310 //TODO: Implement me |
1271 break; | 1311 break; |
1312 } | |
1313 if (decoded->op == M68K_INVALID) { | |
1314 decoded->src.params.immed = *start; | |
1315 return start + 1; | |
1272 } | 1316 } |
1273 return istream+1; | 1317 return istream+1; |
1274 } | 1318 } |
1275 | 1319 |
1276 uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs) | 1320 uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs) |
1414 "tas", | 1458 "tas", |
1415 "trap", | 1459 "trap", |
1416 "trapv", | 1460 "trapv", |
1417 "tst", | 1461 "tst", |
1418 "unlk", | 1462 "unlk", |
1419 "invalid" | 1463 "invalid", |
1464 #ifdef M68010 | |
1465 "bkpt", | |
1466 "move", //from ccr | |
1467 "movec", | |
1468 "moves", | |
1469 #endif | |
1470 #ifdef M68020 | |
1471 "bfchg", | |
1472 "bfclr", | |
1473 "bfexts", | |
1474 "bfextu", | |
1475 "bfffo", | |
1476 "bfins", | |
1477 "bfset", | |
1478 "bftst", | |
1479 "callm", | |
1480 "cas", | |
1481 "cas2", | |
1482 "chk2", | |
1483 "cmp2", | |
1484 "cpbcc", | |
1485 "cpdbcc", | |
1486 "cpgen", | |
1487 "cprestore", | |
1488 "cpsave", | |
1489 "cpscc", | |
1490 "cptrapcc", | |
1491 "divsl", | |
1492 "divul", | |
1493 "extb", | |
1494 "pack", | |
1495 "rtm", | |
1496 "trapcc", | |
1497 "unpk" | |
1498 #endif | |
1420 }; | 1499 }; |
1421 | 1500 |
1422 char * cond_mnem[] = { | 1501 char * cond_mnem[] = { |
1423 "ra", | 1502 "ra", |
1424 "f", | 1503 "f", |
1435 "ge", | 1514 "ge", |
1436 "lt", | 1515 "lt", |
1437 "gt", | 1516 "gt", |
1438 "le" | 1517 "le" |
1439 }; | 1518 }; |
1519 #ifdef M68010 | |
1520 char * cr_mnem[] = { | |
1521 "SFC", | |
1522 "DFC", | |
1523 #ifdef M68020 | |
1524 "CACR", | |
1525 #endif | |
1526 "USP", | |
1527 "VBR", | |
1528 #ifdef M68020 | |
1529 "CAAR", | |
1530 "MSP", | |
1531 "ISP" | |
1532 #endif | |
1533 }; | |
1534 #endif | |
1440 | 1535 |
1441 int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address) | 1536 int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address) |
1442 { | 1537 { |
1443 char * c = need_comma ? "," : ""; | 1538 char * c = need_comma ? "," : ""; |
1444 switch(decoded->addr_mode) | 1539 switch(decoded->addr_mode) |
1609 } else { | 1704 } else { |
1610 ret += sprintf(dst + ret, "USP, "); | 1705 ret += sprintf(dst + ret, "USP, "); |
1611 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address); | 1706 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address); |
1612 } | 1707 } |
1613 return ret; | 1708 return ret; |
1709 case M68K_INVALID: | |
1710 ret = sprintf(dst, "dc.w $%X", decoded->src.params.immed); | |
1711 return ret; | |
1712 #ifdef M68010 | |
1713 case M68K_MOVEC: | |
1714 ret = sprintf(dst, "%s ", mnemonics[decoded->op]); | |
1715 if (decoded->src.addr_mode == MODE_UNUSED) { | |
1716 ret += sprintf(dst + ret, "%s, ", cr_mnem[decoded->src.params.immed]); | |
1717 ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address); | |
1718 } else { | |
1719 ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address); | |
1720 ret += sprintf(dst + ret, ", %s", cr_mnem[decoded->dst.params.immed]); | |
1721 } | |
1722 return ret; | |
1723 #endif | |
1614 default: | 1724 default: |
1615 size = decoded->extra.size; | 1725 size = decoded->extra.size; |
1616 ret = sprintf(dst, "%s%s%s", | 1726 ret = sprintf(dst, "%s%s%s", |
1617 mnemonics[decoded->op], | 1727 mnemonics[decoded->op], |
1618 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""), | 1728 decoded->variant == VAR_QUICK ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""), |