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