/* eBPF simulator support code
   Copyright (C) 2020-2021 Free Software Foundation, Inc.

   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 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/>.  */

#define WANT_CPU_BPFBF
#define WANT_CPU bpfbf

#include "sim-main.h"
#include "sim-fpu.h"
#include "cgen-mem.h"
#include "cgen-ops.h"
#include "cpuall.h"
#include "decode.h"

#include "defs-le.h"  /* For SCACHE */
#include "bpf-helpers.h"

/* It is not possible to include both defs-le.h and defs-be.h due to
   duplicated definitions, so we need a bunch of forward declarations
   here.  */
extern void bpfbf_ebpfle_init_idesc_table (SIM_CPU *);
extern void bpfbf_ebpfbe_init_idesc_table (SIM_CPU *);

uint64_t skb_data_offset;

IDESC *bpf_idesc_le;
IDESC *bpf_idesc_be;


int
bpfbf_fetch_register (SIM_CPU *current_cpu,
                      int rn,
                      unsigned char *buf,
                      int len)
{
  if (rn == 11)
    SETTDI (buf, CPU_PC_GET (current_cpu));
  else if (0 <= rn && rn < 10)
    SETTDI (buf, GET_H_GPR (rn));
  else
    return 0;

  return len;
}

int
bpfbf_store_register (SIM_CPU *current_cpu,
                      int rn,
                      unsigned char *buf,
                      int len)
{
  if (rn == 11)
    CPU_PC_SET (current_cpu, GETTDI (buf));
  else if (0 <= rn && rn < 10)
    SET_H_GPR (rn, GETTDI (buf));
  else
    return 0;

  return len;
}

void
bpfbf_model_insn_before (SIM_CPU *current_cpu, int first_p)
{
  /* XXX */
}

void
bpfbf_model_insn_after (SIM_CPU *current_cpu, int first_p)
{
  /* XXX */
}


/***** Instruction helpers.  *****/

/* The semantic routines for most instructions are expressed in RTL in
   the cpu/bpf.cpu file, and automatically translated to C in the
   sem-*.c files in this directory.

   However, some of the semantic routines make use of helper C
   functions.  This happens when the semantics of the instructions
   can't be expressed in RTL alone in a satisfactory way, or not at
   all.

   The following functions implement these C helpers. */

DI
bpfbf_endle (SIM_CPU *current_cpu, DI value, UINT bitsize)
{
  switch (bitsize)
    {
      case 16: return endian_h2le_2(endian_t2h_2(value));
      case 32: return endian_h2le_4(endian_t2h_4(value));
      case 64: return endian_h2le_8(endian_t2h_8(value));
      default: assert(0);
    }
  return value;
}

DI
bpfbf_endbe (SIM_CPU *current_cpu, DI value, UINT bitsize)
{
  switch (bitsize)
    {
      case 16: return endian_h2be_2(endian_t2h_2(value));
      case 32: return endian_h2be_4(endian_t2h_4(value));
      case 64: return endian_h2be_8(endian_t2h_8(value));
      default: assert(0);
    }
  return value;
}

DI
bpfbf_skb_data_offset (SIM_CPU *current_cpu)
{
  /* Simply return the user-configured value.
     This will be 0 if it has not been set. */
  return skb_data_offset;
}


VOID
bpfbf_call (SIM_CPU *current_cpu, INT disp32, UINT src)
{
  /* eBPF supports two kind of CALL instructions: the so called pseudo
     calls ("bpf to bpf") and external calls ("bpf to helper").

     Both kind of calls use the same instruction (CALL).  However,
     external calls are constructed by passing a constant argument to
     the instruction, that identifies the helper, whereas pseudo calls
     result from expressions involving symbols.

     We distinguish calls from pseudo-calls with the later having a 1
     stored in the SRC field of the instruction.  */

  if (src == 1)
    {
      /* This is a pseudo-call.  */

      /* XXX allocate a new stack frame and transfer control.  For
         that we need to analyze the target function, like the kernel
         verifier does.  We better populate a cache
         (function_start_address -> frame_size) so we avoid
         calculating this more than once.  */
      /* XXX note that disp32 is PC-relative in number of 64-bit
         words, _minus one_.  */
    }
  else
    {
      /* This is a call to a helper.

         DISP32 contains the helper number.  Dispatch to the
         corresponding helper emulator in bpf-helpers.c.  */

      switch (disp32) {
        /* case TRACE_PRINTK: */
        case 7:
          bpf_trace_printk (current_cpu);
          break;
        default:;
      }
    }
}

