binutils-gdb/sim/m32r/mainloop.in
David Edelsohn 646c6f2b83 Merge from branch into devo. CGEN generic files moved to common
directory.  K&R C support is no longer provided.
1997-05-01 22:33:23 +00:00

322 lines
6.3 KiB
C

# This shell script emits C code. -*- C -*-
# Main loop and support routines for the M32R.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Contributed by Cygnus Support.
#
# This file is part of GDB, the GNU debugger.
#
# 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 2, 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, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Syntax:
# /bin/sh mainloop.in {init|normal|fast|support}
# ??? There's lots of conditional compilation here.
# After a few more ports are done, revisit.
case "x$1" in
xinit)
cat <<EOF
#if defined (WITH_SCACHE) && defined (USE_SEM_SWITCH) && defined (__GNUC__)
{
static decode_init_p = 0;
if (! decode_init_p)
{
/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */
#define DEFINE_LABELS
#include "sem-switch.c"
decode_init_p = 1;
}
}
#endif
EOF
;;
xnormal | xfast)
cat <<EOF
#if WITH_SCACHE
{
int hash;
SCACHE *sc;
/* First step: look up current insn in hash table. */
hash = SCACHE_HASH_PC (sd, PC);
sc = CPU_SCACHE_CACHE (current_cpu) + hash;
/* If the entry isn't the one we want (cache miss),
fetch and decode the instruction. */
if (sc->argbuf.addr != PC)
{
PCADDR pc = PC;
insn_t insn;
#if ! FAST
PROFILE_COUNT_SCACHE_MISS (current_cpu);
#endif
/* This only occurs when single stepping.
The test is unnecessary otherwise, but the cost is teensy,
compared with decoding/extraction. */
if (pc & 3)
{
insn = GETMEMUHI (current_cpu, pc);
do_extract_insn16 (current_cpu, pc, insn & 0x7fff, sc, FAST);
}
else
{
insn = GETMEMUSI (current_cpu, pc);
if (insn & 0x80000000)
{
do_extract_insn32 (current_cpu, pc, insn, sc, FAST);
}
else
{
/* 2 16 bit insns. Ignore parallel case for now
(2nd always nop). Decode both as we know there's room.
??? Could do a test for an unconditional branch in the
left slot if one wanted to. */
do_extract_insn16 (current_cpu, pc, insn >> 16, sc, FAST);
do_extract_insn16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST);
}
}
}
#if ! FAST
else
{
PROFILE_COUNT_SCACHE_HIT (current_cpu);
}
#endif
#if 0 /*FIXME:wip*/
/* Run until we get a cache miss. */
do
{
#if ! FAST
TRACE_INSN_INIT (current_cpu);
TRACE_INSN (current_cpu, sc->argbuf.opcode, &sc->argbuf, sc->argbuf.addr);
#endif
sc = (*sc->semantic.sem_fn) (current_cpu, sc);
#if ! FAST
TRACE_INSN_FINI (current_cpu);
#endif
}
while (sc->argbuf.addr == PC);
#if ! FAST
PROFILE_COUNT_INSN (current_cpu, pc, CGEN_INSN_INDEX (sc->argbuf.opcode));
#endif
#else /* !wip */
#if ! FAST
TRACE_INSN_INIT (current_cpu);
TRACE_INSN (current_cpu, sc->argbuf.opcode, &sc->argbuf, sc->argbuf.addr);
#endif
#if FAST && defined (USE_SEM_SWITCH)
#define DEFINE_SWITCH
#include "sem-switch.c"
#else
PC = (*sc->semantic.sem_fn) (current_cpu, sc);
#endif
#if ! FAST
TRACE_INSN_FINI (current_cpu);
PROFILE_COUNT_INSN (current_cpu, pc, CGEN_INSN_INDEX (sc->argbuf.opcode));
#endif
#endif /* !wip */
}
#else /* ! WITH_SCACHE */
{
insn_t insn;
if (PC & 3)
{
insn = GETMEMUHI (current_cpu, PC);
PC = do_insn16 (current_cpu, PC, insn & 0x7fff);
}
else
{
insn = GETMEMUSI (current_cpu, PC);
if (insn & 0x80000000)
{
/* 32 bit insn */
PC = do_insn32 (current_cpu, PC, insn);
}
else
{
/* 2 16 bit insns. Ignore parallel case for now
(2nd always nop). */
PCADDR oldpc = PC;
PC = do_insn16 (current_cpu, PC, insn >> 16);
if (PC == oldpc + 2)
{
PC = do_insn16 (current_cpu, PC, insn & 0x7fff);
}
}
}
}
#endif /* ! WITH_SCACHE */
EOF
;;
xsupport)
cat <<EOF
#if WITH_SCACHE
#ifdef __GNUC__
#define DO_INLINE inline
#else
#define DO_INLINE
#endif
/* FAST is optimized out by GCC. */
static DO_INLINE void
do_extract_insn16 (SIM_CPU *cpu, PCADDR pc, insn_t insn,
SCACHE *sc, int fast)
{
DECODE *d = decode (insn);
(*d->extract) (cpu, pc, insn, &sc->argbuf);
if (fast)
{
#ifdef USE_SEM_SWITCH
#ifdef __GNUC__
sc->semantic.sem_case = d->semantic_lab;
#else
sc->semantic.sem_case = d->insn_type;
#endif
#else
sc->semantic.sem_fn = d->semantic_fast;
#endif
}
else
{
sc->semantic.sem_fn = d->semantic_fast;
sc->argbuf.opcode = d->opcode;
}
sc->next = pc + 2;
}
static DO_INLINE void
do_extract_insn32 (SIM_CPU *cpu, PCADDR pc, insn_t insn,
SCACHE *sc, int fast)
{
/* 32 bit insn */
DECODE *d = decode (insn >> 16);
(*d->extract) (cpu, pc, insn, &sc->argbuf);
if (fast)
{
#ifdef USE_SEM_SWITCH
#ifdef __GNUC__
sc->semantic.sem_case = d->semantic_lab;
#else
sc->semantic.sem_case = d->insn_type;
#endif
#else
sc->semantic.sem_fn = d->semantic_fast;
#endif
}
else
{
sc->semantic.sem_fn = d->semantic_fast;
sc->argbuf.opcode = d->opcode;
}
sc->next = pc + 4;
}
#endif /* WITH_SCACHE */
static PCADDR
do_insn16 (cpu, pc, insn)
SIM_CPU *cpu;
PCADDR pc;
insn_t insn;
{
DECODE *d;
ARGBUF argbuf;
d = decode (insn);
(*d->extract) (cpu, pc, insn, &argbuf);
argbuf.opcode = d->opcode;
TRACE_INSN_INIT (cpu);
TRACE_INSN (cpu, d->opcode, &argbuf, pc);
pc = (*d->semantic) (cpu, &argbuf);
TRACE_INSN_FINI (cpu);
PROFILE_COUNT_INSN (cpu, pc, d->insn_type);
return pc;
}
static PCADDR
do_insn32 (cpu, pc, insn)
SIM_CPU *cpu;
PCADDR pc;
insn_t insn;
{
DECODE *d;
ARGBUF argbuf;
d = decode (insn >> 16);
(*d->extract) (cpu, pc, insn, &argbuf);
argbuf.opcode = d->opcode;
TRACE_INSN_INIT (cpu);
TRACE_INSN (cpu, d->opcode, &argbuf, pc);
pc = (*d->semantic) (cpu, &argbuf);
TRACE_INSN_FINI (cpu);
PROFILE_COUNT_INSN (cpu, pc, d->insn_type);
return pc;
}
EOF
;;
*)
echo "Invalid argument to mainloop.in: $1" >&2
exit 1
;;
esac