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