home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / EMULATOR / UNIX / CAIN1 / DASM.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  7KB  |  342 lines

  1. /*
  2. dasm
  3.  
  4. CP/M emulator - instruction disassembler
  5. Written by D'Arcy J.M. Cain
  6. darcy@druid
  7.  
  8. */
  9.  
  10. #include    <stdio.h>
  11. #include    <string.h>
  12. #include    "cpm.h"
  13.  
  14. #define        get_prog_word(buf)    (buf[1] + (buf[2] << 8))
  15. #define        get_prog_byte(buf)    (*buf)
  16.  
  17. static char        *get_b_reg(int reg)
  18. {
  19.     switch(reg & 0x07)
  20.     {
  21.         case 7:        return("A");
  22.         case 6:        return("(HL)");
  23.         case 0:        return("B");
  24.         case 1:        return("C");
  25.         case 2:        return("D");
  26.         case 3:        return("E");
  27.         case 4:        return("H");
  28.         case 5:        return("L");
  29.     }
  30.  
  31.     return(NULL);
  32. }
  33.  
  34. static char        *get_w_reg(int reg)
  35. {
  36.     switch (reg & 0x03)
  37.     {
  38.         case 2:        return("HL");
  39.         case 1:        return("DE");
  40.         case 0:        return("BC");
  41.         case 3:        return("SP");
  42.     }
  43.  
  44.     return(NULL);
  45. }
  46.  
  47. static char        *get_s_reg(int reg)
  48. {
  49.     switch (reg & 0x03)
  50.     {
  51.         case 2:        return("HL");
  52.         case 1:        return("DE");
  53.         case 0:        return("BC");
  54.         case 3:        return("AF");
  55.     }
  56.  
  57.     return(NULL);
  58. }
  59.  
  60. static int        relative(int r)
  61. {
  62.     if (r & 0x80)
  63.         r |= -256;
  64.  
  65.     return(PC + r + 2);
  66. }
  67.  
  68. static char        *condition(int word)
  69. {
  70.     switch (word & 0x07)
  71.     {
  72.         case 0:        return("NZ");
  73.         case 1:        return("Z");
  74.         case 2:        return("NC");
  75.         case 3:        return("C");
  76.         case 4:        return("PO");
  77.         case 5:        return("PE");
  78.         case 6:        return("P");
  79.         case 7:        return("M");
  80.     }
  81.  
  82.     return("\a* * * Internal error (condition()) * * *");
  83. }
  84.  
  85. const char     *dasm(const byte *buf)
  86. {
  87.     static char    str[32];
  88.     char        s[32];
  89.  
  90.     switch (*buf & 0xc0)                /* get class of opcode */
  91.     {
  92.         case 0x40:                        /* data transfer */
  93.             if (*buf == 0x76)            /* HALT - special case */
  94.                 return("HALT");
  95.  
  96.             sprintf(str, "LD\t%s, %s", get_b_reg(*buf >> 3), get_b_reg(*buf));
  97.             return(str);
  98.  
  99.         case 0x80:                        /* 8 bit math & logic */
  100.             strcpy(s, get_b_reg(*buf));
  101.             strcpy(str, "* * * Internal error * * *");
  102.  
  103. math_immediate:                            /* comes from misc instructions */
  104.             switch ((*buf >> 3) & 7)        /* logic op */
  105.             {
  106.                 case 1:                    /* ADC */
  107.                     sprintf(str, "ADC\tA, %s", s);
  108.                     break;
  109.  
  110.                 case 0:                    /* ADD */
  111.                     sprintf(str, "ADD\tA, %s", s);
  112.                     break;
  113.     
  114.                 case 3:                    /* SBC */
  115.                     sprintf(str, "SBC\tA, %s", s);
  116.                     break;
  117.  
  118.                 case 2:                    /* SUB */
  119.                     sprintf(str, "SUB\tA, %s", s);
  120.                     break;
  121.  
  122.                 case 4:                    /* AND */
  123.                     sprintf(str, "AND\tA, %s", s);
  124.                     break;
  125.  
  126.                 case 5:                    /* XOR */
  127.                     sprintf(str, "XOR\tA, %s", s);
  128.                     break;
  129.  
  130.                 case 6:                    /* OR */
  131.                     sprintf(str, "OR\tA, %s", s);
  132.                     break;
  133.  
  134.                 case 7:                    /* CP */
  135.                     sprintf(str, "CP\tA, %s", s);
  136.                     break;
  137.             }                            /* end - logic op */
  138.  
  139.             return(str);
  140.  
  141.         case 0xc0:                        /* Misc */
  142.             if ((*buf & 0x07) == 0x06)
  143.             {
  144.                 sprintf(s, "0%02.2xH", buf[1]);
  145.                 goto math_immediate;    /* sometimes they're necessary */
  146.             }
  147.  
  148.             if ((*buf & 0x0f) == 1)        /* POP */
  149.             {
  150.                 sprintf(str, "POP\t%s", get_s_reg(*buf >> 4));
  151.                 return(str);
  152.             }
  153.  
  154.             if ((*buf & 0x0f) == 5)        /* PUSH */
  155.             {
  156.                 sprintf(str, "PUSH\t%s", get_s_reg(*buf >> 4));
  157.                 return(str);
  158.             }
  159.  
  160.  
  161.             switch (*buf & 0x07)        /* BRANCH */
  162.             {
  163.                 case 0:                    /* RET cc */
  164.                     sprintf(str, "RET\t%s", condition(*buf >> 3));
  165.                     return(str);
  166.  
  167.                 case 2:                    /* JP cc */
  168.                     sprintf(str, "JP\t%s, 0%02.2x%02.2xH",
  169.                                 condition(*buf >> 3), buf[2], buf[1]);
  170.                     return(str);
  171.  
  172.                 case 4:                    /* CALL cc */
  173.                     sprintf(str, "CALL\t%s, 0%02.2x%02.2xH",
  174.                                 condition(*buf >> 3), buf[2], buf[1]);
  175.                     return(str);
  176.  
  177.                 case 7:                    /* RST n */
  178.                     sprintf(str, "RST\t%d", (*buf >> 3) & 0x07);
  179.                     return(str);
  180.             }                            /* end - BRANCH */
  181.  
  182.             switch (*buf)                /* misc */
  183.             {
  184.                 case 0xcd:                /* CALL */
  185.                     sprintf(str, "CALL\t0%02.2x%02.2xH", buf[2], buf[1]);
  186.                     return(str);
  187.  
  188.                 case 0xc3:                /* JP */
  189.                     sprintf(str, "JP\t0%02.2x%02.2xH", buf[2], buf[1]);
  190.                     return(str);
  191.  
  192.                 case 0xc9:                /* RET */
  193.                     sprintf(str, "RET");
  194.                     return(str);
  195.  
  196.                 case 0xeb:                /* EX DE, HL */
  197.                     return("EX\tDE, HL");
  198.  
  199.                 case 0xe9:                /* JP (HL) */
  200.                     return("JP\t(HL)");
  201.  
  202.                 case 0xe3:                /* EX (SP), HL */
  203.                     return("EX\t(SP), HL");
  204.  
  205.                 case 0xf9:                /* LD SP, HL */
  206.                     return("LD\tSP, HL");
  207.  
  208.                 case 0xf3:                /* DI */
  209.                     return("DI");
  210.  
  211.                 case 0xfb:                /* EI */
  212.                     return("EI");
  213.             }                                /* misc */
  214.  
  215.             sprintf(str, "Unrecognized command (0x%02.2x)", *buf);
  216.             return(str);
  217.  
  218.         case 0:
  219.             switch (*buf & 0x07)            /* misc data (3) */
  220.             {
  221.                 case 4:                        /* INC byte */
  222.                     sprintf(str, "INC\t%s", get_b_reg(*buf >> 3));
  223.                     return(str);
  224.  
  225.                 case 5:                        /* DEC byte */
  226.                     sprintf(str, "DEC\t%s", get_b_reg(*buf >> 3));
  227.                     return(str);
  228.  
  229.                 case 6:                        /* LD byte immediate */
  230.                     sprintf(str, "LD\t%s, 0%02.2xH",
  231.                                 get_b_reg(*buf >> 3), buf[1]);
  232.                     return(str);
  233.             }                                /* end - misc data (3) */
  234.  
  235.             switch (*buf & 0x0f)            /* misc data (4) */
  236.             {
  237.                 case 1:                        /* LD word immediate */
  238.                     sprintf(str, "LD\t%s, 0%02.2x%02.2xH",
  239.                                 get_w_reg(*buf >> 4), buf[2], buf[1]);
  240.                     return(str);
  241.  
  242.                 case 0x03:                    /* INC word */
  243.                     sprintf(str, "INC\t%s", get_w_reg(*buf >> 4));
  244.                     return(str);
  245.  
  246.                 case 0x0b:                    /* DEC word */
  247.                     sprintf(str, "DEC\t%s", get_w_reg(*buf >> 4));
  248.                     return(str);
  249.  
  250.                 case 0x09:                    /* ADD HL, ss */
  251.                     sprintf(str, "ADD\tHL, %s", get_w_reg(*buf >> 4));
  252.                     return(str);
  253.             }                                /* end - misc date (4) */
  254.  
  255.             switch (*buf)                    /* misc data */
  256.             {
  257.                 case 0:                        /* NOP */
  258.                     return("NOP");
  259.  
  260.                 case 0x02:                    /* LD (BC), A */
  261.                     return("LD\t(BC), A");
  262.  
  263.                 case 0x10:
  264.                     sprintf(str, "DJNZ\t0%04.4xH", relative(buf[1]));
  265.                     return(str);
  266.  
  267.                 case 0x20:
  268.                     sprintf(str, "JR\tNZ, 0%04.4xH", relative(buf[1]));
  269.                     return(str);
  270.  
  271.                 case 0x30:
  272.                     sprintf(str, "JR\tNC, 0%04.4xH", relative(buf[1]));
  273.                     return(str);
  274.  
  275.                 case 0x18:
  276.                     sprintf(str, "JR\t, 0%04.4xH", relative(buf[1]));
  277.                     return(str);
  278.  
  279.                 case 0x28:
  280.                     sprintf(str, "JR\tZ, 0%04.4xH", relative(buf[1]));
  281.                     return(str);
  282.  
  283.                 case 0x38:
  284.                     sprintf(str, "JR\tC, 0%04.4xH", relative(buf[1]));
  285.                     return(str);
  286.  
  287.                 case 0x12:                    /* LD (DE), A */
  288.                     return("LD\t(DE), A");
  289.  
  290.                 case 0x22:                    /* LD (nn), HL */
  291.                     sprintf(str, "LD\t(0%02.2x%02.2xH), HL", buf[2], buf[1]);
  292.                     return(str);
  293.  
  294.                 case 0x32:                    /* LD (nn), A */
  295.                     sprintf(str, "LD\t(0%02.2x%02.2xH), A", buf[2], buf[1]);
  296.                     return(str);
  297.  
  298.                 case 0x0a:                    /* LD A, (BC) */
  299.                     return("LD\tA, (BC)");
  300.  
  301.                 case 0x1a:                    /* LD A, (DE) */
  302.                     return("LD\tA, (DE)");
  303.  
  304.                 case 0x2a:                    /* LD HL, (nn) */
  305.                     sprintf(str, "LD\tHL, (0%02.2x%02.2xH)", buf[2], buf[1]);
  306.                     return(str);
  307.  
  308.                 case 0x3a:                    /* LD A, (nn) */
  309.                     sprintf(str, "LD\tA, (0%02.2x%02.2xH)", buf[2], buf[1]);
  310.                     return(str);
  311.  
  312.                 case 7:                        /* RLCA */
  313.                     return("RLCA");
  314.  
  315.                 case 0x0f:                    /* RRCA */
  316.                     return("RRCA");
  317.  
  318.                 case 0x17:                    /* RLA */
  319.                     return("RLA");
  320.  
  321.                 case 0x1f:                    /* RRA */
  322.                     return("RRA");
  323.  
  324.                 case 0x27:                    /* DAA */
  325.                     return("DAA");
  326.  
  327.                 case 0x2f:                    /* CPL */
  328.                     return("CPL");
  329.  
  330.                 case 0x37:                    /* SCF */
  331.                     return("SCF");
  332.  
  333.                 case 0x3f:                    /* CCF */
  334.                     return("CCF");
  335.             }                                /* end - misc date */
  336.  
  337.             return("* * * Internal error * * *");
  338.     }                                        /* end class */
  339.  
  340.     return("* * * Internal error * * *");
  341. }
  342.