123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- /* EBPF opcode support. -*- c -*-
- Copyright (C) 2019 Free Software Foundation, Inc.
- Contributed by Oracle, Inc.
- This file is part of the GNU Binutils and of GDB.
- 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, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
- /*
- Each section is delimited with start and end markers.
- <arch>-opc.h additions use: "-- opc.h"
- <arch>-opc.c additions use: "-- opc.c"
- <arch>-asm.c additions use: "-- asm.c"
- <arch>-dis.c additions use: "-- dis.c"
- <arch>-ibd.h additions use: "-- ibd.h". */
- /* -- opc.h */
- #undef CGEN_DIS_HASH_SIZE
- #define CGEN_DIS_HASH_SIZE 1
- #undef CGEN_DIS_HASH
- #define CGEN_DIS_HASH(buffer, value) 0
- /* Allows reason codes to be output when assembler errors occur. */
- #define CGEN_VERBOSE_ASSEMBLER_ERRORS
- #define CGEN_VALIDATE_INSN_SUPPORTED
- extern int bpf_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
- /* -- opc.c */
- /* -- asm.c */
- /* Parse a signed 64-bit immediate. */
- static const char *
- parse_imm64 (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- int64_t *valuep)
- {
- bfd_vma value;
- enum cgen_parse_operand_result result;
- const char *errmsg;
- errmsg = (* cd->parse_operand_fn)
- (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
- &result, &value);
- if (!errmsg)
- *valuep = value;
- return errmsg;
- }
- /* Endianness size operands are integer immediates whose values can be
- 16, 32 or 64. */
- static const char *
- parse_endsize (CGEN_CPU_DESC cd,
- const char **strp,
- int opindex,
- unsigned long *valuep)
- {
- const char *errmsg;
- errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
- if (errmsg)
- return errmsg;
- switch (*valuep)
- {
- case 16:
- case 32:
- case 64:
- break;
- default:
- return _("expected 16, 32 or 64 in");
- }
- return NULL;
- }
- /* Special check to ensure that the right instruction variant is used
- for the given endianness induced by the ISA selected in the CPU.
- See bpf.cpu for a discussion on how eBPF is really two instruction
- sets. */
- int
- bpf_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
- {
- CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
- return cgen_bitset_intersect_p (&isas, cd->isas);
- }
- /* -- dis.c */
- /* We need to customize the disassembler a bit:
- - Use 8 bytes per line by default.
- */
- #define CGEN_PRINT_INSN bpf_print_insn
- static int
- bpf_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
- {
- bfd_byte buf[CGEN_MAX_INSN_SIZE];
- int buflen;
- int status;
- info->bytes_per_chunk = 1;
- info->bytes_per_line = 8;
- /* Attempt to read the base part of the insn. */
- buflen = cd->base_insn_bitsize / 8;
- status = (*info->read_memory_func) (pc, buf, buflen, info);
- /* Try again with the minimum part, if min < base. */
- if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
- {
- buflen = cd->min_insn_bitsize / 8;
- status = (*info->read_memory_func) (pc, buf, buflen, info);
- }
- if (status != 0)
- {
- (*info->memory_error_func) (status, pc, info);
- return -1;
- }
- return print_insn (cd, pc, info, buf, buflen);
- }
- /* Signed immediates should be printed in hexadecimal. */
- static void
- print_immediate (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
- void *dis_info,
- int64_t value,
- unsigned int attrs ATTRIBUTE_UNUSED,
- bfd_vma pc ATTRIBUTE_UNUSED,
- int length ATTRIBUTE_UNUSED)
- {
- disassemble_info *info = (disassemble_info *) dis_info;
- if (value <= 9)
- (*info->fprintf_func) (info->stream, "%" PRId64, value);
- else
- (*info->fprintf_func) (info->stream, "%#" PRIx64, value);
- /* This is to avoid -Wunused-function for print_normal. */
- if (0)
- print_normal (cd, dis_info, value, attrs, pc, length);
- }
- /* Endianness bit sizes should be printed in decimal. */
- static void
- print_endsize (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
- void *dis_info,
- unsigned long value,
- unsigned int attrs ATTRIBUTE_UNUSED,
- bfd_vma pc ATTRIBUTE_UNUSED,
- int length ATTRIBUTE_UNUSED)
- {
- disassemble_info *info = (disassemble_info *) dis_info;
- (*info->fprintf_func) (info->stream, "%lu", value);
- }
- /* -- */
|