Mercurial > repos > blastem
comparison 68kinst.c @ 9:0a0cd3705c19
Implement (possibly broken) decoding of all M68000 instructions not in the OR_DIV_SBCD group
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 13 Nov 2012 18:26:43 -0800 |
parents | 23b83d94c633 |
children | 4553fc97b15e |
comparison
equal
deleted
inserted
replaced
8:23b83d94c633 | 9:0a0cd3705c19 |
---|---|
323 } | 323 } |
324 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); | 324 istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst)); |
325 break; | 325 break; |
326 case 7: | 326 case 7: |
327 //MOVEP | 327 //MOVEP |
328 deocded->op = M68K_MOVEP; | 328 decoded->op = M68K_MOVEP; |
329 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; | 329 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; |
330 if (*istream & 0x80) { | 330 if (*istream & 0x80) { |
331 //memory dest | 331 //memory dest |
332 decoded->src.addr_mode = MODE_REG; | 332 decoded->src.addr_mode = MODE_REG; |
333 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); | 333 decoded->src.params.regs.pri = m68K_reg_quick_field(*istream); |
335 decoded->dst.params.regs.pri = *istream & 0x7; | 335 decoded->dst.params.regs.pri = *istream & 0x7; |
336 } else { | 336 } else { |
337 //memory source | 337 //memory source |
338 decoded->dst.addr_mode = MODE_REG; | 338 decoded->dst.addr_mode = MODE_REG; |
339 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); | 339 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); |
340 decoded->sr.addr_mode = MODE_AREG_DISPLACE; | 340 decoded->src.addr_mode = MODE_AREG_DISPLACE; |
341 decoded->sr.params.regs.pri = *istream & 0x7; | 341 decoded->src.params.regs.pri = *istream & 0x7; |
342 } | 342 } |
343 immed = *(++istream); | 343 immed = *(++istream); |
344 | 344 |
345 break; | 345 break; |
346 } | 346 } |
367 decoded->op = M68K_CHK; | 367 decoded->op = M68K_CHK; |
368 if ((*istream & 0x180) == 0x180) { | 368 if ((*istream & 0x180) == 0x180) { |
369 decoded->extra.size = OPSIZE_WORD; | 369 decoded->extra.size = OPSIZE_WORD; |
370 } else { | 370 } else { |
371 //only on M68020+ | 371 //only on M68020+ |
372 #ifdef M68020 | |
372 decoded->extra.size = OPSIZE_LONG; | 373 decoded->extra.size = OPSIZE_LONG; |
374 #else | |
375 decoded->op = M68K_INVALID; | |
376 break; | |
377 #endif | |
373 } | 378 } |
374 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 379 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
375 decoded->dst.addr_mode = MODE_REG; | 380 decoded->dst.addr_mode = MODE_REG; |
376 decoded->dst.addr_mode = m68K_reg_quick_field(*istream); | 381 decoded->dst.addr_mode = m68K_reg_quick_field(*istream); |
377 } else { | 382 } else { |
378 optype = (*istream >> 9) & 0x7; | 383 if ((*istream & 0xB80) == 0x880) { |
379 switch(optype) | 384 decoded->op = M68K_MOVEM; |
380 { | 385 decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD; |
381 case 0: | 386 immed = *(++istream); |
382 //Move from SR or NEGX | 387 opmode = (*istream >> 3) & 0x7; |
383 break; | 388 reg = *istream & 0x7; |
384 case 1: | 389 if(*istream & 0x400) { |
385 //MOVE from CCR or CLR | 390 decoded->dst.addr_mode = MODE_REG; |
386 break; | 391 decoded->dst.params.u16 = immed; |
387 case 2: | 392 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src)); |
388 //MOVE to CCR or NEG | |
389 break; | |
390 case 3: | |
391 //MOVE to SR or NOT | |
392 break; | |
393 case 4: | |
394 //EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA, MOVEM | |
395 break; | |
396 case 5: | |
397 //BGND, ILLEGAL, TAS, TST | |
398 optype = *istream & 0xFF; | |
399 if (optype == 0xFA) { | |
400 //BGND - CPU32 only | |
401 } else if (optype == 0xFC) { | |
402 decoded->op = M68K_ILLEGAL; | |
403 } else { | 393 } else { |
404 size = (*istream & 0xC0) >> 6; | 394 decoded->src.addr_mode = MODE_REG; |
395 decoded->src.params.u16 = immed; | |
396 istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst)); | |
397 } | |
398 } else { | |
399 optype = (*istream >> 9) & 0x7; | |
400 size = (*istream >> 6) & 0x3; | |
401 switch(optype) | |
402 { | |
403 case 0: | |
404 //Move from SR or NEGX | |
405 if (size == OPSIZE_INVALID) { | 405 if (size == OPSIZE_INVALID) { |
406 decoded->op = M68K_TAS; | 406 decoded->op = M68K_MOVE_FROM_SR; |
407 size = OPSIZE_WORD; | |
407 } else { | 408 } else { |
408 decoded->op = M68K_TST; | 409 decoded->op = M68K_NEGX; |
409 decoded->extra.size = size; | |
410 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | |
411 } | 410 } |
412 } | 411 decoded->extra.size = size; |
413 break; | 412 istream= m68k_decode_op(istream, size, &(decoded->dst)); |
414 case 6: | 413 break; |
415 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL, MOVEM | 414 case 1: |
416 break; | 415 //MOVE from CCR or CLR |
417 case 7: | 416 if (size == OPSIZE_INVALID) { |
418 //TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP | 417 #ifdef M68010 |
419 if (*istream & 0x80) { | 418 decoded->op = M68K_MOVE_FROM_CCR; |
420 //JSR, JMP | 419 size = OPSIZE_WORD; |
421 } else { | 420 #else |
422 //it would appear bit 6 needs to be set for it to be a valid instruction here | 421 return istream+1; |
423 switch((*istream >> 3) & 0x7) | 422 #endif |
423 } else { | |
424 decoded->op = M68K_CLR; | |
425 } | |
426 decoded->extra.size = size; | |
427 istream= m68k_decode_op(istream, size, &(decoded->dst)); | |
428 break; | |
429 case 2: | |
430 //MOVE to CCR or NEG | |
431 if (size == OPSIZE_INVALID) { | |
432 decoded->op = M68K_MOVE_CCR; | |
433 size = OPSIZE_WORD; | |
434 istream= m68k_decode_op(istream, size, &(decoded->src)); | |
435 } else { | |
436 decoded->op = M68K_NEG; | |
437 istream= m68k_decode_op(istream, size, &(decoded->dst)); | |
438 } | |
439 decoded->extra.size = size; | |
440 break; | |
441 case 3: | |
442 //MOVE to SR or NOT | |
443 if (size == OPSIZE_INVALID) { | |
444 decoded->op = M68K_MOVE_SR; | |
445 size = OPSIZE_WORD; | |
446 istream= m68k_decode_op(istream, size, &(decoded->src)); | |
447 } else { | |
448 decoded->op = M68K_NOT; | |
449 istream= m68k_decode_op(istream, size, &(decoded->dst)); | |
450 } | |
451 decoded->extra.size = size; | |
452 break; | |
453 case 4: | |
454 //EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA | |
455 switch((*istream >> 3) & 0x3F) | |
424 { | 456 { |
425 case 0: | |
426 case 1: | 457 case 1: |
427 //TRAP | 458 #ifdef M68020 |
459 decoded->op = M68K_LINK; | |
460 decoded->extra.size = OPSIZE_LONG; | |
461 reg = *istream & 0x7; | |
462 immed = *(++istream) << 16; | |
463 immed |= *(++istream); | |
464 #endif | |
428 break; | 465 break; |
429 case 2: | 466 case 8: |
430 //LINK.w | 467 decoded->op = M68K_SWAP; |
468 decoded->src.addr_mode = MODE_REG; | |
469 decoded->src.params.regs.pri = *istream & 0x7; | |
470 decoded->extra.size = OPSIZE_WORD; | |
431 break; | 471 break; |
432 case 3: | 472 case 9: |
433 //UNLNK | 473 #ifdef M68010 |
474 decoded->op = M68K_BKPT; | |
475 decoded->src.addr_mode = MODE_IMMEDIATE; | |
476 decoded->extra.size = OPSIZE_BYTE; | |
477 decoded->src.params.u8 = *istream & 0x7; | |
478 #endif | |
434 break; | 479 break; |
435 case 4: | 480 case 0x10: |
436 case 5: | 481 decoded->op = M68K_EXT; |
437 //MOVE USP | 482 decoded->src.addr_mode = MODE_REG; |
483 decoded->src.params.regs.pri = *istream & 0x7; | |
484 decoded->extra.size = OPSIZE_WORD; | |
438 break; | 485 break; |
439 case 6: | 486 case 0x18: |
440 switch(*istream & 0x7) | 487 decoded->op = M68K_EXT; |
488 decoded->src.addr_mode = MODE_REG; | |
489 decoded->src.params.regs.pri = *istream & 0x7; | |
490 decoded->extra.size = OPSIZE_LONG; | |
491 break; | |
492 case 0x38: | |
493 #ifdef M68020 | |
494 #endif | |
495 break; | |
496 default: | |
497 if (!(*istream & 0x1C0)) { | |
498 decoded->op = M68K_NBCD; | |
499 decoded->extra.size = OPSIZE_BYTE; | |
500 istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst)); | |
501 } else if(*istream & 0x1C0 == 0x40) { | |
502 decoded->op = M68K_PEA; | |
503 decoded->extra.size = OPSIZE_LONG; | |
504 istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->dst)); | |
505 } | |
506 } | |
507 break; | |
508 case 5: | |
509 //BGND, ILLEGAL, TAS, TST | |
510 optype = *istream & 0xFF; | |
511 if (optype == 0xFA) { | |
512 //BGND - CPU32 only | |
513 } else if (optype == 0xFC) { | |
514 decoded->op = M68K_ILLEGAL; | |
515 } else { | |
516 if (size == OPSIZE_INVALID) { | |
517 decoded->op = M68K_TAS; | |
518 } else { | |
519 decoded->op = M68K_TST; | |
520 decoded->extra.size = size; | |
521 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | |
522 } | |
523 } | |
524 break; | |
525 case 6: | |
526 //MULU, MULS, DIVU, DIVUL, DIVS, DIVSL | |
527 #ifdef M68020 | |
528 //TODO: Implement these for 68020+ support | |
529 #endif | |
530 break; | |
531 case 7: | |
532 //TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP | |
533 if (*istream & 0x80) { | |
534 //JSR, JMP | |
535 if (*istream & 0x40) { | |
536 decoded->op = M68K_JMP; | |
537 } else { | |
538 decoded->op = M68K_JSR; | |
539 } | |
540 istream = m68k_decode_op(istream, OPSIZE_INVALID, &(decoded->src)); | |
541 } else { | |
542 //it would appear bit 6 needs to be set for it to be a valid instruction here | |
543 switch((*istream >> 3) & 0x7) | |
441 { | 544 { |
442 case 0: | 545 case 0: |
443 decoded->op = M68K_RESET; | |
444 break; | |
445 case 1: | 546 case 1: |
446 decoded->op = M68K_NOP; | 547 //TRAP |
548 decoded->op = M68K_TRAP; | |
549 decoded->extra.size = OPSIZE_BYTE; | |
550 decoded->src.addr_mode = MODE_IMMEDIATE; | |
551 decoded->src.params.u8 = *istream & 0xF; | |
447 break; | 552 break; |
448 case 2: | 553 case 2: |
449 decoded->op = M68K_STOP; | 554 //LINK.w |
555 decoded->op = M68K_LINK; | |
450 decoded->extra.size = OPSIZE_WORD; | 556 decoded->extra.size = OPSIZE_WORD; |
451 decoded->src.addr_mode = MODE_IMMEDIATE; | 557 decoded->src.addr_mode = MODE_AREG; |
452 decoded->src.params.u16 =*(++istream); | 558 decoded->src.params.regs.pri = *istream & 0x7; |
559 decoded->dst.addr_mode = MODE_IMMEDIATE; | |
560 decoded->dst.params.u16 = immed; | |
453 break; | 561 break; |
454 case 3: | 562 case 3: |
455 decoded->op = M68K_RTE; | 563 //UNLK |
564 decoded->op = M68K_UNLK; | |
565 decoded->dst.addr_mode = MODE_AREG; | |
566 decoded->dst.params.regs.pri = *istream & 0x7; | |
456 break; | 567 break; |
457 case 4: | 568 case 4: |
569 case 5: | |
570 //MOVE USP | |
571 decoded->op = M68K_MOVE_USP; | |
572 if (*istream & 0x8) { | |
573 decoded->dst.addr_mode = MODE_AREG; | |
574 decoded->dst.params.regs.pri = *istream & 0x7; | |
575 } else { | |
576 decoded->src.addr_mode = MODE_AREG; | |
577 decoded->src.params.regs.pri = *istream & 0x7; | |
578 } | |
579 break; | |
580 case 6: | |
581 switch(*istream & 0x7) | |
582 { | |
583 case 0: | |
584 decoded->op = M68K_RESET; | |
585 break; | |
586 case 1: | |
587 decoded->op = M68K_NOP; | |
588 break; | |
589 case 2: | |
590 decoded->op = M68K_STOP; | |
591 decoded->extra.size = OPSIZE_WORD; | |
592 decoded->src.addr_mode = MODE_IMMEDIATE; | |
593 decoded->src.params.u16 =*(++istream); | |
594 break; | |
595 case 3: | |
596 decoded->op = M68K_RTE; | |
597 break; | |
598 case 4: | |
458 #ifdef M68010 | 599 #ifdef M68010 |
459 decoded->op = M68K_RTD; | 600 decoded->op = M68K_RTD; |
460 decoded->extra.size = OPSIZE_WORD; | 601 decoded->extra.size = OPSIZE_WORD; |
461 decoded->src.addr_mode = MODE_IMMEDIATE; | 602 decoded->src.addr_mode = MODE_IMMEDIATE; |
462 decoded->src.params.u16 =*(++istream); | 603 decoded->src.params.u16 =*(++istream); |
604 #endif | |
605 break; | |
606 case 5: | |
607 decoded->op = M68K_RTS; | |
608 break; | |
609 case 6: | |
610 decoded->op = M68K_TRAPV; | |
611 break; | |
612 case 7: | |
613 decoded->op = M68K_RTR; | |
614 break; | |
615 } | |
616 break; | |
617 case 7: | |
618 //MOVEC | |
619 #ifdef M68010 | |
463 #endif | 620 #endif |
464 break; | 621 break; |
465 case 5: | |
466 decoded->op = M68K_RTS; | |
467 break; | |
468 case 6: | |
469 decoded->op = M68K_TRAPV; | |
470 break; | |
471 case 7: | |
472 decoded->op = M68K_RTR; | |
473 break; | |
474 } | 622 } |
475 break; | |
476 case 7: | |
477 //MOVEC | |
478 break; | |
479 } | 623 } |
624 break; | |
480 } | 625 } |
481 break; | |
482 } | 626 } |
483 } | 627 } |
484 } | 628 } |
485 break; | 629 break; |
486 case QUICK_ARITH_LOOP: | 630 case QUICK_ARITH_LOOP: |
605 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); | 749 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); |
606 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 750 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
607 } | 751 } |
608 break; | 752 break; |
609 case RESERVED: | 753 case RESERVED: |
610 //TODO: implement me | |
611 break; | 754 break; |
612 case CMP_XOR: | 755 case CMP_XOR: |
613 size = *istream >> 6 & 0x3; | 756 size = *istream >> 6 & 0x3; |
614 decoded->op = M68K_CMP; | 757 decoded->op = M68K_CMP; |
615 if (*istream & 0x100) { | 758 if (*istream & 0x100) { |
733 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); | 876 decoded->dst.params.regs.pri = m68K_reg_quick_field(*istream); |
734 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); | 877 istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src)); |
735 } | 878 } |
736 break; | 879 break; |
737 case SHIFT_ROTATE: | 880 case SHIFT_ROTATE: |
738 //TODO: Implement me | 881 if ((*istream & 0x8C0) == 0xC0) { |
882 switch((*istream >> 8) & 0x7) | |
883 { | |
884 case 0: | |
885 decoded->op = M68K_ASR; | |
886 break; | |
887 case 1: | |
888 decoded->op = M68K_ASL; | |
889 break; | |
890 case 2: | |
891 decoded->op = M68K_LSR; | |
892 break; | |
893 case 3: | |
894 decoded->op = M68K_LSL; | |
895 break; | |
896 case 4: | |
897 decoded->op = M68K_ROXR; | |
898 break; | |
899 case 5: | |
900 decoded->op = M68K_ROXL; | |
901 break; | |
902 case 6: | |
903 decoded->op = M68K_ROR; | |
904 break; | |
905 case 7: | |
906 decoded->op = M68K_ROL; | |
907 break; | |
908 } | |
909 decoded->extra.size = OPSIZE_WORD; | |
910 istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst)); | |
911 } else if((*istream & 0xC0) != 0xC0) { | |
912 switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1)) | |
913 { | |
914 case 0: | |
915 decoded->op = M68K_ASR; | |
916 break; | |
917 case 1: | |
918 decoded->op = M68K_ASL; | |
919 break; | |
920 case 2: | |
921 decoded->op = M68K_LSR; | |
922 break; | |
923 case 3: | |
924 decoded->op = M68K_LSL; | |
925 break; | |
926 case 4: | |
927 decoded->op = M68K_ROXR; | |
928 break; | |
929 case 5: | |
930 decoded->op = M68K_ROXL; | |
931 break; | |
932 case 6: | |
933 decoded->op = M68K_ROR; | |
934 break; | |
935 case 7: | |
936 decoded->op = M68K_ROL; | |
937 break; | |
938 } | |
939 decoded->extra.size = (*istream >> 6) & 0x3; | |
940 immed = (*istream >> 9) & 0x7; | |
941 if (*istream & 0x100) { | |
942 decoded->src.addr_mode = MODE_IMMEDIATE; | |
943 switch(decoded->extra.size) | |
944 { | |
945 case OPSIZE_BYTE: | |
946 decoded->src.params.u8 = immed; | |
947 break; | |
948 case OPSIZE_WORD: | |
949 decoded->src.params.u16 = immed; | |
950 break; | |
951 case OPSIZE_LONG: | |
952 decoded->src.params.u32 = immed; | |
953 break; | |
954 } | |
955 } else { | |
956 decoded->src.addr_mode = MODE_REG; | |
957 decoded->src.params.regs.pri = immed; | |
958 } | |
959 decoded->dst.addr_mode = MODE_REG; | |
960 decoded->dst.params.regs.pri = *istream & 0x7; | |
961 | |
962 } else { | |
963 #ifdef M68020 | |
964 //TODO: Implement bitfield instructions for M68020+ support | |
965 #endif | |
966 } | |
739 break; | 967 break; |
740 case COPROC: | 968 case COPROC: |
741 //TODO: Implement me | 969 //TODO: Implement me |
742 break; | 970 break; |
743 } | 971 } |