1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# Simulator main loop for eBPF. -*- C -*-
#
# Copyright (C) 2020-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 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
|