blob: 5f8d8517c551e50a32f01c960d6c26644cb7c988 [file] [log] [blame]
//
// disass.c - disassembly routines for Xtensa
//
// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/disass.c#1 $
// Copyright (c) 2004-2013 Tensilica Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <xtensa/hal.h>
#include <xtensa/config/core.h>
#ifdef XCHAL_OP0_FORMAT_LENGTHS
extern const unsigned char Xthal_op0_format_lengths[16];
#endif
extern const unsigned char Xthal_byte0_format_lengths[256];
#if defined(__SPLIT__op0_format_lengths)
/* Instruction length in bytes as function of its op0 field (first nibble): */
#ifdef XCHAL_OP0_FORMAT_LENGTHS
const unsigned char Xthal_op0_format_lengths[16] = {
XCHAL_OP0_FORMAT_LENGTHS
};
#endif
#elif defined(__SPLIT__byte0_format_lengths)
/* Instruction length in bytes as function of its first byte: */
const unsigned char Xthal_byte0_format_lengths[256] = {
XCHAL_BYTE0_FORMAT_LENGTHS
};
#elif defined(__SPLIT__disassemble_size)
//
// Disassembly is currently not supported in xtensa hal.
//
int xthal_disassemble_size( unsigned char *instr_buf )
{
#ifdef XCHAL_OP0_FORMAT_LENGTHS
/* Extract op0 field of instruction (first nibble used for decoding): */
# if XCHAL_HAVE_BE
int op0 = ((*instr_buf >> 4) & 0xF);
# else
int op0 = (*instr_buf & 0xF);
# endif
/*return (op0 & 8) ? 2 : 3;*/ /* simple case only works consistently on older hardware */
return Xthal_op0_format_lengths[op0];
#else
return Xthal_byte0_format_lengths[*instr_buf];
#endif
}
#elif defined(__SPLIT__disassemble)
/*
* Note: we make sure to avoid the use of library functions,
* to minimize dependencies.
*/
int xthal_disassemble(
unsigned char *instr_buffer, /* the address of the instructions */
void *tgt_address, /* where the instruction is to be */
char *buffer, /* where the result goes */
unsigned buflen, /* size of buffer */
unsigned options /* what to display */
)
{
#define OUTC(c) do{ if( p < endp ) *p = c; p++; }while(0)
int i, n;
char *p = buffer, *endp = buffer + buflen - 1;
/*static char *ret = " decoding not supported";*/
static const char _hexc[16] = "0123456789ABCDEF";
n = xthal_disassemble_size( instr_buffer );
if( options & XTHAL_DISASM_OPT_ADDR ) {
unsigned addr = (unsigned)tgt_address;
for( i = 0; i < 8; i++ ) {
OUTC( _hexc[(addr >> 28) & 0xF] );
addr <<= 4;
}
}
if( options & XTHAL_DISASM_OPT_OPHEX ) {
if( p > buffer )
OUTC( ' ' );
for( i = 0; i < 3; i++ ) {
if( i < n ) {
OUTC( _hexc[(*instr_buffer >> 4) & 0xF] );
OUTC( _hexc[*instr_buffer++ & 0xF] );
} else {
OUTC( ' ' );
OUTC( ' ' );
}
OUTC( ' ' );
}
}
if( options & XTHAL_DISASM_OPT_OPCODE ) {
if( p > buffer )
OUTC( ' ' );
OUTC( '?' );
OUTC( '?' );
OUTC( '?' );
OUTC( ' ' );
OUTC( ' ' );
OUTC( ' ' );
OUTC( ' ' );
}
if( options & XTHAL_DISASM_OPT_PARMS ) {
if( p > buffer )
OUTC( ' ' );
OUTC( '?' );
OUTC( '?' );
OUTC( '?' );
}
if( p < endp )
*p = 0;
else if( buflen > 0 )
*endp = 0;
return p - buffer; /* return length needed, even if longer than buflen */
}
#undef OUTC
#endif /*split*/