1*16dce513Schristos/* FR30 opcode support. -*- C -*- 2*16dce513Schristos Copyright 2011 Free Software Foundation, Inc. 3*16dce513Schristos 4*16dce513Schristos Contributed by Red Hat Inc; 5*16dce513Schristos 6*16dce513Schristos This file is part of the GNU Binutils. 7*16dce513Schristos 8*16dce513Schristos This program is free software; you can redistribute it and/or modify 9*16dce513Schristos it under the terms of the GNU General Public License as published by 10*16dce513Schristos the Free Software Foundation; either version 3 of the License, or 11*16dce513Schristos (at your option) any later version. 12*16dce513Schristos 13*16dce513Schristos This program is distributed in the hope that it will be useful, 14*16dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 15*16dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*16dce513Schristos GNU General Public License for more details. 17*16dce513Schristos 18*16dce513Schristos You should have received a copy of the GNU General Public License 19*16dce513Schristos along with this program; if not, write to the Free Software 20*16dce513Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21*16dce513Schristos MA 02110-1301, USA. */ 22*16dce513Schristos 23*16dce513Schristos/* This file is an addendum to fr30.cpu. Heavy use of C code isn't 24*16dce513Schristos appropriate in .cpu files, so it resides here. This especially applies 25*16dce513Schristos to assembly/disassembly where parsing/printing can be quite involved. 26*16dce513Schristos Such things aren't really part of the specification of the cpu, per se, 27*16dce513Schristos so .cpu files provide the general framework and .opc files handle the 28*16dce513Schristos nitty-gritty details as necessary. 29*16dce513Schristos 30*16dce513Schristos Each section is delimited with start and end markers. 31*16dce513Schristos 32*16dce513Schristos <arch>-opc.h additions use: "-- opc.h" 33*16dce513Schristos <arch>-opc.c additions use: "-- opc.c" 34*16dce513Schristos <arch>-asm.c additions use: "-- asm.c" 35*16dce513Schristos <arch>-dis.c additions use: "-- dis.c" 36*16dce513Schristos <arch>-ibd.h additions use: "-- ibd.h". */ 37*16dce513Schristos 38*16dce513Schristos/* -- opc.h */ 39*16dce513Schristos 40*16dce513Schristos/* ??? This can be improved upon. */ 41*16dce513Schristos#undef CGEN_DIS_HASH_SIZE 42*16dce513Schristos#define CGEN_DIS_HASH_SIZE 16 43*16dce513Schristos#undef CGEN_DIS_HASH 44*16dce513Schristos#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 4) 45*16dce513Schristos 46*16dce513Schristos/* -- */ 47*16dce513Schristos 48*16dce513Schristos/* -- asm.c */ 49*16dce513Schristos/* Handle register lists for LDMx and STMx. */ 50*16dce513Schristos 51*16dce513Schristosstatic int 52*16dce513Schristosparse_register_number (const char **strp) 53*16dce513Schristos{ 54*16dce513Schristos int regno; 55*16dce513Schristos 56*16dce513Schristos if (**strp < '0' || **strp > '9') 57*16dce513Schristos return -1; /* Error. */ 58*16dce513Schristos regno = **strp - '0'; 59*16dce513Schristos ++*strp; 60*16dce513Schristos 61*16dce513Schristos if (**strp >= '0' && **strp <= '9') 62*16dce513Schristos { 63*16dce513Schristos regno = regno * 10 + (**strp - '0'); 64*16dce513Schristos ++*strp; 65*16dce513Schristos } 66*16dce513Schristos 67*16dce513Schristos return regno; 68*16dce513Schristos} 69*16dce513Schristos 70*16dce513Schristosstatic const char * 71*16dce513Schristosparse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 72*16dce513Schristos const char **strp, 73*16dce513Schristos int opindex ATTRIBUTE_UNUSED, 74*16dce513Schristos unsigned long *valuep, 75*16dce513Schristos int high_low, /* 0 == high, 1 == low. */ 76*16dce513Schristos int load_store) /* 0 == load, 1 == store. */ 77*16dce513Schristos{ 78*16dce513Schristos *valuep = 0; 79*16dce513Schristos while (**strp && **strp != ')') 80*16dce513Schristos { 81*16dce513Schristos int regno; 82*16dce513Schristos 83*16dce513Schristos if (**strp != 'R' && **strp != 'r') 84*16dce513Schristos break; 85*16dce513Schristos ++*strp; 86*16dce513Schristos 87*16dce513Schristos regno = parse_register_number (strp); 88*16dce513Schristos if (regno == -1) 89*16dce513Schristos return _("Register number is not valid"); 90*16dce513Schristos if (regno > 7 && !high_low) 91*16dce513Schristos return _("Register must be between r0 and r7"); 92*16dce513Schristos if (regno < 8 && high_low) 93*16dce513Schristos return _("Register must be between r8 and r15"); 94*16dce513Schristos 95*16dce513Schristos if (high_low) 96*16dce513Schristos regno -= 8; 97*16dce513Schristos 98*16dce513Schristos if (load_store) /* Mask is reversed for store. */ 99*16dce513Schristos *valuep |= 0x80 >> regno; 100*16dce513Schristos else 101*16dce513Schristos *valuep |= 1 << regno; 102*16dce513Schristos 103*16dce513Schristos if (**strp == ',') 104*16dce513Schristos { 105*16dce513Schristos if (*(*strp + 1) == ')') 106*16dce513Schristos break; 107*16dce513Schristos ++*strp; 108*16dce513Schristos } 109*16dce513Schristos } 110*16dce513Schristos 111*16dce513Schristos if (!*strp || **strp != ')') 112*16dce513Schristos return _("Register list is not valid"); 113*16dce513Schristos 114*16dce513Schristos return NULL; 115*16dce513Schristos} 116*16dce513Schristos 117*16dce513Schristosstatic const char * 118*16dce513Schristosparse_low_register_list_ld (CGEN_CPU_DESC cd, 119*16dce513Schristos const char **strp, 120*16dce513Schristos int opindex, 121*16dce513Schristos unsigned long *valuep) 122*16dce513Schristos{ 123*16dce513Schristos return parse_register_list (cd, strp, opindex, valuep, 124*16dce513Schristos 0 /* Low. */, 0 /* Load. */); 125*16dce513Schristos} 126*16dce513Schristos 127*16dce513Schristosstatic const char * 128*16dce513Schristosparse_hi_register_list_ld (CGEN_CPU_DESC cd, 129*16dce513Schristos const char **strp, 130*16dce513Schristos int opindex, 131*16dce513Schristos unsigned long *valuep) 132*16dce513Schristos{ 133*16dce513Schristos return parse_register_list (cd, strp, opindex, valuep, 134*16dce513Schristos 1 /* High. */, 0 /* Load. */); 135*16dce513Schristos} 136*16dce513Schristos 137*16dce513Schristosstatic const char * 138*16dce513Schristosparse_low_register_list_st (CGEN_CPU_DESC cd, 139*16dce513Schristos const char **strp, 140*16dce513Schristos int opindex, 141*16dce513Schristos unsigned long *valuep) 142*16dce513Schristos{ 143*16dce513Schristos return parse_register_list (cd, strp, opindex, valuep, 144*16dce513Schristos 0 /* Low. */, 1 /* Store. */); 145*16dce513Schristos} 146*16dce513Schristos 147*16dce513Schristosstatic const char * 148*16dce513Schristosparse_hi_register_list_st (CGEN_CPU_DESC cd, 149*16dce513Schristos const char **strp, 150*16dce513Schristos int opindex, 151*16dce513Schristos unsigned long *valuep) 152*16dce513Schristos{ 153*16dce513Schristos return parse_register_list (cd, strp, opindex, valuep, 154*16dce513Schristos 1 /* High. */, 1 /* Store. */); 155*16dce513Schristos} 156*16dce513Schristos 157*16dce513Schristos/* -- */ 158*16dce513Schristos 159*16dce513Schristos/* -- dis.c */ 160*16dce513Schristosstatic void 161*16dce513Schristosprint_register_list (void * dis_info, 162*16dce513Schristos long value, 163*16dce513Schristos long offset, 164*16dce513Schristos int load_store) /* 0 == load, 1 == store. */ 165*16dce513Schristos{ 166*16dce513Schristos disassemble_info *info = dis_info; 167*16dce513Schristos int mask; 168*16dce513Schristos int reg_index = 0; 169*16dce513Schristos char * comma = ""; 170*16dce513Schristos 171*16dce513Schristos if (load_store) 172*16dce513Schristos mask = 0x80; 173*16dce513Schristos else 174*16dce513Schristos mask = 1; 175*16dce513Schristos 176*16dce513Schristos if (value & mask) 177*16dce513Schristos { 178*16dce513Schristos (*info->fprintf_func) (info->stream, "r%li", reg_index + offset); 179*16dce513Schristos comma = ","; 180*16dce513Schristos } 181*16dce513Schristos 182*16dce513Schristos for (reg_index = 1; reg_index <= 7; ++reg_index) 183*16dce513Schristos { 184*16dce513Schristos if (load_store) 185*16dce513Schristos mask >>= 1; 186*16dce513Schristos else 187*16dce513Schristos mask <<= 1; 188*16dce513Schristos 189*16dce513Schristos if (value & mask) 190*16dce513Schristos { 191*16dce513Schristos (*info->fprintf_func) (info->stream, "%sr%li", comma, reg_index + offset); 192*16dce513Schristos comma = ","; 193*16dce513Schristos } 194*16dce513Schristos } 195*16dce513Schristos} 196*16dce513Schristos 197*16dce513Schristosstatic void 198*16dce513Schristosprint_hi_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 199*16dce513Schristos void * dis_info, 200*16dce513Schristos long value, 201*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 202*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 203*16dce513Schristos int length ATTRIBUTE_UNUSED) 204*16dce513Schristos{ 205*16dce513Schristos print_register_list (dis_info, value, 8, 0 /* Load. */); 206*16dce513Schristos} 207*16dce513Schristos 208*16dce513Schristosstatic void 209*16dce513Schristosprint_low_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 210*16dce513Schristos void * dis_info, 211*16dce513Schristos long value, 212*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 213*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 214*16dce513Schristos int length ATTRIBUTE_UNUSED) 215*16dce513Schristos{ 216*16dce513Schristos print_register_list (dis_info, value, 0, 0 /* Load. */); 217*16dce513Schristos} 218*16dce513Schristos 219*16dce513Schristosstatic void 220*16dce513Schristosprint_hi_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 221*16dce513Schristos void * dis_info, 222*16dce513Schristos long value, 223*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 224*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 225*16dce513Schristos int length ATTRIBUTE_UNUSED) 226*16dce513Schristos{ 227*16dce513Schristos print_register_list (dis_info, value, 8, 1 /* Store. */); 228*16dce513Schristos} 229*16dce513Schristos 230*16dce513Schristosstatic void 231*16dce513Schristosprint_low_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 232*16dce513Schristos void * dis_info, 233*16dce513Schristos long value, 234*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 235*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 236*16dce513Schristos int length ATTRIBUTE_UNUSED) 237*16dce513Schristos{ 238*16dce513Schristos print_register_list (dis_info, value, 0, 1 /* Store. */); 239*16dce513Schristos} 240*16dce513Schristos 241*16dce513Schristosstatic void 242*16dce513Schristosprint_m4 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 243*16dce513Schristos void * dis_info, 244*16dce513Schristos long value, 245*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 246*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 247*16dce513Schristos int length ATTRIBUTE_UNUSED) 248*16dce513Schristos{ 249*16dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 250*16dce513Schristos 251*16dce513Schristos (*info->fprintf_func) (info->stream, "%ld", value); 252*16dce513Schristos} 253*16dce513Schristos/* -- */ 254