xref: /netbsd-src/external/gpl3/binutils.old/dist/cpu/bpf.opc (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1*867d70fcSchristos/* EBPF opcode support.  -*- c -*-
2*867d70fcSchristos
3*867d70fcSchristos   Copyright (C) 2019 Free Software Foundation, Inc.
4*867d70fcSchristos
5*867d70fcSchristos   Contributed by Oracle, Inc.
6*867d70fcSchristos
7*867d70fcSchristos   This file is part of the GNU Binutils and of GDB.
8*867d70fcSchristos
9*867d70fcSchristos   This program is free software; you can redistribute it and/or modify
10*867d70fcSchristos   it under the terms of the GNU General Public License as published by
11*867d70fcSchristos   the Free Software Foundation; either version 3 of the License, or
12*867d70fcSchristos   (at your option) any later version.
13*867d70fcSchristos
14*867d70fcSchristos   This program is distributed in the hope that it will be useful,
15*867d70fcSchristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
16*867d70fcSchristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*867d70fcSchristos   GNU General Public License for more details.
18*867d70fcSchristos
19*867d70fcSchristos   You should have received a copy of the GNU General Public License
20*867d70fcSchristos   along with this program; if not, write to the Free Software
21*867d70fcSchristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22*867d70fcSchristos   MA 02110-1301, USA.  */
23*867d70fcSchristos
24*867d70fcSchristos/*
25*867d70fcSchristos   Each section is delimited with start and end markers.
26*867d70fcSchristos
27*867d70fcSchristos   <arch>-opc.h additions use: "-- opc.h"
28*867d70fcSchristos   <arch>-opc.c additions use: "-- opc.c"
29*867d70fcSchristos   <arch>-asm.c additions use: "-- asm.c"
30*867d70fcSchristos   <arch>-dis.c additions use: "-- dis.c"
31*867d70fcSchristos   <arch>-ibd.h additions use: "-- ibd.h".  */
32*867d70fcSchristos
33*867d70fcSchristos/* -- opc.h */
34*867d70fcSchristos
35*867d70fcSchristos#undef CGEN_DIS_HASH_SIZE
36*867d70fcSchristos#define CGEN_DIS_HASH_SIZE 1
37*867d70fcSchristos
38*867d70fcSchristos#undef CGEN_DIS_HASH
39*867d70fcSchristos#define CGEN_DIS_HASH(buffer, value) 0
40*867d70fcSchristos
41*867d70fcSchristos/* Allows reason codes to be output when assembler errors occur.  */
42*867d70fcSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
43*867d70fcSchristos
44*867d70fcSchristos#define CGEN_VALIDATE_INSN_SUPPORTED
45*867d70fcSchristosextern int bpf_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
46*867d70fcSchristos
47*867d70fcSchristos
48*867d70fcSchristos/* -- opc.c */
49*867d70fcSchristos
50*867d70fcSchristos/* -- asm.c */
51*867d70fcSchristos
52*867d70fcSchristos/* Parse a signed 64-bit immediate.  */
53*867d70fcSchristos
54*867d70fcSchristosstatic const char *
55*867d70fcSchristosparse_imm64 (CGEN_CPU_DESC cd,
56*867d70fcSchristos             const char **strp,
57*867d70fcSchristos             int opindex,
58*867d70fcSchristos             int64_t *valuep)
59*867d70fcSchristos{
60*867d70fcSchristos  bfd_vma value;
61*867d70fcSchristos  enum cgen_parse_operand_result result;
62*867d70fcSchristos  const char *errmsg;
63*867d70fcSchristos
64*867d70fcSchristos  errmsg = (* cd->parse_operand_fn)
65*867d70fcSchristos    (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
66*867d70fcSchristos     &result, &value);
67*867d70fcSchristos  if (!errmsg)
68*867d70fcSchristos    *valuep = value;
69*867d70fcSchristos
70*867d70fcSchristos  return errmsg;
71*867d70fcSchristos}
72*867d70fcSchristos
73*867d70fcSchristos/* Endianness size operands are integer immediates whose values can be
74*867d70fcSchristos   16, 32 or 64.  */
75*867d70fcSchristos
76*867d70fcSchristosstatic const char *
77*867d70fcSchristosparse_endsize (CGEN_CPU_DESC cd,
78*867d70fcSchristos               const char **strp,
79*867d70fcSchristos               int opindex,
80*867d70fcSchristos               unsigned long *valuep)
81*867d70fcSchristos{
82*867d70fcSchristos  const char *errmsg;
83*867d70fcSchristos
84*867d70fcSchristos  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
85*867d70fcSchristos  if (errmsg)
86*867d70fcSchristos    return errmsg;
87*867d70fcSchristos
88*867d70fcSchristos  switch (*valuep)
89*867d70fcSchristos    {
90*867d70fcSchristos    case 16:
91*867d70fcSchristos    case 32:
92*867d70fcSchristos    case 64:
93*867d70fcSchristos      break;
94*867d70fcSchristos    default:
95*867d70fcSchristos      return _("expected 16, 32 or 64 in");
96*867d70fcSchristos    }
97*867d70fcSchristos
98*867d70fcSchristos  return NULL;
99*867d70fcSchristos}
100*867d70fcSchristos
101*867d70fcSchristos/* Special check to ensure that the right instruction variant is used
102*867d70fcSchristos   for the given endianness induced by the ISA selected in the CPU.
103*867d70fcSchristos   See bpf.cpu for a discussion on how eBPF is really two instruction
104*867d70fcSchristos   sets.  */
105*867d70fcSchristos
106*867d70fcSchristosint
107*867d70fcSchristosbpf_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
108*867d70fcSchristos{
109*867d70fcSchristos  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
110*867d70fcSchristos
111*867d70fcSchristos  return cgen_bitset_intersect_p (&isas, cd->isas);
112*867d70fcSchristos}
113*867d70fcSchristos
114*867d70fcSchristos
115*867d70fcSchristos/* -- dis.c */
116*867d70fcSchristos
117*867d70fcSchristos/* We need to customize the disassembler a bit:
118*867d70fcSchristos   - Use 8 bytes per line by default.
119*867d70fcSchristos*/
120*867d70fcSchristos
121*867d70fcSchristos#define CGEN_PRINT_INSN bpf_print_insn
122*867d70fcSchristos
123*867d70fcSchristosstatic int
124*867d70fcSchristosbpf_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
125*867d70fcSchristos{
126*867d70fcSchristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
127*867d70fcSchristos  int buflen;
128*867d70fcSchristos  int status;
129*867d70fcSchristos
130*867d70fcSchristos  info->bytes_per_chunk = 1;
131*867d70fcSchristos  info->bytes_per_line = 8;
132*867d70fcSchristos
133*867d70fcSchristos  /* Attempt to read the base part of the insn.  */
134*867d70fcSchristos  buflen = cd->base_insn_bitsize / 8;
135*867d70fcSchristos  status = (*info->read_memory_func) (pc, buf, buflen, info);
136*867d70fcSchristos
137*867d70fcSchristos  /* Try again with the minimum part, if min < base.  */
138*867d70fcSchristos  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
139*867d70fcSchristos    {
140*867d70fcSchristos      buflen = cd->min_insn_bitsize / 8;
141*867d70fcSchristos      status = (*info->read_memory_func) (pc, buf, buflen, info);
142*867d70fcSchristos    }
143*867d70fcSchristos
144*867d70fcSchristos  if (status != 0)
145*867d70fcSchristos    {
146*867d70fcSchristos      (*info->memory_error_func) (status, pc, info);
147*867d70fcSchristos      return -1;
148*867d70fcSchristos    }
149*867d70fcSchristos
150*867d70fcSchristos  return print_insn (cd, pc, info, buf, buflen);
151*867d70fcSchristos}
152*867d70fcSchristos
153*867d70fcSchristos/* Signed immediates should be printed in hexadecimal.  */
154*867d70fcSchristos
155*867d70fcSchristosstatic void
156*867d70fcSchristosprint_immediate (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
157*867d70fcSchristos                 void *dis_info,
158*867d70fcSchristos                 int64_t value,
159*867d70fcSchristos                 unsigned int attrs ATTRIBUTE_UNUSED,
160*867d70fcSchristos                 bfd_vma pc ATTRIBUTE_UNUSED,
161*867d70fcSchristos                 int length ATTRIBUTE_UNUSED)
162*867d70fcSchristos{
163*867d70fcSchristos  disassemble_info *info = (disassemble_info *) dis_info;
164*867d70fcSchristos
165*867d70fcSchristos  if (value <= 9)
166*867d70fcSchristos    (*info->fprintf_func) (info->stream, "%" PRId64, value);
167*867d70fcSchristos  else
168*867d70fcSchristos    (*info->fprintf_func) (info->stream, "%#" PRIx64, value);
169*867d70fcSchristos
170*867d70fcSchristos  /* This is to avoid -Wunused-function for print_normal.  */
171*867d70fcSchristos  if (0)
172*867d70fcSchristos    print_normal (cd, dis_info, value, attrs, pc, length);
173*867d70fcSchristos}
174*867d70fcSchristos
175*867d70fcSchristos/* Endianness bit sizes should be printed in decimal.  */
176*867d70fcSchristos
177*867d70fcSchristosstatic void
178*867d70fcSchristosprint_endsize (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
179*867d70fcSchristos               void *dis_info,
180*867d70fcSchristos               unsigned long value,
181*867d70fcSchristos               unsigned int attrs ATTRIBUTE_UNUSED,
182*867d70fcSchristos               bfd_vma pc ATTRIBUTE_UNUSED,
183*867d70fcSchristos               int length ATTRIBUTE_UNUSED)
184*867d70fcSchristos{
185*867d70fcSchristos  disassemble_info *info = (disassemble_info *) dis_info;
186*867d70fcSchristos  (*info->fprintf_func) (info->stream, "%lu", value);
187*867d70fcSchristos}
188*867d70fcSchristos
189*867d70fcSchristos
190*867d70fcSchristos/* -- */
191*867d70fcSchristos
192