home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / armdis.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  20.6 KB  |  743 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. /************************************************************************/
  20. /* Arm/Thumb command set disassembler                                   */
  21. /************************************************************************/
  22. #include <stdio.h>
  23.  
  24. #include "System.h"
  25. #include "Port.h"
  26. #include "GBA.h"
  27. #include "armdis.h"
  28. #include "elf.h"
  29.  
  30. struct Opcodes {
  31.   u32 mask;
  32.   u32 cval;
  33.   char *mnemonic;
  34. };
  35.  
  36. #define debuggerReadMemory(addr) \
  37.   READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
  38.  
  39. #define debuggerReadHalfWord(addr) \
  40.   READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
  41.  
  42. #define debuggerReadByte(addr) \
  43.   map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
  44.  
  45. const char hdig[] = "0123456789abcdef";
  46.  
  47. const char *decVals[16] = {
  48.   "0","1","2","3","4","5","6","7","8",
  49.   "9","10","11","12","13","14","15"
  50. };
  51.  
  52. const char *regs[16] = {
  53.   "r0","r1","r2","r3","r4","r5","r6","r7",
  54.   "r8","r9","r10","r11","r12","sp","lr","pc"
  55. };
  56.  
  57. const char *conditions[16] = {
  58.   "eq","ne","cs","cc","mi","pl","vs","vc",
  59.   "hi","ls","ge","lt","gt","le","","nv"
  60. };
  61.  
  62. const char *shifts[5] = {
  63.   "lsl","lsr","asr","ror","rrx"
  64. };
  65.  
  66. const char *armMultLoadStore[12] = {
  67.   // non-stack
  68.   "da","ia","db","ib",
  69.   // stack store
  70.   "ed","ea","fd","fa",
  71.   // stack load
  72.   "fa","fd","ea","ed"
  73. };
  74.  
  75. const Opcodes thumbOpcodes[] = {
  76.   // Format 1
  77.   {0xf800, 0x0000, "lsl %r0, %r3, %o"},
  78.   {0xf800, 0x0800, "lsr %r0, %r3, %o"},
  79.   {0xf800, 0x1000, "asr %r0, %r3, %o"},
  80.   // Format 2
  81.   {0xfe00, 0x1800, "add %r0, %r3, %r6"},
  82.   {0xfe00, 0x1a00, "sub %r0, %r3, %r6"},
  83.   {0xfe00, 0x1c00, "add %r0, %r3, %i"},
  84.   {0xfe00, 0x1e00, "sub %r0, %r3, %i"},
  85.   // Format 3
  86.   {0xf800, 0x2000, "mov %r8, %O"},
  87.   {0xf800, 0x2800, "cmp %r8, %O"},
  88.   {0xf800, 0x3000, "add %r8, %O"},
  89.   {0xf800, 0x3800, "sub %r8, %O"},
  90.   // Format 4
  91.   {0xffc0, 0x4000, "and %r0, %r3"},
  92.   {0xffc0, 0x4040, "eor %r0, %r3"},
  93.   {0xffc0, 0x4080, "lsl %r0, %r3"},
  94.   {0xffc0, 0x40c0, "lsr %r0, %r3"},
  95.   {0xffc0, 0x4100, "asr %r0, %r3"},
  96.   {0xffc0, 0x4140, "adc %r0, %r3"},
  97.   {0xffc0, 0x4180, "sbc %r0, %r3"},
  98.   {0xffc0, 0x41c0, "ror %r0, %r3"},
  99.   {0xffc0, 0x4200, "tst %r0, %r3"},
  100.   {0xffc0, 0x4240, "neg %r0, %r3"},
  101.   {0xffc0, 0x4280, "cmp %r0, %r3"},
  102.   {0xffc0, 0x42c0, "cmn %r0, %r3"},
  103.   {0xffc0, 0x4300, "orr %r0, %r3"},
  104.   {0xffc0, 0x4340, "mul %r0, %r3"},
  105.   {0xffc0, 0x4380, "bic %r0, %r3"},
  106.   {0xffc0, 0x43c0, "mvn %r0, %r3"},
  107.   // Format 5
  108.   {0xff80, 0x4700, "bx %h36"},
  109.   {0xfcc0, 0x4400, "[ ??? ]"},
  110.   {0xff00, 0x4400, "add %h07, %h36"},
  111.   {0xff00, 0x4500, "cmp %h07, %h36"},
  112.   {0xff00, 0x4600, "mov %h07, %h36"},
  113.   // Format 6
  114.   {0xf800, 0x4800, "ldr %r8, [%I] (=%J)"},
  115.   // Format 7
  116.   {0xfa00, 0x5000, "str%b %r0, [%r3, %r6]"},
  117.   {0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]"},
  118.   // Format 8
  119.   {0xfe00, 0x5200, "strh %r0, [%r3, %r6]"},
  120.   {0xfe00, 0x5600, "ldrh %r0, [%r3, %r6]"},
  121.   {0xfe00, 0x5a00, "ldsb %r0, [%r3, %r6]"},
  122.   {0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]"},
  123.   // Format 9
  124.   {0xe800, 0x6000, "str%B %r0, [%r3, %p]"},
  125.   {0xe800, 0x6800, "ldr%B %r0, [%r3, %p]"},
  126.   // Format 10
  127.   {0xf800, 0x8000, "strh %r0, [%r3, %e]"},
  128.   {0xf800, 0x8800, "ldrh %r0, [%r3, %e]"},
  129.   // Format 11
  130.   {0xf800, 0x9000, "str %r8, [sp, %w]"},
  131.   {0xf800, 0x9800, "ldr %r8, [sp, %w]"},
  132.   // Format 12
  133.   {0xf800, 0xa000, "add %r8, pc, %w (=%K)"},
  134.   {0xf800, 0xa800, "add %r8, sp, %w"},
  135.   // Format 13
  136.   {0xff00, 0xb000, "add sp, %s"},
  137.   // Format 14
  138.   {0xffff, 0xb500, "push {lr}"},  
  139.   {0xff00, 0xb400, "push {%l}"},
  140.   {0xff00, 0xb500, "push {%l,lr}"},
  141.   {0xffff, 0xbd00, "pop {pc}"},
  142.   {0xff00, 0xbd00, "pop {%l,pc}"},  
  143.   {0xff00, 0xbc00, "pop {%l}"},
  144.   // Format 15
  145.   {0xf800, 0xc000, "stmia %r8!, {%l}"},
  146.   {0xf800, 0xc800, "ldmia %r8!, {%l}"},
  147.   // Format 17
  148.   {0xff00, 0xdf00, "swi %m"},
  149.   // Format 16
  150.   {0xf000, 0xd000, "b%c %W"},
  151.   // Format 18
  152.   {0xf800, 0xe000, "b %a"},
  153.   // Format 19
  154.   {0xf800, 0xf000, "bl %A"},
  155.   {0xf800, 0xf800, "blh %Z"},
  156.   {0xff00, 0xbe00, "bkpt %O"},
  157.   // Unknown
  158.   {0x0000, 0x0000, "[ ??? ]"}
  159. };
  160.  
  161. const Opcodes armOpcodes[] = {
  162.   // Undefined
  163.   {0x0e000010, 0x06000010, "[ undefined ]"},
  164.   // Branch instructions
  165.   {0x0ff000f0, 0x01200010, "bx%c %r0"},
  166.   {0x0f000000, 0x0a000000, "b%c %o"},
  167.   {0x0f000000, 0x0b000000, "bl%c %o"},
  168.   {0x0f000000, 0x0f000000, "swi%c %q"},
  169.   // PSR transfer
  170.   {0x0fbf0fff, 0x010f0000, "mrs%c %r3, %p"},
  171.   {0x0db0f000, 0x0120f000, "msr%c %p, %i"},
  172.   // Multiply instructions
  173.   {0x0fe000f0, 0x00000090, "mul%c%s %r4, %r0, %r2"},
  174.   {0x0fe000f0, 0x00200090, "mla%c%s %r4, %r0, %r2, %r3"},
  175.   {0x0fa000f0, 0x00800090, "%umull%c%s %r3, %r4, %r0, %r2"},
  176.   {0x0fa000f0, 0x00a00090, "%umlal%c%s %r3, %r4, %r0, %r2"},
  177.   // Load/Store instructions
  178.   {0x0fb00ff0, 0x01000090, "swp%c%b %r3, %r0, [%r4]"},
  179.   {0x0fb000f0, 0x01000090, "[ ??? ]"},
  180.   {0x0c100000, 0x04000000, "str%c%b%t %r3, %a"},
  181.   {0x0c100000, 0x04100000, "ldr%c%b%t %r3, %a"},
  182.   {0x0e100090, 0x00000090, "str%c%h %r3, %a"},
  183.   {0x0e100090, 0x00100090, "ldr%c%h %r3, %a"},
  184.   {0x0e100000, 0x08000000, "stm%c%m %r4%l"},
  185.   {0x0e100000, 0x08100000, "ldm%c%m %r4%l"},
  186.   // Data processing
  187.   {0x0de00000, 0x00000000, "and%c%s %r3, %r4, %i"},
  188.   {0x0de00000, 0x00200000, "eor%c%s %r3, %r4, %i"},
  189.   {0x0de00000, 0x00400000, "sub%c%s %r3, %r4, %i"},
  190.   {0x0de00000, 0x00600000, "rsb%c%s %r3, %r4, %i"},
  191.   {0x0de00000, 0x00800000, "add%c%s %r3, %r4, %i"},
  192.   {0x0de00000, 0x00a00000, "adc%c%s %r3, %r4, %i"},
  193.   {0x0de00000, 0x00c00000, "sbc%c%s %r3, %r4, %i"},
  194.   {0x0de00000, 0x00e00000, "rsc%c%s %r3, %r4, %i"},
  195.   {0x0de00000, 0x01000000, "tst%c%s %r4, %i"},
  196.   {0x0de00000, 0x01200000, "teq%c%s %r4, %i"},
  197.   {0x0de00000, 0x01400000, "cmp%c%s %r4, %i"},
  198.   {0x0de00000, 0x01600000, "cmn%c%s %r4, %i"},
  199.   {0x0de00000, 0x01800000, "orr%c%s %r3, %r4, %i"},
  200.   {0x0de00000, 0x01a00000, "mov%c%s %r3, %i"},
  201.   {0x0de00000, 0x01c00000, "bic%c%s %r3, %r4, %i"},
  202.   {0x0de00000, 0x01e00000, "mvn%c%s %r3, %i"},
  203.   // Coprocessor operations
  204.   {0x0f000010, 0x0e000000, "cdp%c %P, %N, %r3, %R4, %R0%V"},
  205.   {0x0e100000, 0x0c000000, "stc%c%L %P, %r3, %A"},
  206.   {0x0f100010, 0x0e000010, "mcr%c %P, %N, %r3, %R4, %R0%V"},
  207.   {0x0f100010, 0x0e100010, "mrc%c %P, %N, %r3, %R4, %R0%V"},
  208.   // Unknown
  209.   {0x00000000, 0x00000000, "[ ??? ]"}
  210. };
  211.  
  212. char* addStr(char *dest, const char *src){
  213.   while (*src){
  214.     *dest++ = *src++;
  215.   }
  216.   return dest;
  217. }
  218.  
  219. char* addHex(char *dest, int siz, u32 val){
  220.   if (siz==0){
  221.     siz = 28;
  222.     while ( (((val>>siz)&15)==0) && (siz>=4) )
  223.       siz -= 4;
  224.     siz += 4;
  225.   }
  226.   while (siz>0){
  227.     siz -= 4;
  228.     *dest++ = hdig[(val>>siz)&15];
  229.   }
  230.   return dest;
  231. }
  232.  
  233. int disArm(u32 offset, char *dest, int flags){
  234.   u32 opcode = debuggerReadMemory(offset);
  235.         
  236.   const Opcodes *sp = armOpcodes;
  237.   while( sp->cval != (opcode & sp->mask) )
  238.     sp++;
  239.  
  240.   if (flags&DIS_VIEW_ADDRESS){
  241.     dest = addHex(dest, 32, offset);
  242.     *dest++ = ' ';
  243.   }
  244.   if (flags&DIS_VIEW_CODE){
  245.     dest = addHex(dest, 32, opcode);
  246.     *dest++ = ' ';
  247.   }
  248.  
  249.   char *src = sp->mnemonic;
  250.   while (*src){
  251.     if (*src!='%')
  252.       *dest++ = *src++;
  253.     else{
  254.       src++;
  255.       switch (*src){
  256.       case 'c':
  257.         dest = addStr(dest, conditions[opcode>>28]);
  258.         break;
  259.       case 'r':
  260.         dest = addStr(dest, regs[(opcode>>((*(++src)-'0')*4))&15]);
  261.         break;
  262.       case 'o':
  263.         {
  264.           *dest++ = '$';
  265.           int off = opcode&0xffffff;
  266.           if (off&0x800000)
  267.             off |= 0xff000000;
  268.           off <<= 2;
  269.           dest = addHex(dest, 32, offset+8+off);
  270.         }
  271.         break;
  272.       case 'i':
  273.         if (opcode&(1<<25)){
  274.           dest = addStr(dest, "#0x");
  275.           int imm = opcode&0xff;
  276.           int rot = (opcode&0xf00)>>7;
  277.           int val = (imm<<(32-rot))|(imm>>rot);
  278.           dest = addHex(dest, 0, val);
  279.         } else{
  280.           dest = addStr(dest, regs[opcode&0x0f]);
  281.           int shi = (opcode>>5)&3;
  282.           int sdw = (opcode>>7)&0x1f;
  283.           if ((sdw==0)&&(shi==3))
  284.             shi = 4;
  285.           if ( (sdw) || (opcode&0x10) || (shi)) {
  286.             dest = addStr(dest, ", ");
  287.             dest = addStr(dest, shifts[shi]);
  288.             if (opcode&0x10){
  289.               *dest++ = ' ';
  290.               dest = addStr(dest, regs[(opcode>>8)&15]);
  291.             } else {
  292.               if (sdw==0 && ( (shi==1) || (shi==2) ))
  293.                 sdw = 32;
  294.               if(shi != 4) {
  295.                 dest = addStr(dest, " #0x");
  296.                 dest = addHex(dest, 8, sdw);
  297.               }
  298.             }
  299.           }
  300.         }
  301.         break;
  302.       case 'p':
  303.         if (opcode&(1<<22))
  304.           dest = addStr(dest, "spsr");
  305.         else
  306.           dest = addStr(dest, "cpsr");
  307.         if(opcode & 0x00F00000) {
  308.           *dest++ = '_';
  309.           if(opcode & 0x00080000)
  310.             *dest++ = 'f';
  311.           if(opcode & 0x00040000)
  312.             *dest++ = 's';
  313.           if(opcode & 0x00020000)
  314.             *dest++ = 'x';
  315.           if(opcode & 0x00010000)
  316.             *dest++ = 'c';
  317.         }
  318.         break;
  319.       case 's':
  320.         if (opcode&(1<<20))
  321.           *dest++ = 's';
  322.         break;
  323.       case 'S':
  324.         if (opcode&(1<<22))
  325.           *dest++ = 's';
  326.         break;
  327.       case 'u':
  328.         if (opcode&(1<<22))
  329.           *dest++ = 's';
  330.         else
  331.           *dest++ = 'u';
  332.         break;
  333.       case 'b':
  334.         if (opcode&(1<<22))
  335.           *dest++ = 'b';
  336.         break;
  337.       case 'a':
  338.         if ((opcode&0x076f0000)==0x004f0000){
  339.           *dest++ = '[';
  340.           *dest++ = '$';
  341.           int adr = offset+8;
  342.           int add = (opcode&15)|((opcode>>8)&0xf0);
  343.           if (opcode&(1<<23))
  344.             adr += add;
  345.           else
  346.             adr -= add;
  347.           dest = addHex(dest, 32, adr);
  348.           *dest++ = ']';
  349.           dest = addStr(dest, " (=");
  350.           *dest++ = '$';
  351.           dest = addHex(dest ,32, debuggerReadMemory(adr));
  352.           *dest++=')';
  353.         }
  354.         if ((opcode&0x072f0000)==0x050f0000){
  355.           *dest++ = '[';
  356.           *dest++ = '$';
  357.           int adr = offset+8;
  358.           if (opcode&(1<<23))
  359.             adr += opcode&0xfff;
  360.           else
  361.             adr -= opcode&0xfff;
  362.           dest = addHex(dest, 32, adr);
  363.           *dest++ = ']';
  364.           dest = addStr(dest, " (=");
  365.           *dest++ = '$';
  366.           dest = addHex(dest ,32, debuggerReadMemory(adr));
  367.           *dest++=')';
  368.         } else {
  369.           int reg = (opcode>>16)&15;
  370.           *dest++ = '[';
  371.           dest = addStr(dest, regs[reg]);
  372.           if (!(opcode&(1<<24)))
  373.             *dest++ = ']';
  374.           if ( ((opcode&(1<<25))&&(opcode&(1<<26))) || (!(opcode&(1<<22))&&!(opcode&(1<<26))) ){
  375.             dest = addStr(dest, ", ");
  376.             if (!(opcode&(1<<23)))
  377.               *dest++ = '-';
  378.             dest = addStr(dest, regs[opcode&0x0f]);
  379.             int shi = (opcode>>5)&3;
  380.             if (opcode&(1<<26)){
  381.               if ( ((opcode>>7)&0x1f) || (opcode&0x10) || (shi==1) || (shi==2)){
  382.                 dest = addStr(dest, ", ");
  383.                 dest = addStr(dest, shifts[shi]);
  384.                 if (opcode&0x10){
  385.                   *dest++ = ' ';
  386.                   dest = addStr(dest, regs[(opcode>>8)&15]);
  387.                 } else {
  388.                   int sdw = (opcode>>7)&0x1f;
  389.                   if (sdw==0 && ( (shi==1) || (shi==2) ))
  390.                     sdw = 32;
  391.                   dest = addStr(dest, " #0x");
  392.                   dest = addHex(dest, 8, sdw);
  393.                 }
  394.               }
  395.             }
  396.           } else {
  397.             int off;
  398.             if (opcode&(1<<26))
  399.               off = opcode&0xfff;
  400.             else
  401.               off = (opcode&15)|((opcode>>4)&0xf0);
  402.             if (off){
  403.               dest = addStr(dest, ", ");
  404.               if (!(opcode&(1<<23)))
  405.                 *dest++ = '-';
  406.               dest = addStr(dest, "#0x");
  407.               dest = addHex(dest, 0, off);
  408.             }
  409.           }
  410.           if (opcode&(1<<24)){
  411.             *dest++ = ']';
  412.             if (opcode&(1<<21))
  413.               *dest++ = '!';
  414.           }
  415.         }
  416.         break;
  417.       case 't':
  418.         if ((opcode&0x01200000)==0x01200000)
  419.           *dest++ = 't';
  420.         break;
  421.       case 'h':
  422.         if (opcode&(1<<6))
  423.           *dest++ = 's';
  424.         if (opcode&(1<<5))
  425.           *dest++ = 'h';
  426.         else
  427.           *dest++ = 'b';
  428.         break;
  429.       case 'm':
  430.         if (((opcode>>16)&15)==13) {
  431.           if(opcode & 0x00100000)
  432.             dest = addStr(dest, armMultLoadStore[8+((opcode>>23)&3)]);
  433.           else
  434.             dest = addStr(dest, armMultLoadStore[4+((opcode>>23)&3)]);      
  435.         } else
  436.           dest = addStr(dest, armMultLoadStore[(opcode>>23)&3]);
  437.         break;
  438.       case 'l':
  439.         if (opcode&(1<<21))
  440.           *dest++ = '!';
  441.         dest = addStr(dest, ", {");
  442.         {
  443.           int rlst = opcode&0xffff;
  444.           int msk = 0;
  445.           int not_first = 0;
  446.           while (msk<16){
  447.             if (rlst&(1<<msk)){
  448.               int fr = msk;
  449.               while (rlst&(1<<msk))
  450.                 msk++;
  451.               int to = msk-1;
  452.               if (not_first)
  453.                 //dest = addStr(dest, ", ");
  454.                 *dest++ = ',';
  455.               dest = addStr(dest, regs[fr]);
  456.               if (fr!=to){
  457.                 if (fr==to-1)
  458.                   //dest = addStr(", ");
  459.                   *dest++ = ',';
  460.                 else
  461.                   *dest++ = '-';
  462.                 dest = addStr(dest, regs[to]);
  463.               }
  464.               not_first = 1;
  465.             } else
  466.               msk++;
  467.           }
  468.           *dest++ = '}';
  469.           if (opcode&(1<<22))
  470.             *dest++ = '^';
  471.         }
  472.         break;
  473.       case 'q':
  474.         *dest++ = '$';
  475.         dest = addHex(dest, 24, opcode&0xffffff);
  476.         break;
  477.       case 'P':
  478.         *dest++ = 'p';
  479.         dest = addStr(dest, decVals[(opcode>>8)&15]);
  480.         break;
  481.       case 'N':
  482.         if (opcode&0x10)
  483.           dest = addStr(dest, decVals[(opcode>>21)&7]);
  484.         else
  485.           dest = addStr(dest, decVals[(opcode>>20)&15]);
  486.         break;
  487.       case 'R':
  488.         {
  489.           src++;
  490.           int reg = 4*(*src-'0');
  491.           *dest++ = 'c';
  492.           dest = addStr(dest, decVals[(opcode>>reg)&15]);
  493.         }
  494.         break;
  495.       case 'V':
  496.         {
  497.           int val = (opcode>>5)&7;
  498.           if (val){
  499.             dest = addStr(dest, ", ");
  500.             dest = addStr(dest, decVals[val]);
  501.           }
  502.         }
  503.         break;
  504.       case 'L':
  505.         if (opcode&(1<<22))
  506.           *dest++ = 'l';
  507.         break;
  508.       case 'A':
  509.         if ((opcode&0x012f0000)==0x010f0000){
  510.           int adr = offset+8;
  511.           int add = (opcode&0xff)<<2;
  512.           if (opcode&(1<<23))
  513.             adr += add;
  514.           else
  515.             adr -= add;
  516.           *dest++ = '$';
  517.           addHex(dest, 32, adr);
  518.         } else {
  519.           *dest++ = '[';
  520.           dest = addStr(dest, regs[(opcode>>16)&15]);
  521.           if (!(opcode&(1<<24)))
  522.             *dest++ = ']';
  523.           int off = (opcode&0xff)<<2;
  524.           if (off){
  525.             dest = addStr(dest, ", ");
  526.             if (!(opcode&(1<<23)))
  527.               *dest++ = '-';
  528.             dest = addStr(dest, "#0x");
  529.             dest = addHex(dest, 0, off);
  530.           }
  531.           if (opcode&(1<<24)){
  532.             *dest++ = ']';
  533.             if (opcode&(1<<21))
  534.               *dest++ = '!';
  535.           }
  536.         }
  537.         break;
  538.       }
  539.       src++;
  540.     }
  541.   }
  542.   *dest++ = 0;
  543.         
  544.   return 4;
  545. }
  546.  
  547. int disThumb(u32 offset, char *dest, int flags){
  548.   u32 opcode = debuggerReadHalfWord(offset);
  549.         
  550.   const Opcodes *sp = thumbOpcodes;
  551.   int ret = 2;
  552.   while( sp->cval != (opcode & sp->mask) )
  553.     sp++;
  554.         
  555.   if (flags&DIS_VIEW_ADDRESS){
  556.     dest = addHex(dest, 32, offset);
  557.     *dest++ = ' ';
  558.   }
  559.   if (flags&DIS_VIEW_CODE){
  560.     dest = addHex(dest, 16, opcode);
  561.     *dest++ = ' ';
  562.   }
  563.         
  564.   char *src = sp->mnemonic;
  565.   while (*src){
  566.     if (*src!='%')
  567.       *dest++ = *src++;
  568.     else {
  569.       src++;
  570.       switch (*src){
  571.       case 'r':
  572.         src++;
  573.         dest = addStr(dest, regs[(opcode>>(*src-'0'))&7]);
  574.         break;
  575.       case 'o':
  576.         dest = addStr(dest, "#0x");
  577.         {
  578.           int val = (opcode>>6)&0x1f;
  579.           dest = addHex(dest, 8, val);
  580.         }
  581.         break;
  582.       case 'p':
  583.         dest = addStr(dest, "#0x");
  584.         {
  585.           int val = (opcode>>6)&0x1f;
  586.           if (!(opcode&(1<<12)))
  587.             val <<= 2;
  588.           dest = addHex(dest, 0, val);
  589.         }
  590.         break;
  591.       case 'e':
  592.         dest = addStr(dest, "#0x");
  593.         dest = addHex(dest, 0, ((opcode>>6)&0x1f)<<1);
  594.         break;
  595.       case 'i':
  596.         dest = addStr(dest, "#0x");
  597.         dest = addHex(dest, 0, (opcode>>6)&7);
  598.         break;
  599.       case 'h':
  600.         {
  601.           src++;
  602.           int reg = (opcode>>(*src-'0'))&7;
  603.           src++;
  604.           if (opcode&(1<<(*src-'0')))
  605.             reg += 8;
  606.           dest = addStr(dest, regs[reg]);
  607.         }
  608.         break;
  609.       case 'O':
  610.         dest = addStr(dest, "#0x");
  611.         dest = addHex(dest, 0, (opcode&0xff));
  612.         break;
  613.       case 'I':
  614.         *dest++ = '$';
  615.         dest = addHex(dest, 32, (offset&0xfffffffc)+4+((opcode&0xff)<<2));
  616.         break;
  617.       case 'J':
  618.         {
  619.           u32 value = debuggerReadMemory((offset&0xfffffffc)+4+
  620.                                          ((opcode & 0xff)<<2));
  621.           *dest++ = '$';
  622.           dest = addHex(dest, 32, value);
  623.           char *s = elfGetAddressSymbol(value);
  624.           if(*s) {
  625.             *dest++ = ' ';
  626.             dest = addStr(dest, s);
  627.           }
  628.         }
  629.         break;
  630.       case 'K':
  631.         {
  632.           u32 value = (offset&0xfffffffc)+4+((opcode & 0xff)<<2);
  633.           *dest++ = '$';
  634.           dest = addHex(dest, 32, value);
  635.           char *s = elfGetAddressSymbol(value);
  636.           if(*s) {
  637.             *dest++ = ' ';
  638.             dest = addStr(dest, s);
  639.           }          
  640.         }
  641.         break;
  642.       case 'b':
  643.         if (opcode&(1<<10))
  644.           *dest++ = 'b';
  645.         break;
  646.       case 'B':
  647.         if (opcode&(1<<12))
  648.           *dest++ = 'b';
  649.         break;
  650.       case 'w':
  651.         dest = addStr(dest, "#0x");
  652.         dest = addHex(dest, 0, (opcode&0xff)<<2);
  653.         break;
  654.       case 'W':
  655.         *dest++ = '$';
  656.         {
  657.           int add = opcode&0xff;
  658.           if (add&0x80)
  659.             add |= 0xffffff00;
  660.           dest = addHex(dest, 32, (offset&0xfffffffe)+4+(add<<1));
  661.         }
  662.         break;
  663.       case 'c':
  664.         dest = addStr(dest, conditions[(opcode>>8)&15]);
  665.         break;
  666.       case 's':
  667.         if (opcode&(1<<7))
  668.           *dest++ = '-';
  669.         dest = addStr(dest, "#0x");
  670.         dest = addHex(dest, 0, (opcode&0x7f)<<2);
  671.         break;
  672.       case 'l':
  673.         {
  674.           int rlst = opcode&0xff;
  675.           int msk = 0;
  676.           int not_first = 0;
  677.           while (msk<8){
  678.             if (rlst&(1<<msk)){
  679.               int fr = msk;
  680.               while (rlst&(1<<msk))
  681.                 msk++;
  682.               int to = msk-1;
  683.               if (not_first)
  684.                 *dest++ = ',';
  685.               dest = addStr(dest, regs[fr]);
  686.               if (fr!=to){
  687.                 if (fr==to-1)
  688.                   *dest++ = ',';
  689.                 else
  690.                   *dest++ = '-';
  691.                 dest = addStr(dest, regs[to]);
  692.               }
  693.               not_first = 1;
  694.             } else
  695.               msk++;
  696.           }
  697.         }
  698.         break;
  699.       case 'm':
  700.         *dest++ = '$';
  701.         dest = addHex(dest, 8, opcode&0xff);
  702.         break;
  703.       case 'Z':
  704.         *dest++ = '$';
  705.         dest = addHex(dest, 16, (opcode&0x7ff)<<1);
  706.         break;
  707.       case 'a':
  708.         *dest++ = '$';
  709.         {
  710.           int add = opcode&0x07ff;
  711.           if (add&0x400)
  712.             add |= 0xfffff800;
  713.           add <<= 1;
  714.           dest = addHex(dest, 32, offset+4+add);
  715.         }
  716.         break;
  717.       case 'A':
  718.         {
  719.           int nopcode = debuggerReadHalfWord(offset+2);
  720.           int add = opcode&0x7ff;
  721.           if (add&0x400)
  722.             add |= 0xfff800;
  723.           add = (add<<12)|((nopcode&0x7ff)<<1);
  724.           *dest++ = '$';
  725.           dest = addHex(dest,32, offset+4+add);
  726.           char *s = elfGetAddressSymbol(offset+4+add);
  727.           if(*s) {
  728.             *dest++ = ' ';
  729.             *dest++ = '(';
  730.             dest = addStr(dest, s);
  731.             *dest++ = ')';
  732.           }
  733.           ret = 4;
  734.         }
  735.         break;
  736.       }
  737.       src++;
  738.     }
  739.   }
  740.   *dest++ = 0;
  741.   return ret;
  742. }
  743.