// dsm-ppc.cc -- disassemble PowerPC instructions from memory	-*- C++ -*-
// 
// @copyright@
// 
// Author: Ian.Piumarta@inria.fr
// 
// Last edited: 2000-10-17 16:57:44 by piumarta on emilia.rd.wdi.disney.com

// Note: requires libbfd (along with its header files), libopcode.a
//	 (from GNU binutils) someplace where the linker can find it,
//	 and a snarfed copy of "dis-asm.h" from the binutils/include
//	 directory.  (This header file is included in the VPU
//	 distribution, to make your life just that teeny bit less
//	 tedious.  [You're welcome.])


#include <stdio.h>

#ifdef DISASM

extern "C"
{
# include <bfd.h>
# include "dis-asm.h"
};


static struct disassemble_info info;
static int initialised= 0;


static enum bfd_architecture bfd_get_arch(bfd *abfd)
{
  return bfd_arch_powerpc;    /* PowerPC */
}

static bfd_vma bfd_getb32(const unsigned char *addr)
{
  return *(bfd_vma *)addr;
}

static bfd_vma bfd_getl32(const unsigned char *addr)
{
  abort();	// this should never be called
  return 0;
}

// pretend to snarf bytes from a bfd, but really
// read them from the process address space

static int my_read_memory_func(bfd_vma memaddr, bfd_byte *buffer, int n,
			       struct disassemble_info *dinfo)
{
  bfd_byte *ptr= (bfd_byte *)memaddr;
  while (n--)
    *buffer++= *ptr++;
  return 0;
}

// this is the only function exported from this file

int disassemble(void *addr, FILE *stream= stdout)
{
  if (!initialised)
    {
      INIT_DISASSEMBLE_INFO(info, stream, fprintf);
      info.read_memory_func= my_read_memory_func;
    }
  info.stream= stream;
  return print_insn_big_powerpc((bfd_vma)addr, &info);
}

#else // !DISASM

int disassemble(void *addr, FILE *stream= stdout)
{
  return 0;
}

#endif // !DISASM

#if 0

// tester...

int main()
{
  // should print something like:	stwu	r1, -16(r1)
  disassemble(main);
  printf("\n");
  return 0;
}

#endif
