1 //
2 // disass.c - disassembly routines for Xtensa
3 //
4 // $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/disass.c#1 $
5
6 // Copyright (c) 2004-2013 Tensilica Inc.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included
17 // in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 #include <xtensa/hal.h>
28 #include <xtensa/config/core.h>
29
30 #ifdef XCHAL_OP0_FORMAT_LENGTHS
31 extern const unsigned char Xthal_op0_format_lengths[16];
32 #endif
33 extern const unsigned char Xthal_byte0_format_lengths[256];
34
35
36
37 /* Instruction length in bytes as function of its op0 field (first nibble): */
38 #ifdef XCHAL_OP0_FORMAT_LENGTHS
39 const unsigned char Xthal_op0_format_lengths[16] = {
40 XCHAL_OP0_FORMAT_LENGTHS
41 };
42 #endif
43
44
45
46 /* Instruction length in bytes as function of its first byte: */
47 const unsigned char Xthal_byte0_format_lengths[256] = {
48 XCHAL_BYTE0_FORMAT_LENGTHS
49 };
50
51
52
53 //
54 // Disassembly is currently not supported in xtensa hal.
55 //
56
xthal_disassemble_size(unsigned char * instr_buf)57 int xthal_disassemble_size( unsigned char *instr_buf )
58 {
59 #ifdef XCHAL_OP0_FORMAT_LENGTHS
60 /* Extract op0 field of instruction (first nibble used for decoding): */
61 # if XCHAL_HAVE_BE
62 int op0 = ((*instr_buf >> 4) & 0xF);
63 # else
64 int op0 = (*instr_buf & 0xF);
65 # endif
66 /*return (op0 & 8) ? 2 : 3;*/ /* simple case only works consistently on older hardware */
67 return Xthal_op0_format_lengths[op0];
68 #else
69 return Xthal_byte0_format_lengths[*instr_buf];
70 #endif
71 }
72
73
74
75 /*
76 * Note: we make sure to avoid the use of library functions,
77 * to minimize dependencies.
78 */
xthal_disassemble(unsigned char * instr_buffer,void * tgt_address,char * buffer,unsigned buflen,unsigned options)79 int xthal_disassemble(
80 unsigned char *instr_buffer, /* the address of the instructions */
81 void *tgt_address, /* where the instruction is to be */
82 char *buffer, /* where the result goes */
83 unsigned buflen, /* size of buffer */
84 unsigned options /* what to display */
85 )
86 {
87 #define OUTC(c) do{ if( p < endp ) *p = c; p++; }while(0)
88 int i, n;
89 char *p = buffer, *endp = buffer + buflen - 1;
90 /*static char *ret = " decoding not supported";*/
91 static const char _hexc[16] = "0123456789ABCDEF";
92
93 n = xthal_disassemble_size( instr_buffer );
94
95 if( options & XTHAL_DISASM_OPT_ADDR ) {
96 unsigned addr = (unsigned)tgt_address;
97 for( i = 0; i < 8; i++ ) {
98 OUTC( _hexc[(addr >> 28) & 0xF] );
99 addr <<= 4;
100 }
101 }
102
103 if( options & XTHAL_DISASM_OPT_OPHEX ) {
104 if( p > buffer )
105 OUTC( ' ' );
106 for( i = 0; i < 3; i++ ) {
107 if( i < n ) {
108 OUTC( _hexc[(*instr_buffer >> 4) & 0xF] );
109 OUTC( _hexc[*instr_buffer++ & 0xF] );
110 } else {
111 OUTC( ' ' );
112 OUTC( ' ' );
113 }
114 OUTC( ' ' );
115 }
116 }
117
118 if( options & XTHAL_DISASM_OPT_OPCODE ) {
119 if( p > buffer )
120 OUTC( ' ' );
121 OUTC( '?' );
122 OUTC( '?' );
123 OUTC( '?' );
124 OUTC( ' ' );
125 OUTC( ' ' );
126 OUTC( ' ' );
127 OUTC( ' ' );
128 }
129
130 if( options & XTHAL_DISASM_OPT_PARMS ) {
131 if( p > buffer )
132 OUTC( ' ' );
133 OUTC( '?' );
134 OUTC( '?' );
135 OUTC( '?' );
136 }
137
138 if( p < endp )
139 *p = 0;
140 else if( buflen > 0 )
141 *endp = 0;
142
143 return p - buffer; /* return length needed, even if longer than buflen */
144 }
145
146 #undef OUTC
147
148
149