VOID
bpfbf_exit (SIM_CPU *current_cpu)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  /*  r0 holds "return code" */
  DI r0 = GET_H_GPR (0);

  printf ("exit %ld (0x%lx)\n", r0, r0);

  sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu),
                   sim_exited, 0 /* sigrc */);
}

VOID
bpfbf_breakpoint (SIM_CPU *current_cpu)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu),
                   sim_stopped, SIM_SIGTRAP);
}

/* We use the definitions below instead of the cgen-generated model.c,
   because the later is not really able to work with cpus featuring
   several ISAs.  This should be fixed in CGEN.  */

static void
bpf_def_model_init ()
{
  /* Do nothing.  */
}

static void
bpfbf_prepare_run (SIM_CPU *cpu)
{
  /* Nothing.  */
}

void
bpf_engine_run_full (SIM_CPU *cpu)
{
  if (current_target_byte_order == BFD_ENDIAN_LITTLE)
    {
      if (!bpf_idesc_le)
        {
          bpfbf_ebpfle_init_idesc_table (cpu);
          bpf_idesc_le = CPU_IDESC (cpu);
        }
      else
        CPU_IDESC (cpu) = bpf_idesc_le;

      bpfbf_ebpfle_engine_run_full (cpu);
    }
  else
    {
      if (!bpf_idesc_be)
        {
          bpfbf_ebpfbe_init_idesc_table (cpu);
          bpf_idesc_be = CPU_IDESC (cpu);
        }
      else
        CPU_IDESC (cpu) = bpf_idesc_be;

      bpfbf_ebpfbe_engine_run_full (cpu);
    }
}

#if WITH_FAST

void
bpf_engine_run_fast (SIM_CPU *cpu)
{
  if (current_target_byte_order == BFD_ENDIAN_LITTLE)
    {
      if (!bpf_idesc_le)
        {
          bpfbf_ebpfle_init_idesc_table (cpu);
          bpf_idesc_le = CPU_IDESC (cpu);
        }
      else
        CPU_IDESC (cpu) = bpf_idesc_le;

      bpfbf_ebpfle_engine_run_fast (cpu);
    }
  else
    {
      if (!bpf_idesc_be)
        {
          bpfbf_ebpfbe_init_idesc_table (cpu);
          bpf_idesc_be = CPU_IDESC (cpu);
        }
      else
        CPU_IDESC (cpu) = bpf_idesc_be;

      bpfbf_ebpfbe_engine_run_fast (cpu);
    }
}

#endif /* WITH_FAST */

static const CGEN_INSN *
bpfbf_get_idata (SIM_CPU *cpu, int inum)
{
  return CPU_IDESC (cpu) [inum].idata;
}

static void
bpf_init_cpu (SIM_CPU *cpu)
{
  CPU_REG_FETCH (cpu) = bpfbf_fetch_register;
  CPU_REG_STORE (cpu) = bpfbf_store_register;
  CPU_PC_FETCH (cpu) = bpfbf_h_pc_get;
  CPU_PC_STORE (cpu) = bpfbf_h_pc_set;
  CPU_GET_IDATA (cpu) = bpfbf_get_idata;
  /* Only used by profiling.  0 disables it. */
  CPU_MAX_INSNS (cpu) = 0;
  CPU_INSN_NAME (cpu) = cgen_insn_name;
  CPU_FULL_ENGINE_FN (cpu) = bpf_engine_run_full;
#if WITH_FAST
  CPU_FAST_ENGINE_FN (cpu) = bpf_engine_run_fast;
#else
  CPU_FAST_ENGINE_FN (cpu) = bpf_engine_run_full;
#endif
}

static const SIM_MODEL bpf_models[] =
{
 { "bpf-def", & bpf_mach, MODEL_BPF_DEF, NULL, bpf_def_model_init },
 { 0 }
};

static const SIM_MACH_IMP_PROPERTIES bpfbf_imp_properties =
{
  sizeof (SIM_CPU),
#if WITH_SCACHE
  sizeof (SCACHE)
#else
  0
#endif
};

const SIM_MACH bpf_mach =
{
  "bpf", "bpf", MACH_BPF,
  32, 32, & bpf_models[0], & bpfbf_imp_properties,
  bpf_init_cpu,
  bpfbf_prepare_run
};
