OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gdb-6.8/] [pre-binutils-2.20.1-sync/] [sim/] [m32r/] [mloopx.in] - Diff between revs 157 and 223

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 157 Rev 223
# Simulator main loop for m32rx. -*- C -*-
# Simulator main loop for m32rx. -*- C -*-
#
#
# Copyright 1996, 1997, 1998, 2004, 2007, 2008 Free Software Foundation, Inc.
# Copyright 1996, 1997, 1998, 2004, 2007, 2008 Free Software Foundation, Inc.
#
#
# This file is part of the GNU Simulators.
# This file is part of the GNU Simulators.
#
#
# This program is free software; you can redistribute it and/or modify
# 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
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .
# along with this program.  If not, see .
# Syntax:
# Syntax:
# /bin/sh mainloop.in command
# /bin/sh mainloop.in command
#
#
# Command is one of:
# Command is one of:
#
#
# init
# init
# support
# support
# extract-{simple,scache,pbb}
# extract-{simple,scache,pbb}
# {full,fast}-exec-{simple,scache,pbb}
# {full,fast}-exec-{simple,scache,pbb}
#
#
# A target need only provide a "full" version of one of 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
# 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
# the slow (full featured) version is `simple', then the fast version can be
# one of scache/pbb.
# one of scache/pbb.
# A target can't provide more than this.
# A target can't provide more than this.
# ??? After a few more ports are done, revisit.
# ??? After a few more ports are done, revisit.
# Will eventually need to machine generate a lot of this.
# Will eventually need to machine generate a lot of this.
case "x$1" in
case "x$1" in
xsupport)
xsupport)
cat <
cat <
/* Emit insns to write back the results of insns executed in parallel.
/* Emit insns to write back the results of insns executed in parallel.
   SC points to a sufficient number of scache entries for the writeback
   SC points to a sufficient number of scache entries for the writeback
   handlers.
   handlers.
   SC1/ID1 is the first insn (left slot, lower address).
   SC1/ID1 is the first insn (left slot, lower address).
   SC2/ID2 is the second insn (right slot, higher address).  */
   SC2/ID2 is the second insn (right slot, higher address).  */
