/*  Run function for the micromips simulator

    Copyright (C) 2005-2021 Free Software Foundation, Inc.
    Contributed by Imagination Technologies, Ltd.
    Written by Andrew Bennett <andrew.bennett@imgtec.com>.

    This file is part of the MIPS sim.

    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 "sim-main.h"
#include "micromips16_idecode.h"
#include "micromips32_idecode.h"
#include "micromips_m32_idecode.h"
#include "bfd.h"
#include "sim-engine.h"

/* These definitions come from the *_support.h files generated by igen and are
   required because they are used in some of the macros in the code below.
   Unfortunately we can not just blindly include the *_support.h files to get
   these definitions because some of the defines in these files are specific
   for a particular configuration of the simulator for example instruction word
   size is 16 bits for micromips16 and 32 bits for micromips32.  This means we
   could break future code changes by doing this, so a safer approach is to just
   extract the defines that we need to get this file to compile.  */
#define SD sd
#define CPU cpu

address_word
micromips_instruction_decode (SIM_DESC sd, sim_cpu * cpu,
			      address_word cia,
			      int instruction_size)
{
  if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_ANY)
    {
      micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia);
      if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0
	  && MICROMIPS_MINOR_OPCODE (instruction_0) < 4)
	return micromips16_idecode_issue (sd, instruction_0, cia);
      else
	{
	  micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia);
	  return micromips32_idecode_issue (sd, instruction_0, cia);
	}
    }
  else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_16)
    {
      micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia);
      if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0
	  && MICROMIPS_MINOR_OPCODE (instruction_0) < 4)
	return micromips16_idecode_issue (sd, instruction_0, cia);
      else
	sim_engine_abort (sd, cpu, cia,
			  "Invalid 16 bit micromips instruction");
    }
  else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_32)
    {
      micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia);
      return micromips32_idecode_issue (sd, instruction_0, cia);
    }
  else
    return NULL_CIA;
}

void
sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus,
		int signal)
{
  struct mips_sim_state *state = MIPS_SIM_STATE (sd);
  micromips_m32_instruction_word instruction_0;
  sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr);
  micromips32_instruction_address cia = CPU_PC_GET (cpu);
  state->isa_mode = ISA_MODE_MIPS32;

  while (1)
    {
      micromips32_instruction_address nia;

      /* Allow us to switch back from MIPS32 to microMIPS
	 This covers two cases:
	 1. Setting the correct isa mode based on the start address
	 from the elf header.
	 2. Setting the correct isa mode after a MIPS32 jump or branch
	 instruction.  */
      if ((state->isa_mode == ISA_MODE_MIPS32)
	  && ((cia & 0x1) == ISA_MODE_MICROMIPS))
	{
	  state->isa_mode = ISA_MODE_MICROMIPS;
	  cia = cia & ~0x1;
	}

#if defined (ENGINE_ISSUE_PREFIX_HOOK)
      ENGINE_ISSUE_PREFIX_HOOK ();
#endif
      switch (state->isa_mode)
	{
	case ISA_MODE_MICROMIPS:
	  nia =
	    micromips_instruction_decode (sd, cpu, cia,
					  MICROMIPS_DELAYSLOT_SIZE_ANY);
	  break;
	case ISA_MODE_MIPS32:
	  instruction_0 = IMEM32 (cia);
	  nia = micromips_m32_idecode_issue (sd, instruction_0, cia);
	  break;
	default:
	  nia = NULL_CIA;
	}

#if defined (ENGINE_ISSUE_POSTFIX_HOOK)
      ENGINE_ISSUE_POSTFIX_HOOK ();
#endif

      /* Update the instruction address */
      cia = nia;

      /* process any events */
      if (sim_events_tick (sd))
	{
	  CPU_PC_SET (cpu, cia);
	  sim_events_process (sd);
	  cia = CPU_PC_GET (cpu);
	}
    }
}
