1*56bb7041Schristos# Simulator main loop for eBPF. -*- C -*- 2*56bb7041Schristos# 3*56bb7041Schristos# Copyright (C) 2020 Free Software Foundation, Inc. 4*56bb7041Schristos# 5*56bb7041Schristos# This file is part of the GNU Simulators. 6*56bb7041Schristos# 7*56bb7041Schristos# This program is free software; you can redistribute it and/or modify 8*56bb7041Schristos# it under the terms of the GNU General Public License as published by 9*56bb7041Schristos# the Free Software Foundation; either version 3 of the License, or 10*56bb7041Schristos# (at your option) any later version. 11*56bb7041Schristos# 12*56bb7041Schristos# This program is distributed in the hope that it will be useful, 13*56bb7041Schristos# but WITHOUT ANY WARRANTY; without even the implied warranty of 14*56bb7041Schristos# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*56bb7041Schristos# GNU General Public License for more details. 16*56bb7041Schristos# 17*56bb7041Schristos# You should have received a copy of the GNU General Public License 18*56bb7041Schristos# along with this program. If not, see <http://www.gnu.org/licenses/>. 19*56bb7041Schristos 20*56bb7041Schristos# Syntax: 21*56bb7041Schristos# /bin/sh mloop.in command 22*56bb7041Schristos# 23*56bb7041Schristos# Command is one of: 24*56bb7041Schristos# 25*56bb7041Schristos# init 26*56bb7041Schristos# support 27*56bb7041Schristos# extract-{simple,scache,pbb} 28*56bb7041Schristos# {full,fast}-exec-{simple,scache,pbb} 29*56bb7041Schristos# 30*56bb7041Schristos# A target need only provide a "full" version of one of simple,scache,pbb. 31*56bb7041Schristos# If the target wants it can also provide a fast version of same, or if 32*56bb7041Schristos# the slow (full featured) version is `simple', then the fast version can be 33*56bb7041Schristos# one of scache/pbb. 34*56bb7041Schristos# A target can't provide more than this. 35*56bb7041Schristos# However for illustration's sake this file provides examples of all. 36*56bb7041Schristos 37*56bb7041Schristos# ??? After a few more ports are done, revisit. 38*56bb7041Schristos# Will eventually need to machine generate a lot of this. 39*56bb7041Schristos 40*56bb7041Schristoscase "x$1" in 41*56bb7041Schristos 42*56bb7041Schristosxsupport) 43*56bb7041Schristos 44*56bb7041Schristoscat <<EOF 45*56bb7041Schristos 46*56bb7041Schristosstatic INLINE const IDESC * 47*56bb7041Schristosextract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_WORD insn, 48*56bb7041Schristos ARGBUF *abuf, int fast_p) 49*56bb7041Schristos{ 50*56bb7041Schristos const IDESC *id = @prefix@_decode (current_cpu, pc, insn, abuf); 51*56bb7041Schristos @prefix@_fill_argbuf (current_cpu, abuf, id, pc, fast_p); 52*56bb7041Schristos if (!fast_p) 53*56bb7041Schristos { 54*56bb7041Schristos int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc); 55*56bb7041Schristos int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc); 56*56bb7041Schristos @prefix@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p); 57*56bb7041Schristos } 58*56bb7041Schristos return id; 59*56bb7041Schristos} 60*56bb7041Schristos 61*56bb7041Schristosstatic INLINE SEM_PC 62*56bb7041Schristosexecute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p) 63*56bb7041Schristos{ 64*56bb7041Schristos SEM_PC vpc; 65*56bb7041Schristos 66*56bb7041Schristos if (fast_p) 67*56bb7041Schristos vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); 68*56bb7041Schristos else 69*56bb7041Schristos { 70*56bb7041Schristos ARGBUF *abuf = &sc->argbuf; 71*56bb7041Schristos const IDESC *idesc = abuf->idesc; 72*56bb7041Schristos const CGEN_INSN *idata = idesc->idata; 73*56bb7041Schristos int virtual_p = 0; 74*56bb7041Schristos 75*56bb7041Schristos if (! virtual_p) 76*56bb7041Schristos { 77*56bb7041Schristos /* FIXME: call x-before */ 78*56bb7041Schristos if (ARGBUF_PROFILE_P (abuf)) 79*56bb7041Schristos PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); 80*56bb7041Schristos /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ 81*56bb7041Schristos if (PROFILE_MODEL_P (current_cpu) 82*56bb7041Schristos && ARGBUF_PROFILE_P (abuf)) 83*56bb7041Schristos @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); 84*56bb7041Schristos CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); 85*56bb7041Schristos CGEN_TRACE_INSN (current_cpu, idata, 86*56bb7041Schristos (const struct argbuf *) abuf, abuf->addr); 87*56bb7041Schristos } 88*56bb7041Schristos vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); 89*56bb7041Schristos if (! virtual_p) 90*56bb7041Schristos { 91*56bb7041Schristos /* FIXME: call x-after */ 92*56bb7041Schristos if (PROFILE_MODEL_P (current_cpu) 93*56bb7041Schristos && ARGBUF_PROFILE_P (abuf)) 94*56bb7041Schristos { 95*56bb7041Schristos int cycles; 96*56bb7041Schristos 97*56bb7041Schristos cycles = (*idesc->timing->model_fn) (current_cpu, sc); 98*56bb7041Schristos @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); 99*56bb7041Schristos } 100*56bb7041Schristos CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); 101*56bb7041Schristos } 102*56bb7041Schristos } 103*56bb7041Schristos 104*56bb7041Schristos return vpc; 105*56bb7041Schristos} 106*56bb7041Schristos 107*56bb7041SchristosEOF 108*56bb7041Schristos 109*56bb7041Schristos;; 110*56bb7041Schristos 111*56bb7041Schristosxinit) 112*56bb7041Schristos 113*56bb7041Schristos# Nothing needed. 114*56bb7041Schristos 115*56bb7041Schristos;; 116*56bb7041Schristos 117*56bb7041Schristosxextract-scache) 118*56bb7041Schristos 119*56bb7041Schristoscat <<EOF 120*56bb7041Schristos{ 121*56bb7041Schristos 122*56bb7041Schristos UDI insn = GETIMEMUDI (current_cpu, vpc); 123*56bb7041Schristos 124*56bb7041Schristos if (current_target_byte_order == BFD_ENDIAN_BIG) 125*56bb7041Schristos { 126*56bb7041Schristos /* eBPF instructions are little-endian, but GETIMEMUDI reads according 127*56bb7041Schristos to target byte order. Swap to little-endian. */ 128*56bb7041Schristos insn = SWAP_8 (insn); 129*56bb7041Schristos 130*56bb7041Schristos /* But, the imm32 and offset16 fields within instructions follow target 131*56bb7041Schristos byte order. Swap those fields back. */ 132*56bb7041Schristos UHI off16 = (UHI) ((insn & 0x00000000ffff0000) >> 16); 133*56bb7041Schristos USI imm32 = (USI) ((insn & 0xffffffff00000000) >> 32); 134*56bb7041Schristos off16 = SWAP_2 (off16); 135*56bb7041Schristos imm32 = SWAP_4 (imm32); 136*56bb7041Schristos 137*56bb7041Schristos insn = (((UDI) imm32) << 32) | (((UDI) off16) << 16) | (insn & 0xffff); 138*56bb7041Schristos } 139*56bb7041Schristos 140*56bb7041Schristos extract (current_cpu, vpc, insn, sc, FAST_P); 141*56bb7041Schristos 142*56bb7041Schristos //XXX SEM_SKIP_COMPILE (current_cpu, sc, 1); 143*56bb7041Schristos} 144*56bb7041SchristosEOF 145*56bb7041Schristos 146*56bb7041Schristos;; 147*56bb7041Schristos 148*56bb7041Schristosxfull-exec-* | xfast-exec-*) 149*56bb7041Schristos 150*56bb7041Schristos# Inputs: current_cpu, vpc, sc, FAST_P 151*56bb7041Schristos# Outputs: vpc 152*56bb7041Schristos# vpc is the virtual program counter. 153*56bb7041Schristos 154*56bb7041Schristoscat <<EOF 155*56bb7041Schristos vpc = execute (current_cpu, sc, FAST_P); 156*56bb7041SchristosEOF 157*56bb7041Schristos 158*56bb7041Schristos;; 159*56bb7041Schristos 160*56bb7041Schristos*) 161*56bb7041Schristos echo "Invalid argument to mainloop.in: $1" >&2 162*56bb7041Schristos exit 1 163*56bb7041Schristos ;; 164*56bb7041Schristos 165*56bb7041Schristosesac 166