static INLINE void
static INLINE void
emit_par_finish (SIM_CPU *current_cpu, PCADDR pc, SCACHE *sc,
emit_par_finish (SIM_CPU *current_cpu, PCADDR pc, SCACHE *sc,
                 SCACHE *sc1, const IDESC *id1, SCACHE *sc2, const IDESC *id2)
                 SCACHE *sc1, const IDESC *id1, SCACHE *sc2, const IDESC *id2)
{
{
  ARGBUF *abuf;
  ARGBUF *abuf;
  abuf = &sc->argbuf;
  abuf = &sc->argbuf;
  id1 = id1->par_idesc;
  id1 = id1->par_idesc;
  abuf->fields.write.abuf = &sc1->argbuf;
  abuf->fields.write.abuf = &sc1->argbuf;
  @cpu@_fill_argbuf (current_cpu, abuf, id1, pc, 0);
  @cpu@_fill_argbuf (current_cpu, abuf, id1, pc, 0);
  /* no need to set trace_p,profile_p */
  /* no need to set trace_p,profile_p */
#if 0 /* not currently needed for id2 since results written directly */
#if 0 /* not currently needed for id2 since results written directly */
  abuf = &sc[1].argbuf;
  abuf = &sc[1].argbuf;
  id2 = id2->par_idesc;
  id2 = id2->par_idesc;
  abuf->fields.write.abuf = &sc2->argbuf;
  abuf->fields.write.abuf = &sc2->argbuf;
  @cpu@_fill_argbuf (current_cpu, abuf, id2, pc + 2, 0);
  @cpu@_fill_argbuf (current_cpu, abuf, id2, pc + 2, 0);
  /* no need to set trace_p,profile_p */
  /* no need to set trace_p,profile_p */
#endif
#endif
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
emit_16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
         SCACHE *sc, int fast_p, int parallel_p)
         SCACHE *sc, int fast_p, int parallel_p)
{
{
  ARGBUF *abuf = &sc->argbuf;
  ARGBUF *abuf = &sc->argbuf;
  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
  if (parallel_p)
  if (parallel_p)
    id = id->par_idesc;
    id = id->par_idesc;
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  return id;
  return id;
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_full16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
emit_full16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
             int trace_p, int profile_p)
             int trace_p, int profile_p)
{
{
  const IDESC *id;
  const IDESC *id;
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  id = emit_16 (current_cpu, pc, insn, sc + 1, 0, 0);
  id = emit_16 (current_cpu, pc, insn, sc + 1, 0, 0);
  @cpu@_emit_after (current_cpu, sc + 2, pc);
  @cpu@_emit_after (current_cpu, sc + 2, pc);
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.profile_p = profile_p;
  sc[1].argbuf.profile_p = profile_p;
  return id;
  return id;
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
               SCACHE *sc, int fast_p)
               SCACHE *sc, int fast_p)
{
{
  const IDESC *id,*id2;
  const IDESC *id,*id2;
  /* Emit both insns, then emit a finisher-upper.
  /* Emit both insns, then emit a finisher-upper.
     We speed things up by handling the second insn serially
     We speed things up by handling the second insn serially
     [not parallelly].  Then the writeback only has to deal
     [not parallelly].  Then the writeback only has to deal
     with the first insn.  */
     with the first insn.  */
  /* ??? Revisit to handle exceptions right.  */
  /* ??? Revisit to handle exceptions right.  */
  /* FIXME: No need to handle this parallely if second is nop.  */
  /* FIXME: No need to handle this parallely if second is nop.  */
  id = emit_16 (current_cpu, pc, insn >> 16, sc, fast_p, 1);
  id = emit_16 (current_cpu, pc, insn >> 16, sc, fast_p, 1);
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, fast_p, 0);
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, fast_p, 0);
  /* Set sc/snc insns notion of where to skip to.  */
  /* Set sc/snc insns notion of where to skip to.  */
  if (IDESC_SKIP_P (id))
  if (IDESC_SKIP_P (id))
    SEM_SKIP_COMPILE (current_cpu, sc, 1);
    SEM_SKIP_COMPILE (current_cpu, sc, 1);
  /* Emit code to finish executing the semantics
  /* Emit code to finish executing the semantics
     (write back the results).  */
     (write back the results).  */
  emit_par_finish (current_cpu, pc, sc + 2, sc, id, sc + 1, id2);
  emit_par_finish (current_cpu, pc, sc + 2, sc, id, sc + 1, id2);
  return id;
  return id;
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
                    SCACHE *sc, int trace_p, int profile_p)
                    SCACHE *sc, int trace_p, int profile_p)
{
{
  const IDESC *id,*id2;
  const IDESC *id,*id2;
  /* Emit both insns, then emit a finisher-upper.
  /* Emit both insns, then emit a finisher-upper.
     We speed things up by handling the second insn serially
     We speed things up by handling the second insn serially
     [not parallelly].  Then the writeback only has to deal
     [not parallelly].  Then the writeback only has to deal
     with the first insn.  */
     with the first insn.  */
  /* ??? Revisit to handle exceptions right.  */
  /* ??? Revisit to handle exceptions right.  */
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  /* FIXME: No need to handle this parallelly if second is nop.  */
  /* FIXME: No need to handle this parallelly if second is nop.  */
  id = emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 1);
  id = emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 1);
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.profile_p = profile_p;
  sc[1].argbuf.profile_p = profile_p;
  @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
  @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
  /* Note that this can never be a cti.  No cti's go in the S pipeline.  */
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 3, 0, 0);
  id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 3, 0, 0);
  sc[3].argbuf.trace_p = trace_p;
  sc[3].argbuf.trace_p = trace_p;
  sc[3].argbuf.profile_p = profile_p;
  sc[3].argbuf.profile_p = profile_p;
  /* Set sc/snc insns notion of where to skip to.  */
  /* Set sc/snc insns notion of where to skip to.  */
  if (IDESC_SKIP_P (id))
  if (IDESC_SKIP_P (id))
    SEM_SKIP_COMPILE (current_cpu, sc, 4);
    SEM_SKIP_COMPILE (current_cpu, sc, 4);
  /* Emit code to finish executing the semantics
  /* Emit code to finish executing the semantics
     (write back the results).  */
     (write back the results).  */
  emit_par_finish (current_cpu, pc, sc + 4, sc + 1, id, sc + 3, id2);
  emit_par_finish (current_cpu, pc, sc + 4, sc + 1, id, sc + 3, id2);
  @cpu@_emit_after (current_cpu, sc + 5, pc);
  @cpu@_emit_after (current_cpu, sc + 5, pc);
  return id;
  return id;
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
         SCACHE *sc, int fast_p)
         SCACHE *sc, int fast_p)
{
{
  ARGBUF *abuf = &sc->argbuf;
  ARGBUF *abuf = &sc->argbuf;
  const IDESC *id = @cpu@_decode (current_cpu, pc,
  const IDESC *id = @cpu@_decode (current_cpu, pc,
                                  (USI) insn >> 16, insn, abuf);
                                  (USI) insn >> 16, insn, abuf);
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
  return id;
  return id;
}
}
static INLINE const IDESC *
static INLINE const IDESC *
emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
             int trace_p, int profile_p)
             int trace_p, int profile_p)
{
{
  const IDESC *id;
  const IDESC *id;
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  @cpu@_emit_before (current_cpu, sc, pc, 1);
  id = emit_32 (current_cpu, pc, insn, sc + 1, 0);
  id = emit_32 (current_cpu, pc, insn, sc + 1, 0);
  @cpu@_emit_after (current_cpu, sc + 2, pc);
  @cpu@_emit_after (current_cpu, sc + 2, pc);
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.trace_p = trace_p;
  sc[1].argbuf.profile_p = profile_p;
  sc[1].argbuf.profile_p = profile_p;
  return id;
  return id;
}
}
EOF
EOF
;;
;;
xinit)
xinit)
# Nothing needed.
# Nothing needed.
;;
;;
xextract-pbb)
xextract-pbb)
# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
# Outputs: sc, pc
# Outputs: sc, pc
# sc must be left pointing past the last created entry.
# sc must be left pointing past the last created entry.
# pc 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
# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
# to record the vpc of the cti insn.
# to record the vpc of the cti insn.
# SET_INSN_COUNT(n) must be called to record number of real insns.
# SET_INSN_COUNT(n) must be called to record number of real insns.
cat <
cat <
{
{
  const IDESC *idesc;
  const IDESC *idesc;
  int icount = 0;
  int icount = 0;
  if ((pc & 3) != 0)
  if ((pc & 3) != 0)
    {
    {
      /* This occurs when single stepping and when compiling the not-taken
      /* This occurs when single stepping and when compiling the not-taken
         part of conditional branches.  */
         part of conditional branches.  */
      UHI insn = GETIMEMUHI (current_cpu, pc);
      UHI insn = GETIMEMUHI (current_cpu, pc);
      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
      SCACHE *cti_sc; /* ??? tmp hack */
      SCACHE *cti_sc; /* ??? tmp hack */
      /* A parallel insn isn't allowed here, but we don't mind nops.
      /* A parallel insn isn't allowed here, but we don't mind nops.
         ??? We need to wait until the insn is executed before signalling
         ??? We need to wait until the insn is executed before signalling
         the error, for situations where such signalling is wanted.  */
         the error, for situations where such signalling is wanted.  */
#if 0
#if 0
      if ((insn & 0x8000) != 0
      if ((insn & 0x8000) != 0
          && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
          && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
        sim_engine_invalid_insn (current_cpu, pc, 0);
        sim_engine_invalid_insn (current_cpu, pc, 0);
#endif
#endif
      /* Only emit before/after handlers if necessary.  */
      /* Only emit before/after handlers if necessary.  */
      if (FAST_P || (! trace_p && ! profile_p))
      if (FAST_P || (! trace_p && ! profile_p))
        {
        {
          idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
          idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
          cti_sc = sc;
          cti_sc = sc;
          ++sc;
          ++sc;
          --max_insns;
          --max_insns;
        }
        }
      else
      else
        {
        {
          idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
          idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
                               trace_p, profile_p);
                               trace_p, profile_p);
          cti_sc = sc + 1;
          cti_sc = sc + 1;
          sc += 3;
          sc += 3;
          max_insns -= 3;
          max_insns -= 3;
        }
        }
      ++icount;
      ++icount;
      pc += 2;
      pc += 2;
      if (IDESC_CTI_P (idesc))
      if (IDESC_CTI_P (idesc))
        {
        {
          SET_CTI_VPC (cti_sc);
          SET_CTI_VPC (cti_sc);
          goto Finish;
          goto Finish;
        }
        }
    }
    }
  /* There are two copies of the compiler: full(!fast) and fast.
  /* There are two copies of the compiler: full(!fast) and fast.
     The "full" case emits before/after handlers for each insn.
     The "full" case emits before/after handlers for each insn.
     Having two copies of this code is a tradeoff, having one copy
     Having two copies of this code is a tradeoff, having one copy
     seemed a bit more difficult to read (due to constantly testing
     seemed a bit more difficult to read (due to constantly testing
     FAST_P).  ??? On the other hand, with address ranges we'll want to
     FAST_P).  ??? On the other hand, with address ranges we'll want to
     omit before/after handlers for unwanted insns.  Having separate loops
     omit before/after handlers for unwanted insns.  Having separate loops
     for FAST/!FAST avoids constantly doing the test in the loop, but
     for FAST/!FAST avoids constantly doing the test in the loop, but
     typically FAST_P is a constant and such tests will get optimized out.  */
     typically FAST_P is a constant and such tests will get optimized out.  */
  if (FAST_P)
  if (FAST_P)
    {
    {
      while (max_insns > 0)
      while (max_insns > 0)
        {
        {
          USI insn = GETIMEMUSI (current_cpu, pc);
          USI insn = GETIMEMUSI (current_cpu, pc);
          if ((SI) insn < 0)
          if ((SI) insn < 0)
            {
            {
              /* 32 bit insn */
              /* 32 bit insn */
              idesc = emit_32 (current_cpu, pc, insn, sc, 1);
              idesc = emit_32 (current_cpu, pc, insn, sc, 1);
              ++sc;
              ++sc;
              --max_insns;
              --max_insns;
              ++icount;
              ++icount;
              pc += 4;
              pc += 4;
              if (IDESC_CTI_P (idesc))
              if (IDESC_CTI_P (idesc))
                {
                {
                  SET_CTI_VPC (sc - 1);
                  SET_CTI_VPC (sc - 1);
                  break;
                  break;
                }
                }
            }
            }
          else
          else
            {
            {
              if ((insn & 0x8000) != 0) /* parallel? */
              if ((insn & 0x8000) != 0) /* parallel? */
                {
                {
                  int up_count;
                  int up_count;
                  if (((insn >> 16) & 0xfff0) == 0x10f0)
                  if (((insn >> 16) & 0xfff0) == 0x10f0)
                    {
                    {
                      /* FIXME: No need to handle this sequentially if system
                      /* FIXME: No need to handle this sequentially if system
                         calls will be able to execute after second insn in
                         calls will be able to execute after second insn in
                         parallel. ( trap #num || insn ) */
                         parallel. ( trap #num || insn ) */
                      /* insn */
                      /* insn */
                      idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
                      idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
                                       sc, 1, 0);
                                       sc, 1, 0);
                      /* trap */
                      /* trap */
                      emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
                      emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
                      up_count = 2;
                      up_count = 2;
                    }
                    }
                  else
                  else
                    {
                    {
                      /* Yep.  Here's the "interesting" [sic] part.  */
                      /* Yep.  Here's the "interesting" [sic] part.  */
                      idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
                      idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
                      up_count = 3;
                      up_count = 3;
                    }
                    }
                  sc += up_count;
                  sc += up_count;
                  max_insns -= up_count;
                  max_insns -= up_count;
                  icount += 2;
                  icount += 2;
                  pc += 4;
                  pc += 4;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (sc - up_count);
                      SET_CTI_VPC (sc - up_count);
                      break;
                      break;
                    }
                    }
                }
                }
              else /* 2 serial 16 bit insns */
              else /* 2 serial 16 bit insns */
                {
                {
                  idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
                  idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
                  ++sc;
                  ++sc;
                  --max_insns;
                  --max_insns;
                  ++icount;
                  ++icount;
                  pc += 2;
                  pc += 2;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (sc - 1);
                      SET_CTI_VPC (sc - 1);
                      break;
                      break;
                    }
                    }
                  /* While we're guaranteed that there's room to extract the
                  /* While we're guaranteed that there's room to extract the
                     insn, when single stepping we can't; the pbb must stop
                     insn, when single stepping we can't; the pbb must stop
                     after the first insn.  */
                     after the first insn.  */
                  if (max_insns == 0)
                  if (max_insns == 0)
                    break;
                    break;
                  idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
                  idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
                  ++sc;
                  ++sc;
                  --max_insns;
                  --max_insns;
                  ++icount;
                  ++icount;
                  pc += 2;
                  pc += 2;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (sc - 1);
                      SET_CTI_VPC (sc - 1);
                      break;
                      break;
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
  else /* ! FAST_P */
  else /* ! FAST_P */
    {
    {
      while (max_insns > 0)
      while (max_insns > 0)
        {
        {
          USI insn = GETIMEMUSI (current_cpu, pc);
          USI insn = GETIMEMUSI (current_cpu, pc);
          int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
          int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
          int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
          int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
          SCACHE *cti_sc; /* ??? tmp hack */
          SCACHE *cti_sc; /* ??? tmp hack */
          if ((SI) insn < 0)
          if ((SI) insn < 0)
            {
            {
              /* 32 bit insn
              /* 32 bit insn
                 Only emit before/after handlers if necessary.  */
                 Only emit before/after handlers if necessary.  */
              if (trace_p || profile_p)
              if (trace_p || profile_p)
                {
                {
                  idesc = emit_full32 (current_cpu, pc, insn, sc,
                  idesc = emit_full32 (current_cpu, pc, insn, sc,
                                       trace_p, profile_p);
                                       trace_p, profile_p);
                  cti_sc = sc + 1;
                  cti_sc = sc + 1;
                  sc += 3;
                  sc += 3;
                  max_insns -= 3;
                  max_insns -= 3;
                }
                }
              else
              else
                {
                {
                  idesc = emit_32 (current_cpu, pc, insn, sc, 0);
                  idesc = emit_32 (current_cpu, pc, insn, sc, 0);
                  cti_sc = sc;
                  cti_sc = sc;
                  ++sc;
                  ++sc;
                  --max_insns;
                  --max_insns;
                }
                }
              ++icount;
              ++icount;
              pc += 4;
              pc += 4;
              if (IDESC_CTI_P (idesc))
              if (IDESC_CTI_P (idesc))
                {
                {
                  SET_CTI_VPC (cti_sc);
                  SET_CTI_VPC (cti_sc);
                  break;
                  break;
                }
                }
            }
            }
          else
          else
            {
            {
              if ((insn & 0x8000) != 0) /* parallel? */
              if ((insn & 0x8000) != 0) /* parallel? */
                {
                {
                  /* Yep.  Here's the "interesting" [sic] part.
                  /* Yep.  Here's the "interesting" [sic] part.
                     Only emit before/after handlers if necessary.  */
                     Only emit before/after handlers if necessary.  */
                  if (trace_p || profile_p)
                  if (trace_p || profile_p)
                    {
                    {
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
                        {
                        {
                          /* FIXME: No need to handle this sequentially if
                          /* FIXME: No need to handle this sequentially if
                             system calls will be able to execute after second
                             system calls will be able to execute after second
                             insn in parallel. ( trap #num || insn ) */
                             insn in parallel. ( trap #num || insn ) */
                          /* insn */
                          /* insn */
                          idesc = emit_full16 (current_cpu, pc + 2,
                          idesc = emit_full16 (current_cpu, pc + 2,
                                               insn & 0x7fff, sc, 0, 0);
                                               insn & 0x7fff, sc, 0, 0);
                          /* trap */
                          /* trap */
                          emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
                          emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
                                       0, 0);
                                       0, 0);
                        }
                        }
                      else
                      else
                        {
                        {
                          idesc = emit_full_parallel (current_cpu, pc, insn,
                          idesc = emit_full_parallel (current_cpu, pc, insn,
                                                      sc, trace_p, profile_p);
                                                      sc, trace_p, profile_p);
                        }
                        }
                      cti_sc = sc + 1;
                      cti_sc = sc + 1;
                      sc += 6;
                      sc += 6;
                      max_insns -= 6;
                      max_insns -= 6;
                    }
                    }
                  else
                  else
                    {
                    {
                      int up_count;
                      int up_count;
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
                      if (((insn >> 16) & 0xfff0) == 0x10f0)
                        {
                        {
                          /* FIXME: No need to handle this sequentially if
                          /* FIXME: No need to handle this sequentially if
                             system calls will be able to execute after second
                             system calls will be able to execute after second
                             insn in parallel. ( trap #num || insn ) */
                             insn in parallel. ( trap #num || insn ) */
                          /* insn */
                          /* insn */
                          idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
                          idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
                                           sc, 0, 0);
                                           sc, 0, 0);
                          /* trap */
                          /* trap */
                          emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
                          emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
                          up_count = 2;
                          up_count = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
                          idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
                          up_count = 3;
                          up_count = 3;
                        }
                        }
                      cti_sc = sc;
                      cti_sc = sc;
                      sc += up_count;
                      sc += up_count;
                      max_insns -= up_count;
                      max_insns -= up_count;
                    }
                    }
                  icount += 2;
                  icount += 2;
                  pc += 4;
                  pc += 4;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (cti_sc);
                      SET_CTI_VPC (cti_sc);
                      break;
                      break;
                    }
                    }
                }
                }
              else /* 2 serial 16 bit insns */
              else /* 2 serial 16 bit insns */
                {
                {
                  /* Only emit before/after handlers if necessary.  */
                  /* Only emit before/after handlers if necessary.  */
                  if (trace_p || profile_p)
                  if (trace_p || profile_p)
                    {
                    {
                      idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
                      idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
                                           trace_p, profile_p);
                                           trace_p, profile_p);
                      cti_sc = sc + 1;
                      cti_sc = sc + 1;
                      sc += 3;
                      sc += 3;
                      max_insns -= 3;
                      max_insns -= 3;
                    }
                    }
                  else
                  else
                    {
                    {
                      idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
                      idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
                      cti_sc = sc;
                      cti_sc = sc;
                      ++sc;
                      ++sc;
                      --max_insns;
                      --max_insns;
                    }
                    }
                  ++icount;
                  ++icount;
                  pc += 2;
                  pc += 2;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (cti_sc);
                      SET_CTI_VPC (cti_sc);
                      break;
                      break;
                    }
                    }
                  /* While we're guaranteed that there's room to extract the
                  /* While we're guaranteed that there's room to extract the
                     insn, when single stepping we can't; the pbb must stop
                     insn, when single stepping we can't; the pbb must stop
                     after the first insn.  */
                     after the first insn.  */
                  if (max_insns <= 0)
                  if (max_insns <= 0)
                    break;
                    break;
                  /* Use the same trace/profile address for the 2nd insn.
                  /* Use the same trace/profile address for the 2nd insn.
                     Saves us having to compute it and they come in pairs
                     Saves us having to compute it and they come in pairs
                     anyway (e.g. can never branch to the 2nd insn).  */
                     anyway (e.g. can never branch to the 2nd insn).  */
                  if (trace_p || profile_p)
                  if (trace_p || profile_p)
                    {
                    {
                      idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
                      idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
                                           trace_p, profile_p);
                                           trace_p, profile_p);
                      cti_sc = sc + 1;
                      cti_sc = sc + 1;
                      sc += 3;
                      sc += 3;
                      max_insns -= 3;
                      max_insns -= 3;
                    }
                    }
                  else
                  else
                    {
                    {
                      idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
                      idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
                      cti_sc = sc;
                      cti_sc = sc;
                      ++sc;
                      ++sc;
                      --max_insns;
                      --max_insns;
                    }
                    }
                  ++icount;
                  ++icount;
                  pc += 2;
                  pc += 2;
                  if (IDESC_CTI_P (idesc))
                  if (IDESC_CTI_P (idesc))
                    {
                    {
                      SET_CTI_VPC (cti_sc);
                      SET_CTI_VPC (cti_sc);
                      break;
                      break;
                    }
                    }
                }
                }
            }
            }
        }
        }
    }
    }
 Finish:
 Finish:
  SET_INSN_COUNT (icount);
  SET_INSN_COUNT (icount);
}
}
EOF
EOF
;;
;;
xfull-exec-pbb)
xfull-exec-pbb)
# Inputs: current_cpu, vpc, FAST_P
# Inputs: current_cpu, vpc, FAST_P
# Outputs: vpc
# Outputs: vpc
# vpc is the virtual program counter.
# vpc is the virtual program counter.
cat <
cat <
#define DEFINE_SWITCH
#define DEFINE_SWITCH
#include "semx-switch.c"
#include "semx-switch.c"
EOF
EOF
;;
;;
*)
*)
  echo "Invalid argument to mainloop.in: $1" >&2
  echo "Invalid argument to mainloop.in: $1" >&2
  exit 1
  exit 1
  ;;
  ;;
esac
esac
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.