1*16dce513Schristos/* Adapteva epiphany opcode support. -*- C -*- 2*16dce513Schristos 3*16dce513Schristos Copyright 2009, 2011 Free Software Foundation, Inc. 4*16dce513Schristos 5*16dce513Schristos Contributed by Embecosm on behalf of Adapteva, Inc. 6*16dce513Schristos 7*16dce513Schristos This file is part of the GNU Binutils and of GDB. 8*16dce513Schristos 9*16dce513Schristos This program is free software; you can redistribute it and/or modify 10*16dce513Schristos it under the terms of the GNU General Public License as published by 11*16dce513Schristos the Free Software Foundation; either version 3 of the License, or 12*16dce513Schristos (at your option) any later version. 13*16dce513Schristos 14*16dce513Schristos This program is distributed in the hope that it will be useful, 15*16dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 16*16dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*16dce513Schristos GNU General Public License for more details. 18*16dce513Schristos 19*16dce513Schristos You should have received a copy of the GNU General Public License 20*16dce513Schristos along with this program; if not, write to the Free Software 21*16dce513Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 22*16dce513Schristos MA 02110-1301, USA. */ 23*16dce513Schristos 24*16dce513Schristos/* 25*16dce513Schristos Each section is delimited with start and end markers. 26*16dce513Schristos 27*16dce513Schristos <arch>-opc.h additions use: "-- opc.h" 28*16dce513Schristos <arch>-opc.c additions use: "-- opc.c" 29*16dce513Schristos <arch>-asm.c additions use: "-- asm.c" 30*16dce513Schristos <arch>-dis.c additions use: "-- dis.c" 31*16dce513Schristos <arch>-ibd.h additions use: "-- ibd.h". */ 32*16dce513Schristos 33*16dce513Schristos/* -- opc.h */ 34*16dce513Schristos 35*16dce513Schristos/* enumerate relaxation types for gas. */ 36*16dce513Schristostypedef enum epiphany_relax_types 37*16dce513Schristos{ 38*16dce513Schristos EPIPHANY_RELAX_NONE=0, 39*16dce513Schristos EPIPHANY_RELAX_NEED_RELAXING, 40*16dce513Schristos 41*16dce513Schristos EPIPHANY_RELAX_BRANCH_SHORT, /* Fits into +127..-128 */ 42*16dce513Schristos EPIPHANY_RELAX_BRANCH_LONG, /* b/bl/b<cond> +-2*16 */ 43*16dce513Schristos 44*16dce513Schristos EPIPHANY_RELAX_ARITH_SIMM3, /* add/sub -7..3 */ 45*16dce513Schristos EPIPHANY_RELAX_ARITH_SIMM11, /* add/sub -2**11-1 .. 2**10-1 */ 46*16dce513Schristos 47*16dce513Schristos EPIPHANY_RELAX_MOV_IMM8, /* mov r,imm8 */ 48*16dce513Schristos EPIPHANY_RELAX_MOV_IMM16, /* mov r,imm16 */ 49*16dce513Schristos 50*16dce513Schristos EPIPHANY_RELAX_LDST_IMM3, /* (ldr|str)* r,[r,disp3] */ 51*16dce513Schristos EPIPHANY_RELAX_LDST_IMM11 /* (ldr|str)* r,[r,disp11] */ 52*16dce513Schristos 53*16dce513Schristos} EPIPHANY_RELAX_TYPES; 54*16dce513Schristos 55*16dce513Schristos/* Override disassembly hashing... */ 56*16dce513Schristos 57*16dce513Schristos/* Can only depend on instruction having 4 decode bits which gets us to the 58*16dce513Schristos major groups of 16/32 instructions. */ 59*16dce513Schristos#undef CGEN_DIS_HASH_SIZE 60*16dce513Schristos#if 1 61*16dce513Schristos 62*16dce513Schristos/* hash code on the 4 LSBs */ 63*16dce513Schristos#define CGEN_DIS_HASH_SIZE 16 64*16dce513Schristos 65*16dce513Schristos#define CGEN_DIS_HASH(buf, value) ((*buf) & 0xf) 66*16dce513Schristos#else 67*16dce513Schristos#define CGEN_DIS_HASH_SIZE 1 68*16dce513Schristos#define CGEN_DIS_HASH(buf, value) 0 69*16dce513Schristos#endif 70*16dce513Schristos 71*16dce513Schristosextern const char * parse_shortregs (CGEN_CPU_DESC cd, 72*16dce513Schristos const char ** strp, 73*16dce513Schristos CGEN_KEYWORD * keywords, 74*16dce513Schristos long * valuep); 75*16dce513Schristos 76*16dce513Schristosextern const char * parse_branch_addr (CGEN_CPU_DESC cd, 77*16dce513Schristos const char ** strp, 78*16dce513Schristos int opindex, 79*16dce513Schristos int opinfo, 80*16dce513Schristos enum cgen_parse_operand_result * resultp, 81*16dce513Schristos bfd_vma *valuep); 82*16dce513Schristos 83*16dce513Schristos/* Allows reason codes to be output when assembler errors occur. */ 84*16dce513Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS 85*16dce513Schristos 86*16dce513Schristos 87*16dce513Schristos/* -- opc.c */ 88*16dce513Schristos 89*16dce513Schristos 90*16dce513Schristos 91*16dce513Schristos/* -- asm.c */ 92*16dce513Schristosconst char * 93*16dce513Schristosparse_shortregs (CGEN_CPU_DESC cd, 94*16dce513Schristos const char ** strp, 95*16dce513Schristos CGEN_KEYWORD * keywords, 96*16dce513Schristos long * regno) 97*16dce513Schristos{ 98*16dce513Schristos const char * errmsg; 99*16dce513Schristos 100*16dce513Schristos /* Parse register. */ 101*16dce513Schristos errmsg = cgen_parse_keyword (cd, strp, keywords, regno); 102*16dce513Schristos 103*16dce513Schristos if (errmsg) 104*16dce513Schristos return errmsg; 105*16dce513Schristos 106*16dce513Schristos if (*regno > 7) 107*16dce513Schristos errmsg = _("register unavailable for short instructions"); 108*16dce513Schristos 109*16dce513Schristos return errmsg; 110*16dce513Schristos} 111*16dce513Schristos 112*16dce513Schristosstatic const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int, 113*16dce513Schristos long *); 114*16dce513Schristos 115*16dce513Schristosstatic const char * 116*16dce513Schristosparse_uimm_not_reg (CGEN_CPU_DESC cd, 117*16dce513Schristos const char ** strp, 118*16dce513Schristos int opindex, 119*16dce513Schristos unsigned long * valuep) 120*16dce513Schristos{ 121*16dce513Schristos long * svalp = (void *) valuep; 122*16dce513Schristos return parse_simm_not_reg (cd, strp, opindex, svalp); 123*16dce513Schristos} 124*16dce513Schristos 125*16dce513Schristos/* Handle simm3/simm11/imm3/imm12. */ 126*16dce513Schristos 127*16dce513Schristosstatic const char * 128*16dce513Schristosparse_simm_not_reg (CGEN_CPU_DESC cd, 129*16dce513Schristos const char ** strp, 130*16dce513Schristos int opindex, 131*16dce513Schristos long * valuep) 132*16dce513Schristos{ 133*16dce513Schristos const char * errmsg; 134*16dce513Schristos 135*16dce513Schristos int sign = 0; 136*16dce513Schristos int bits = 0; 137*16dce513Schristos 138*16dce513Schristos switch (opindex) 139*16dce513Schristos { 140*16dce513Schristos case EPIPHANY_OPERAND_SIMM3: 141*16dce513Schristos sign = 1; bits = 3; break; 142*16dce513Schristos case EPIPHANY_OPERAND_SIMM11: 143*16dce513Schristos sign = 1; bits = 11; break; 144*16dce513Schristos case EPIPHANY_OPERAND_DISP3: 145*16dce513Schristos sign = 0; bits = 3; break; 146*16dce513Schristos case EPIPHANY_OPERAND_DISP11: 147*16dce513Schristos /* Load/store displacement is a sign-magnitude 12 bit value. */ 148*16dce513Schristos sign = 0; bits = 11; break; 149*16dce513Schristos } 150*16dce513Schristos 151*16dce513Schristos /* First try to parse as a register name and reject the operand. */ 152*16dce513Schristos errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep); 153*16dce513Schristos if (!errmsg) 154*16dce513Schristos return _("register name used as immediate value"); 155*16dce513Schristos 156*16dce513Schristos errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep) 157*16dce513Schristos : cgen_parse_unsigned_integer (cd, strp, opindex, 158*16dce513Schristos (unsigned long *) valuep)); 159*16dce513Schristos if (errmsg) 160*16dce513Schristos return errmsg; 161*16dce513Schristos 162*16dce513Schristos if (sign) 163*16dce513Schristos errmsg = cgen_validate_signed_integer (*valuep, 164*16dce513Schristos -((1L << bits) - 1), (1 << (bits - 1)) - 1); 165*16dce513Schristos else 166*16dce513Schristos errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1); 167*16dce513Schristos 168*16dce513Schristos return errmsg; 169*16dce513Schristos} 170*16dce513Schristos 171*16dce513Schristosstatic const char * 172*16dce513Schristosparse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 173*16dce513Schristos const char ** strp, 174*16dce513Schristos int opindex ATTRIBUTE_UNUSED, 175*16dce513Schristos unsigned long *valuep) 176*16dce513Schristos{ 177*16dce513Schristos if (**strp == '#') 178*16dce513Schristos ++*strp; /* Skip leading hashes. */ 179*16dce513Schristos 180*16dce513Schristos if (**strp == '-') 181*16dce513Schristos { 182*16dce513Schristos *valuep = 1; 183*16dce513Schristos ++*strp; 184*16dce513Schristos } 185*16dce513Schristos else if (**strp == '+') 186*16dce513Schristos { 187*16dce513Schristos *valuep = 0; 188*16dce513Schristos ++*strp; 189*16dce513Schristos } 190*16dce513Schristos else 191*16dce513Schristos *valuep = 0; 192*16dce513Schristos 193*16dce513Schristos return NULL; 194*16dce513Schristos} 195*16dce513Schristos 196*16dce513Schristosstatic const char * 197*16dce513Schristosparse_imm8 (CGEN_CPU_DESC cd, 198*16dce513Schristos const char ** strp, 199*16dce513Schristos int opindex, 200*16dce513Schristos bfd_reloc_code_real_type code, 201*16dce513Schristos enum cgen_parse_operand_result * result_type, 202*16dce513Schristos bfd_vma * valuep) 203*16dce513Schristos{ 204*16dce513Schristos const char * errmsg; 205*16dce513Schristos enum cgen_parse_operand_result rt; 206*16dce513Schristos long dummyval; 207*16dce513Schristos 208*16dce513Schristos if (!result_type) 209*16dce513Schristos result_type = &rt; 210*16dce513Schristos 211*16dce513Schristos code = BFD_RELOC_NONE; 212*16dce513Schristos 213*16dce513Schristos if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval) 214*16dce513Schristos || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names, 215*16dce513Schristos &dummyval)) 216*16dce513Schristos /* Don't treat "mov ip,ip" as a move-immediate. */ 217*16dce513Schristos return _("register source in immediate move"); 218*16dce513Schristos 219*16dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep); 220*16dce513Schristos if (errmsg) 221*16dce513Schristos return errmsg; 222*16dce513Schristos 223*16dce513Schristos if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 224*16dce513Schristos errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff); 225*16dce513Schristos else 226*16dce513Schristos errmsg = _("byte relocation unsupported"); 227*16dce513Schristos 228*16dce513Schristos *valuep &= 0xff; 229*16dce513Schristos return errmsg; 230*16dce513Schristos} 231*16dce513Schristos 232*16dce513Schristosstatic const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'"); 233*16dce513Schristos 234*16dce513Schristosstatic const char * 235*16dce513Schristosparse_imm16 (CGEN_CPU_DESC cd, 236*16dce513Schristos const char ** strp, 237*16dce513Schristos int opindex, 238*16dce513Schristos bfd_reloc_code_real_type code ATTRIBUTE_UNUSED, 239*16dce513Schristos enum cgen_parse_operand_result * result_type, 240*16dce513Schristos bfd_vma * valuep) 241*16dce513Schristos{ 242*16dce513Schristos const char * errmsg; 243*16dce513Schristos enum cgen_parse_operand_result rt; 244*16dce513Schristos long dummyval; 245*16dce513Schristos 246*16dce513Schristos if (!result_type) 247*16dce513Schristos result_type = &rt; 248*16dce513Schristos 249*16dce513Schristos if (strncasecmp (*strp, "%high(", 6) == 0) 250*16dce513Schristos { 251*16dce513Schristos *strp += 6; 252*16dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH, 253*16dce513Schristos result_type, valuep); 254*16dce513Schristos if (**strp != ')') 255*16dce513Schristos return MISSING_CLOSE_PARENTHESIS; 256*16dce513Schristos ++*strp; 257*16dce513Schristos *valuep >>= 16; 258*16dce513Schristos } 259*16dce513Schristos else if (strncasecmp (*strp, "%low(", 5) == 0) 260*16dce513Schristos { 261*16dce513Schristos *strp += 5; 262*16dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW, 263*16dce513Schristos result_type, valuep); 264*16dce513Schristos if (**strp != ')') 265*16dce513Schristos return MISSING_CLOSE_PARENTHESIS; 266*16dce513Schristos ++*strp; 267*16dce513Schristos } 268*16dce513Schristos else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, 269*16dce513Schristos &dummyval) 270*16dce513Schristos || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names, 271*16dce513Schristos &dummyval)) 272*16dce513Schristos /* Don't treat "mov ip,ip" as a move-immediate. */ 273*16dce513Schristos return _("register source in immediate move"); 274*16dce513Schristos else 275*16dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16, 276*16dce513Schristos result_type, valuep); 277*16dce513Schristos 278*16dce513Schristos if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 279*16dce513Schristos errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff); 280*16dce513Schristos 281*16dce513Schristos *valuep &= 0xffff; 282*16dce513Schristos return errmsg; 283*16dce513Schristos} 284*16dce513Schristos 285*16dce513Schristosconst char * 286*16dce513Schristosparse_branch_addr (CGEN_CPU_DESC cd, 287*16dce513Schristos const char ** strp, 288*16dce513Schristos int opindex, 289*16dce513Schristos int opinfo ATTRIBUTE_UNUSED, 290*16dce513Schristos enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED, 291*16dce513Schristos bfd_vma *valuep ATTRIBUTE_UNUSED) 292*16dce513Schristos{ 293*16dce513Schristos const char * errmsg; 294*16dce513Schristos enum cgen_parse_operand_result result_type; 295*16dce513Schristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 296*16dce513Schristos bfd_vma value; 297*16dce513Schristos 298*16dce513Schristos switch (opindex) 299*16dce513Schristos { 300*16dce513Schristos case EPIPHANY_OPERAND_SIMM24: 301*16dce513Schristos code = BFD_RELOC_EPIPHANY_SIMM24; 302*16dce513Schristos break; 303*16dce513Schristos 304*16dce513Schristos case EPIPHANY_OPERAND_SIMM8: 305*16dce513Schristos code = BFD_RELOC_EPIPHANY_SIMM8; 306*16dce513Schristos break; 307*16dce513Schristos 308*16dce513Schristos default: 309*16dce513Schristos errmsg = _("ABORT: unknown operand"); 310*16dce513Schristos return errmsg; 311*16dce513Schristos } 312*16dce513Schristos 313*16dce513Schristos errmsg = cgen_parse_address (cd, strp, opindex, code, 314*16dce513Schristos &result_type, &value); 315*16dce513Schristos if (errmsg == NULL) 316*16dce513Schristos { 317*16dce513Schristos if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 318*16dce513Schristos { 319*16dce513Schristos /* Act as if we had done a PC-relative branch, ala .+num. */ 320*16dce513Schristos char buf[20]; 321*16dce513Schristos const char * bufp = (const char *) buf; 322*16dce513Schristos 323*16dce513Schristos sprintf (buf, ".+%ld", (long) value); 324*16dce513Schristos errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type, 325*16dce513Schristos &value); 326*16dce513Schristos } 327*16dce513Schristos 328*16dce513Schristos if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED) 329*16dce513Schristos { 330*16dce513Schristos /* This will happen for things like (s2-s1) where s2 and s1 331*16dce513Schristos are labels. */ 332*16dce513Schristos /* Nothing further to be done. */ 333*16dce513Schristos } 334*16dce513Schristos else 335*16dce513Schristos errmsg = _("Not a pc-relative address."); 336*16dce513Schristos } 337*16dce513Schristos return errmsg; 338*16dce513Schristos} 339*16dce513Schristos 340*16dce513Schristos/* -- dis.c */ 341*16dce513Schristos 342*16dce513Schristos#define CGEN_PRINT_INSN epiphany_print_insn 343*16dce513Schristos 344*16dce513Schristosstatic int 345*16dce513Schristosepiphany_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 346*16dce513Schristos{ 347*16dce513Schristos bfd_byte buf[CGEN_MAX_INSN_SIZE]; 348*16dce513Schristos int buflen; 349*16dce513Schristos int status; 350*16dce513Schristos 351*16dce513Schristos info->bytes_per_chunk = 2; 352*16dce513Schristos info->bytes_per_line = 4; 353*16dce513Schristos 354*16dce513Schristos /* Attempt to read the base part of the insn. */ 355*16dce513Schristos buflen = cd->base_insn_bitsize / 8; 356*16dce513Schristos status = (*info->read_memory_func) (pc, buf, buflen, info); 357*16dce513Schristos 358*16dce513Schristos /* Try again with the minimum part, if min < base. */ 359*16dce513Schristos if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) 360*16dce513Schristos { 361*16dce513Schristos buflen = cd->min_insn_bitsize / 8; 362*16dce513Schristos status = (*info->read_memory_func) (pc, buf, buflen, info); 363*16dce513Schristos } 364*16dce513Schristos 365*16dce513Schristos if (status != 0) 366*16dce513Schristos { 367*16dce513Schristos (*info->memory_error_func) (status, pc, info); 368*16dce513Schristos return -1; 369*16dce513Schristos } 370*16dce513Schristos 371*16dce513Schristos return print_insn (cd, pc, info, buf, buflen); 372*16dce513Schristos} 373*16dce513Schristos 374*16dce513Schristos 375*16dce513Schristosstatic void 376*16dce513Schristosprint_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 377*16dce513Schristos void * dis_info, 378*16dce513Schristos long value, 379*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 380*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 381*16dce513Schristos int length ATTRIBUTE_UNUSED) 382*16dce513Schristos{ 383*16dce513Schristos disassemble_info *info = (disassemble_info *) dis_info; 384*16dce513Schristos (*info->fprintf_func) (info->stream, value ? "-" : "+"); 385*16dce513Schristos} 386*16dce513Schristos 387*16dce513Schristosstatic void 388*16dce513Schristosprint_simm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 389*16dce513Schristos void * dis_info, 390*16dce513Schristos long value, 391*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 392*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 393*16dce513Schristos int length ATTRIBUTE_UNUSED) 394*16dce513Schristos{ 395*16dce513Schristos print_address (cd, dis_info, value, attrs, pc, length); 396*16dce513Schristos} 397*16dce513Schristos 398*16dce513Schristosstatic void 399*16dce513Schristosprint_uimm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 400*16dce513Schristos void * dis_info, 401*16dce513Schristos unsigned long value, 402*16dce513Schristos unsigned int attrs ATTRIBUTE_UNUSED, 403*16dce513Schristos bfd_vma pc ATTRIBUTE_UNUSED, 404*16dce513Schristos int length ATTRIBUTE_UNUSED) 405*16dce513Schristos{ 406*16dce513Schristos disassemble_info *info = (disassemble_info *)dis_info; 407*16dce513Schristos 408*16dce513Schristos if (value & 0x800) 409*16dce513Schristos (*info->fprintf_func) (info->stream, "-"); 410*16dce513Schristos 411*16dce513Schristos value &= 0x7ff; 412*16dce513Schristos print_address (cd, dis_info, value, attrs, pc, length); 413*16dce513Schristos} 414*16dce513Schristos 415*16dce513Schristos 416*16dce513Schristos/* -- */ 417*16dce513Schristos 418