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