/* Self tests for disassembler for GDB, the GNU debugger.

   Copyright (C) 2017-2018 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "disasm.h"

#if GDB_SELF_TEST
#include "selftest.h"
#include "selftest-arch.h"

namespace selftests {

/* Test disassembly of one instruction.  */

static void
print_one_insn_test (struct gdbarch *gdbarch)
{
  size_t len = 0;
  const gdb_byte *insn = NULL;

  switch (gdbarch_bfd_arch_info (gdbarch)->arch)
    {
    case bfd_arch_bfin:
      /* M3.L = 0xe117 */
      static const gdb_byte bfin_insn[] = {0x17, 0xe1, 0xff, 0xff};

      insn = bfin_insn;
      len = sizeof (bfin_insn);
      break;
    case bfd_arch_arm:
      /* mov     r0, #0 */
      static const gdb_byte arm_insn[] = {0x0, 0x0, 0xa0, 0xe3};

      insn = arm_insn;
      len = sizeof (arm_insn);
      break;
    case bfd_arch_ia64:
    case bfd_arch_mep:
    case bfd_arch_mips:
    case bfd_arch_tic6x:
    case bfd_arch_xtensa:
      return;
    case bfd_arch_s390:
      /* nopr %r7 */
      static const gdb_byte s390_insn[] = {0x07, 0x07};

      insn = s390_insn;
      len = sizeof (s390_insn);
      break;
    case bfd_arch_xstormy16:
      /* nop */
      static const gdb_byte xstormy16_insn[] = {0x0, 0x0};

      insn = xstormy16_insn;
      len = sizeof (xstormy16_insn);
      break;
    case bfd_arch_arc:
      /* PR 21003 */
      if (gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_arc_arc601)
	return;
      /* fall through */
    case bfd_arch_nios2:
    case bfd_arch_score:
    case bfd_arch_riscv:
      /* nios2, riscv, and score need to know the current instruction
	 to select breakpoint instruction.  Give the breakpoint
	 instruction kind explicitly.  */
      {
	int bplen;
	insn = gdbarch_sw_breakpoint_from_kind (gdbarch, 4, &bplen);
	len = bplen;
      }
      break;
    default:
      {
	/* Test disassemble breakpoint instruction.  */
	CORE_ADDR pc = 0;
	int kind = gdbarch_breakpoint_kind_from_pc (gdbarch, &pc);
	int bplen;

	insn = gdbarch_sw_breakpoint_from_kind (gdbarch, kind, &bplen);
	len = bplen;

	break;
      }
    }
  SELF_CHECK (len > 0);

  /* Test gdb_disassembler for a given gdbarch by reading data from a
     pre-allocated buffer.  If you want to see the disassembled
     instruction printed to gdb_stdout, set verbose to true.  */
  static const bool verbose = false;

  class gdb_disassembler_test : public gdb_disassembler
  {
  public:

    explicit gdb_disassembler_test (struct gdbarch *gdbarch,
				    const gdb_byte *insn,
				    size_t len)
      : gdb_disassembler (gdbarch,
			  (verbose ? gdb_stdout : &null_stream),
			  gdb_disassembler_test::read_memory),
	m_insn (insn), m_len (len)
    {
    }

    int
    print_insn (CORE_ADDR memaddr)
    {
      if (verbose)
	{
	  fprintf_unfiltered (stream (), "%s ",
			      gdbarch_bfd_arch_info (arch ())->arch_name);
	}

      int len = gdb_disassembler::print_insn (memaddr);

      if (verbose)
	fprintf_unfiltered (stream (), "\n");

      return len;
    }

  private:
    /* A buffer contain one instruction.  */
    const gdb_byte *m_insn;

    /* Length of the buffer.  */
    size_t m_len;

    static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
			    unsigned int len, struct disassemble_info *info)
    {
      gdb_disassembler_test *self
	= static_cast<gdb_disassembler_test *>(info->application_data);

      /* The disassembler in opcodes may read more data than one
	 instruction.  Supply infinite consecutive copies
	 of the same instruction.  */
      for (size_t i = 0; i < len; i++)
	myaddr[i] = self->m_insn[(memaddr + i) % self->m_len];

      return 0;
    }
  };

  gdb_disassembler_test di (gdbarch, insn, len);

  SELF_CHECK (di.print_insn (0) == len);
}

/* Test disassembly on memory error.  */

static void
memory_error_test (struct gdbarch *gdbarch)
{
  class gdb_disassembler_test : public gdb_disassembler
  {
  public:
    gdb_disassembler_test (struct gdbarch *gdbarch)
      : gdb_disassembler (gdbarch, &null_stream,
			  gdb_disassembler_test::read_memory)
    {
    }

    static int read_memory (bfd_vma memaddr, gdb_byte *myaddr,
			    unsigned int len,
			    struct disassemble_info *info)
    {
      /* Always return an error.  */
      return -1;
    }
  };

  gdb_disassembler_test di (gdbarch);
  bool saw_memory_error = false;

  TRY
    {
      di.print_insn (0);
    }
  CATCH (ex, RETURN_MASK_ERROR)
    {
      if (ex.error == MEMORY_ERROR)
	saw_memory_error = true;
    }
  END_CATCH

  /* Expect MEMORY_ERROR.  */
  SELF_CHECK (saw_memory_error);
}

} // namespace selftests
#endif /* GDB_SELF_TEST */

void
_initialize_disasm_selftests (void)
{
#if GDB_SELF_TEST
  selftests::register_test_foreach_arch ("print_one_insn",
					 selftests::print_one_insn_test);
  selftests::register_test_foreach_arch ("memory_error",
					 selftests::memory_error_test);
#endif
}
