# Simulator main loop for m32r. -*- C -*-
#
# Copyright (C) 1996-2021 Free Software Foundation, 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/>.

# Syntax:
# /bin/sh mainloop.in command
#
# Command is one of:
#
# init
# support
# extract-{simple,scache,pbb}
# {full,fast}-exec-{simple,scache,pbb}
#
# A target need only provide a "full" version of one of simple,scache,pbb.
# If the target wants it can also provide a fast version of same, or if
# the slow (full featured) version is `simple', then the fast version can be
# one of scache/pbb.
# A target can't provide more than this.
# However for illustration's sake this file provides examples of all.

# ??? After a few more ports are done, revisit.
# Will eventually need to machine generate a lot of this.

case "x$1" in

xsupport)

cat <<EOF
#include <stdlib.h>

static INLINE const IDESC *
extract16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
	   ARGBUF *abuf, int fast_p)
{
  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);

  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  if (! fast_p)
    {
      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
    }
  return id;
}

static INLINE const IDESC *
extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
	   ARGBUF *abuf, int fast_p)
{
  const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf);

  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  if (! fast_p)
    {
      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
    }
  return id;
}

static INLINE SEM_PC
execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
{
  SEM_PC vpc;

  if (fast_p)
    {
#if ! WITH_SEM_SWITCH_FAST
#if WITH_SCACHE
      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
#else
      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf);
#endif
#else
      abort ();
#endif /* WITH_SEM_SWITCH_FAST */
    }
  else
    {
#if ! WITH_SEM_SWITCH_FULL
      ARGBUF *abuf = &sc->argbuf;
      const IDESC *idesc = abuf->idesc;
      const CGEN_INSN *idata = idesc->idata;
#if WITH_SCACHE_PBB
      int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL);
#else
      int virtual_p = 0;
#endif

      if (! virtual_p)
	{
	  /* FIXME: call x-before */
	  if (ARGBUF_PROFILE_P (abuf))
	    PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num);
	  /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}.  */
	  if (PROFILE_MODEL_P (current_cpu)
	      && ARGBUF_PROFILE_P (abuf))
	    @cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
	  CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1);
	  CGEN_TRACE_INSN (current_cpu, idata,
		      (const struct argbuf *) abuf, abuf->addr);
	}
#if WITH_SCACHE
      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
#else
      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf);
#endif
      if (! virtual_p)
	{
	  /* FIXME: call x-after */
	  if (PROFILE_MODEL_P (current_cpu)
	      && ARGBUF_PROFILE_P (abuf))
	    {
	      int cycles;

	      cycles = (*idesc->timing->model_fn) (current_cpu, sc);
	      @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
	    }
	  CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1);
	}
#else
      abort ();
#endif /* WITH_SEM_SWITCH_FULL */
    }

  return vpc;
}

EOF

;;

xinit)

# Nothing needed.

;;

xextract-simple | xextract-scache)

cat <<EOF
{
  if ((pc & 3) != 0)
    {
      /* This only occurs when single stepping.
	 The test is unnecessary otherwise, but the cost is teensy,
	 compared with decoding/extraction.  */
      UHI insn = GETIMEMUHI (current_cpu, pc);
      extract16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P);
    }
  else
    {
      USI insn = GETIMEMUSI (current_cpu, pc);
      if ((SI) insn < 0)
	{
	  extract32 (current_cpu, pc, insn, sc, FAST_P);
	}
      else
	{
	  extract16 (current_cpu, pc, insn >> 16, sc, FAST_P);
	  extract16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST_P);
	  /* The m32r doesn't support parallel execution.  */
	  if ((insn & 0x8000) != 0
	      && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
	    sim_engine_illegal_insn (current_cpu, pc);
	}
    }
}
EOF

;;

xextract-pbb)

# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
# Outputs: sc, pc
# sc must be left pointing past the last created entry.
# pc must be left pointing past the last created entry.
# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
# to record the vpc of the cti insn.
# SET_INSN_COUNT(n) must be called to record number of real insns.

cat <<EOF
{
  const IDESC *idesc;
  int icount = 0;

  if ((pc & 3) != 0)
    {
      /* This only occurs when single stepping.
	 The test is unnecessary otherwise, but the cost is teensy,
	 compared with decoding/extraction.  */
      UHI insn = GETIMEMUHI (current_cpu, pc);
      idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
      ++sc;
      --max_insns;
      ++icount;
      pc += 2;
      if (IDESC_CTI_P (idesc))
	{
	  SET_CTI_VPC (sc - 1);
	  goto Finish;
	}
    }

  while (max_insns > 0)
    {
      USI insn = GETIMEMUSI (current_cpu, pc);
      if ((SI) insn < 0)
	{
	  idesc = extract32 (current_cpu, pc, insn, &sc->argbuf, FAST_P);
	  ++sc;
	  --max_insns;
	  ++icount;
	  pc += 4;
	  if (IDESC_CTI_P (idesc))
	    {
	      SET_CTI_VPC (sc - 1);
	      break;
	    }
	}
      else
	{
	  idesc = extract16 (current_cpu, pc, insn >> 16, &sc->argbuf, FAST_P);
	  ++sc;
	  --max_insns;
	  ++icount;
	  pc += 2;
	  if (IDESC_CTI_P (idesc))
	    {
	      SET_CTI_VPC (sc - 1);
	      break;
	    }
	  /* The m32r doesn't support parallel execution.  */
	  if ((insn & 0x8000) != 0)
	    {
	      /* ??? Defer signalling to execution.  */
	      if ((insn & 0x7fff) != 0x7000) /* parallel nops are ok */
		sim_engine_invalid_insn (current_cpu, pc - 2, 0);
	      /* There's no point in processing parallel nops in fast mode.
		 We might as well do this test since we've already tested
		 that we have a parallel nop.  */
	      if (0 && FAST_P)
		{
		  pc += 2;
		  continue;
		}
	    }
	  else
	    {
	      /* Non-parallel case.
		 While we're guaranteed that there's room to extract the
		 insn, when single stepping we can't; the pbb must stop
		 after the first insn.  */
	      if (max_insns == 0)
		break;
	    }
	  /* We're guaranteed that we can always process 16 bit insns in
	     pairs.  */
	  idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
	  ++sc;
	  --max_insns;
	  ++icount;
	  pc += 2;
	  if (IDESC_CTI_P (idesc))
	    {
	      SET_CTI_VPC (sc - 1);
	      break;
	    }
	}
    }

 Finish:
  SET_INSN_COUNT (icount);
}
EOF

;;

xfull-exec-* | xfast-exec-*)

# Inputs: current_cpu, vpc, FAST_P
# Outputs: vpc
# vpc is the virtual program counter.

cat <<EOF
#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
#define DEFINE_SWITCH
#include "sem-switch.c"
#else
  vpc = execute (current_cpu, vpc, FAST_P);
#endif
EOF

;;

*)
  echo "Invalid argument to mainloop.in: $1" >&2
  exit 1
  ;;

esac
