/* load.c --- loading object files into the RL78 simulator.

   Copyright (C) 2005-2023 Free Software Foundation, Inc.
   Contributed by Red Hat, Inc.

   This file is part of the GNU simulators.

   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/>.
*/

/* This must come before any other includes.  */
#include "defs.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libiberty.h"
#include "bfd.h"
#include "bfd/elf-bfd.h"
#include "elf/rl78.h"
#include "cpu.h"
#include "mem.h"
#include "load.h"
#include "elf/internal.h"
#include "elf/common.h"

/* Helper function for invoking a GDB-specified printf.  */
static void
xprintf (host_callback *callback, const char *fmt, ...)
{
  va_list ap;

  va_start (ap, fmt);

  (*callback->vprintf_filtered) (callback, fmt, ap);

  va_end (ap);
}

/* Given a file offset, look up the section name.  */
static const char *
find_section_name_by_offset (bfd *abfd, file_ptr filepos)
{
  asection *s;

  for (s = abfd->sections; s; s = s->next)
    if (s->filepos == filepos)
      return bfd_section_name (s);

  return "(unknown)";
}

void
rl78_load (bfd *prog, host_callback *callbacks, const char * const simname)
{
  Elf_Internal_Phdr * phdrs;
  long sizeof_phdrs;
  int num_headers;
  int i;
  int max_rom = 0;

  init_cpu ();

  /* Note we load by ELF program header not by BFD sections.
     This is because BFD sections get their information from
     the ELF section structure, which only includes a VMA value
     and not an LMA value.  */
  sizeof_phdrs = bfd_get_elf_phdr_upper_bound (prog);
  if (sizeof_phdrs == 0)
    {
      fprintf (stderr, "%s: Failed to get size of program headers\n", simname);
      return;
    }
  phdrs = xmalloc (sizeof_phdrs);

  num_headers = bfd_get_elf_phdrs (prog, phdrs);
  if (num_headers < 1)
    {
      fprintf (stderr, "%s: Failed to read program headers\n", simname);
      return;
    }

  switch (elf_elfheader (prog)->e_flags & E_FLAG_RL78_CPU_MASK)
    {
    case E_FLAG_RL78_G10:
      rl78_g10_mode = 1;
      g13_multiply = 0;
      g14_multiply = 0;
      mem_set_mirror (0, 0xf8000, 4096);
      break;
    case E_FLAG_RL78_G13:
      rl78_g10_mode = 0;
      g13_multiply = 1;
      g14_multiply = 0;
      break;
    case E_FLAG_RL78_G14:
      rl78_g10_mode = 0;
      g13_multiply = 0;
      g14_multiply = 1;
      break;
    default:
      /* Keep whatever was manually specified.  */
      break;
    }

  for (i = 0; i < num_headers; i++)
    {
      Elf_Internal_Phdr * p = phdrs + i;
      char *buf;
      bfd_vma size;
      bfd_vma base;
      file_ptr offset;

      size = p->p_filesz;
      if (size <= 0)
	continue;

      base = p->p_paddr;
      if (verbose > 1)
	fprintf (stderr,
		 "[load segment: lma=%08" PRIx64 " vma=%08" PRIx64 " "
		 "size=%08" PRIx64 "]\n",
		 (uint64_t) base, (uint64_t) p->p_vaddr, (uint64_t) size);
      if (callbacks)
	xprintf (callbacks,
		 "Loading section %s, size %#" PRIx64 " "
		 "lma %08" PRIx64 " vma %08" PRIx64 "\n",
		 find_section_name_by_offset (prog, p->p_offset),
		 (uint64_t) size, (uint64_t) base, (uint64_t) p->p_vaddr);

      buf = xmalloc (size);

      offset = p->p_offset;
      if (bfd_seek (prog, offset, SEEK_SET) != 0)
	{
	  fprintf (stderr, "%s, Failed to seek to offset %lx\n", simname, (long) offset);
	  continue;
	}

      if (bfd_read (buf, size, prog) != size)
	{
	  fprintf (stderr, "%s: Failed to read %" PRIx64 " bytes\n",
		   simname, (uint64_t) size);
	  continue;
	}

      if (base > 0xeffff || base + size > 0xeffff)
	{
	  fprintf (stderr,
		   "%s, Can't load image to RAM/SFR space: 0x%" PRIx64 " "
		   "- 0x%" PRIx64 "\n",
		   simname, (uint64_t) base, (uint64_t) (base + size));
	  continue;
	}
      if (max_rom < base + size)
	max_rom = base + size;

      mem_put_blk (base, buf, size);
      free (buf);
    }

  free (phdrs);

  mem_rom_size (max_rom);

  pc = prog->start_address;

  if (strcmp (bfd_get_target (prog), "srec") == 0
      || pc == 0)
    {
      pc = mem_get_hi (0);
    }

  if (verbose > 1)
    fprintf (stderr, "[start pc=%08x]\n", (unsigned int) pc);
}
