8sa1-binutils-gdb/sim/bpf/mloop.in
Jose E. Marchesi b26e2ae7d3 sim: eBPF simulator
This patch introduces the basics of an instruction-simulator for eBPF.
The simulator is based on CGEN.

gdb/ChangeLog:

2020-08-04  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* configure.tgt: Set gdb_sim for bpf-*-* targets.

sim/ChangeLog:

2020-08-04  Jose E. Marchesi  <jose.marchesi@oracle.com>
	    David Faust <david.faust@oracle.com>

	* configure.tgt (sim_arch): Add entry for bpf-*-*.
	* configure: Regenerate.
	* MAINTAINERS: Add maintainer for the BPF simulator.
	* bpf/Makefile.in: New file.
	* bpf/bpf-helpers.c: Likewise.
	* bpf/bpf-helpers.def: Likewise.
	* bpf/bpf-helpers.h: Likewise.
	* bpf/bpf-sim.h: Likewise.
	* bpf/bpf.c: Likewise.
	* bpf/config.in: Likewise.
	* bpf/configure.ac: Likewise.
	* bpf/decode.h: Likewise.
	* bpf/eng.h: Likewise.
	* bpf/mloop.in: Likewise.
	* bpf/sim-if.c: Likewise.
	* bpf/sim-main.h: Likewise.
	* bpf/traps.c: Likewise.
	* bpf/configure: Generate.
	* bpf/aclocal.m4: Likewise.

sim/testsuite/ChangeLog:

2020-08-04  David Faust  <david.faust@oracle.com>
	    Jose E. Marchesi  <jose.marchesi@oracle.com>

	* configure: Regenerate.
	* sim/bpf/allinsn.exp: New file.
	* sim/bpf/alu.s: Likewise.
	* sim/bpf/alu32.s: Likewise.
	* sim/bpf/endbe.s: Likewise.
	* sim/bpf/endle.s: Likewise.
	* sim/bpf/jmp.s: Likewise.
	* sim/bpf/jmp32.s: Likewise.
	* sim/bpf/ldabs.s: Likewise.
	* sim/bpf/mem.s: Likewise.
	* sim/bpf/mov.s: Likewise.
	* sim/bpf/testutils.inc: Likewise.
	* sim/bpf/xadd.s: Likewise.
2020-08-04 18:09:16 +02:00

166 lines
4.3 KiB
C

# Simulator main loop for eBPF. -*- C -*-
#
# Copyright (C) 2020 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 mloop.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
static INLINE const IDESC *
extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_WORD insn,
ARGBUF *abuf, int fast_p)
{
const IDESC *id = @prefix@_decode (current_cpu, pc, insn, abuf);
@prefix@_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);
@prefix@_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)
vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
else
{
ARGBUF *abuf = &sc->argbuf;
const IDESC *idesc = abuf->idesc;
const CGEN_INSN *idata = idesc->idata;
int virtual_p = 0;
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);
}
vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
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);
}
}
return vpc;
}
EOF
;;
xinit)
# Nothing needed.
;;
xextract-scache)
cat <<EOF
{
UDI insn = GETIMEMUDI (current_cpu, vpc);
if (current_target_byte_order == BFD_ENDIAN_BIG)
{
/* eBPF instructions are little-endian, but GETIMEMUDI reads according
to target byte order. Swap to little-endian. */
insn = SWAP_8 (insn);
/* But, the imm32 and offset16 fields within instructions follow target
byte order. Swap those fields back. */
UHI off16 = (UHI) ((insn & 0x00000000ffff0000) >> 16);
USI imm32 = (USI) ((insn & 0xffffffff00000000) >> 32);
off16 = SWAP_2 (off16);
imm32 = SWAP_4 (imm32);
insn = (((UDI) imm32) << 32) | (((UDI) off16) << 16) | (insn & 0xffff);
}
extract (current_cpu, vpc, insn, sc, FAST_P);
//XXX SEM_SKIP_COMPILE (current_cpu, sc, 1);
}
EOF
;;
xfull-exec-* | xfast-exec-*)
# Inputs: current_cpu, vpc, sc, FAST_P
# Outputs: vpc
# vpc is the virtual program counter.
cat <<EOF
vpc = execute (current_cpu, sc, FAST_P);
EOF
;;
*)
echo "Invalid argument to mainloop.in: $1" >&2
exit 1
;;
esac