1*a2e2270fSchristos/* IP2K opcode support. -*- C -*- 2*a2e2270fSchristos Copyright 2002, 2005, 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/* 24*a2e2270fSchristos Each section is delimited with start and end markers. 25*a2e2270fSchristos 26*a2e2270fSchristos <arch>-opc.h additions use: "-- opc.h" 27*a2e2270fSchristos <arch>-opc.c additions use: "-- opc.c" 28*a2e2270fSchristos <arch>-asm.c additions use: "-- asm.c" 29*a2e2270fSchristos <arch>-dis.c additions use: "-- dis.c" 30*a2e2270fSchristos <arch>-ibd.h additions use: "-- ibd.h". */ 31*a2e2270fSchristos 32*a2e2270fSchristos/* -- opc.h */ 33*a2e2270fSchristos 34*a2e2270fSchristos/* Check applicability of instructions against machines. */ 35*a2e2270fSchristos#define CGEN_VALIDATE_INSN_SUPPORTED 36*a2e2270fSchristos 37*a2e2270fSchristos/* Allows reason codes to be output when assembler errors occur. */ 38*a2e2270fSchristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS 39*a2e2270fSchristos 40*a2e2270fSchristos/* Override disassembly hashing - there are variable bits in the top 41*a2e2270fSchristos byte of these instructions. */ 42*a2e2270fSchristos#define CGEN_DIS_HASH_SIZE 8 43*a2e2270fSchristos#define CGEN_DIS_HASH(buf, value) \ 44*a2e2270fSchristos (((* (unsigned char*) (buf)) >> 5) % CGEN_DIS_HASH_SIZE) 45*a2e2270fSchristos 46*a2e2270fSchristos#define CGEN_ASM_HASH_SIZE 127 47*a2e2270fSchristos#define CGEN_ASM_HASH(insn) ip2k_asm_hash (insn) 48*a2e2270fSchristos 49*a2e2270fSchristosextern unsigned int ip2k_asm_hash (const char *); 50*a2e2270fSchristosextern int ip2k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); 51*a2e2270fSchristos 52*a2e2270fSchristos/* -- opc.c */ 53*a2e2270fSchristos 54*a2e2270fSchristos#include "safe-ctype.h" 55*a2e2270fSchristos 56*a2e2270fSchristos/* A better hash function for instruction mnemonics. */ 57*a2e2270fSchristosunsigned int 58*a2e2270fSchristosip2k_asm_hash (const char* insn) 59*a2e2270fSchristos{ 60*a2e2270fSchristos unsigned int hash; 61*a2e2270fSchristos const char* m = insn; 62*a2e2270fSchristos 63*a2e2270fSchristos for (hash = 0; *m && ! ISSPACE (*m); m++) 64*a2e2270fSchristos hash = (hash * 23) ^ (0x1F & TOLOWER (*m)); 65*a2e2270fSchristos 66*a2e2270fSchristos /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */ 67*a2e2270fSchristos 68*a2e2270fSchristos return hash % CGEN_ASM_HASH_SIZE; 69*a2e2270fSchristos} 70*a2e2270fSchristos 71*a2e2270fSchristos 72*a2e2270fSchristos/* Special check to ensure that instruction exists for given machine. */ 73*a2e2270fSchristos 74*a2e2270fSchristosint 75*a2e2270fSchristosip2k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn) 76*a2e2270fSchristos{ 77*a2e2270fSchristos int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); 78*a2e2270fSchristos 79*a2e2270fSchristos /* No mach attribute? Assume it's supported for all machs. */ 80*a2e2270fSchristos if (machs == 0) 81*a2e2270fSchristos return 1; 82*a2e2270fSchristos 83*a2e2270fSchristos return (machs & cd->machs) != 0; 84*a2e2270fSchristos} 85*a2e2270fSchristos 86*a2e2270fSchristos 87*a2e2270fSchristos/* -- asm.c */ 88*a2e2270fSchristos 89*a2e2270fSchristosstatic const char * 90*a2e2270fSchristosparse_fr (CGEN_CPU_DESC cd, 91*a2e2270fSchristos const char **strp, 92*a2e2270fSchristos int opindex, 93*a2e2270fSchristos unsigned long *valuep) 94*a2e2270fSchristos{ 95*a2e2270fSchristos const char *errmsg; 96*a2e2270fSchristos const char *old_strp; 97*a2e2270fSchristos char *afteroffset; 98*a2e2270fSchristos enum cgen_parse_operand_result result_type; 99*a2e2270fSchristos bfd_vma value; 100*a2e2270fSchristos extern CGEN_KEYWORD ip2k_cgen_opval_register_names; 101*a2e2270fSchristos bfd_vma tempvalue; 102*a2e2270fSchristos 103*a2e2270fSchristos old_strp = *strp; 104*a2e2270fSchristos afteroffset = NULL; 105*a2e2270fSchristos 106*a2e2270fSchristos /* Check here to see if you're about to try parsing a w as the first arg 107*a2e2270fSchristos and return an error if you are. */ 108*a2e2270fSchristos if ((strncmp (*strp, "w", 1) == 0) || (strncmp (*strp, "W", 1) == 0)) 109*a2e2270fSchristos { 110*a2e2270fSchristos (*strp)++; 111*a2e2270fSchristos 112*a2e2270fSchristos if ((strncmp (*strp, ",", 1) == 0) || ISSPACE (**strp)) 113*a2e2270fSchristos { 114*a2e2270fSchristos /* We've been passed a w. Return with an error message so that 115*a2e2270fSchristos cgen will try the next parsing option. */ 116*a2e2270fSchristos errmsg = _("W keyword invalid in FR operand slot."); 117*a2e2270fSchristos return errmsg; 118*a2e2270fSchristos } 119*a2e2270fSchristos *strp = old_strp; 120*a2e2270fSchristos } 121*a2e2270fSchristos 122*a2e2270fSchristos /* Attempt parse as register keyword. */ 123*a2e2270fSchristos errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names, 124*a2e2270fSchristos (long *) valuep); 125*a2e2270fSchristos if (*strp != NULL 126*a2e2270fSchristos && errmsg == NULL) 127*a2e2270fSchristos return errmsg; 128*a2e2270fSchristos 129*a2e2270fSchristos /* Attempt to parse for "(IP)". */ 130*a2e2270fSchristos afteroffset = strstr (*strp, "(IP)"); 131*a2e2270fSchristos 132*a2e2270fSchristos if (afteroffset == NULL) 133*a2e2270fSchristos /* Make sure it's not in lower case. */ 134*a2e2270fSchristos afteroffset = strstr (*strp, "(ip)"); 135*a2e2270fSchristos 136*a2e2270fSchristos if (afteroffset != NULL) 137*a2e2270fSchristos { 138*a2e2270fSchristos if (afteroffset != *strp) 139*a2e2270fSchristos { 140*a2e2270fSchristos /* Invalid offset present. */ 141*a2e2270fSchristos errmsg = _("offset(IP) is not a valid form"); 142*a2e2270fSchristos return errmsg; 143*a2e2270fSchristos } 144*a2e2270fSchristos else 145*a2e2270fSchristos { 146*a2e2270fSchristos *strp += 4; 147*a2e2270fSchristos *valuep = 0; 148*a2e2270fSchristos errmsg = NULL; 149*a2e2270fSchristos return errmsg; 150*a2e2270fSchristos } 151*a2e2270fSchristos } 152*a2e2270fSchristos 153*a2e2270fSchristos /* Attempt to parse for DP. ex: mov w, offset(DP) 154*a2e2270fSchristos mov offset(DP),w */ 155*a2e2270fSchristos 156*a2e2270fSchristos /* Try parsing it as an address and see what comes back. */ 157*a2e2270fSchristos afteroffset = strstr (*strp, "(DP)"); 158*a2e2270fSchristos 159*a2e2270fSchristos if (afteroffset == NULL) 160*a2e2270fSchristos /* Maybe it's in lower case. */ 161*a2e2270fSchristos afteroffset = strstr (*strp, "(dp)"); 162*a2e2270fSchristos 163*a2e2270fSchristos if (afteroffset != NULL) 164*a2e2270fSchristos { 165*a2e2270fSchristos if (afteroffset == *strp) 166*a2e2270fSchristos { 167*a2e2270fSchristos /* No offset present. Use 0 by default. */ 168*a2e2270fSchristos tempvalue = 0; 169*a2e2270fSchristos errmsg = NULL; 170*a2e2270fSchristos } 171*a2e2270fSchristos else 172*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, 173*a2e2270fSchristos BFD_RELOC_IP2K_FR_OFFSET, 174*a2e2270fSchristos & result_type, & tempvalue); 175*a2e2270fSchristos 176*a2e2270fSchristos if (errmsg == NULL) 177*a2e2270fSchristos { 178*a2e2270fSchristos if (tempvalue <= 127) 179*a2e2270fSchristos { 180*a2e2270fSchristos /* Value is ok. Fix up the first 2 bits and return. */ 181*a2e2270fSchristos *valuep = 0x0100 | tempvalue; 182*a2e2270fSchristos *strp += 4; /* Skip over the (DP) in *strp. */ 183*a2e2270fSchristos return errmsg; 184*a2e2270fSchristos } 185*a2e2270fSchristos else 186*a2e2270fSchristos { 187*a2e2270fSchristos /* Found something there in front of (DP) but it's out 188*a2e2270fSchristos of range. */ 189*a2e2270fSchristos errmsg = _("(DP) offset out of range."); 190*a2e2270fSchristos return errmsg; 191*a2e2270fSchristos } 192*a2e2270fSchristos } 193*a2e2270fSchristos } 194*a2e2270fSchristos 195*a2e2270fSchristos 196*a2e2270fSchristos /* Attempt to parse for SP. ex: mov w, offset(SP) 197*a2e2270fSchristos mov offset(SP), w. */ 198*a2e2270fSchristos afteroffset = strstr (*strp, "(SP)"); 199*a2e2270fSchristos 200*a2e2270fSchristos if (afteroffset == NULL) 201*a2e2270fSchristos /* Maybe it's in lower case. */ 202*a2e2270fSchristos afteroffset = strstr (*strp, "(sp)"); 203*a2e2270fSchristos 204*a2e2270fSchristos if (afteroffset != NULL) 205*a2e2270fSchristos { 206*a2e2270fSchristos if (afteroffset == *strp) 207*a2e2270fSchristos { 208*a2e2270fSchristos /* No offset present. Use 0 by default. */ 209*a2e2270fSchristos tempvalue = 0; 210*a2e2270fSchristos errmsg = NULL; 211*a2e2270fSchristos } 212*a2e2270fSchristos else 213*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, 214*a2e2270fSchristos BFD_RELOC_IP2K_FR_OFFSET, 215*a2e2270fSchristos & result_type, & tempvalue); 216*a2e2270fSchristos 217*a2e2270fSchristos if (errmsg == NULL) 218*a2e2270fSchristos { 219*a2e2270fSchristos if (tempvalue <= 127) 220*a2e2270fSchristos { 221*a2e2270fSchristos /* Value is ok. Fix up the first 2 bits and return. */ 222*a2e2270fSchristos *valuep = 0x0180 | tempvalue; 223*a2e2270fSchristos *strp += 4; /* Skip over the (SP) in *strp. */ 224*a2e2270fSchristos return errmsg; 225*a2e2270fSchristos } 226*a2e2270fSchristos else 227*a2e2270fSchristos { 228*a2e2270fSchristos /* Found something there in front of (SP) but it's out 229*a2e2270fSchristos of range. */ 230*a2e2270fSchristos errmsg = _("(SP) offset out of range."); 231*a2e2270fSchristos return errmsg; 232*a2e2270fSchristos } 233*a2e2270fSchristos } 234*a2e2270fSchristos } 235*a2e2270fSchristos 236*a2e2270fSchristos /* Attempt to parse as an address. */ 237*a2e2270fSchristos *strp = old_strp; 238*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9, 239*a2e2270fSchristos & result_type, & value); 240*a2e2270fSchristos if (errmsg == NULL) 241*a2e2270fSchristos { 242*a2e2270fSchristos *valuep = value; 243*a2e2270fSchristos 244*a2e2270fSchristos /* If a parenthesis is found, warn about invalid form. */ 245*a2e2270fSchristos if (**strp == '(') 246*a2e2270fSchristos errmsg = _("illegal use of parentheses"); 247*a2e2270fSchristos 248*a2e2270fSchristos /* If a numeric value is specified, ensure that it is between 249*a2e2270fSchristos 1 and 255. */ 250*a2e2270fSchristos else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 251*a2e2270fSchristos { 252*a2e2270fSchristos if (value < 0x1 || value > 0xff) 253*a2e2270fSchristos errmsg = _("operand out of range (not between 1 and 255)"); 254*a2e2270fSchristos } 255*a2e2270fSchristos } 256*a2e2270fSchristos return errmsg; 257*a2e2270fSchristos} 258*a2e2270fSchristos 259*a2e2270fSchristosstatic const char * 260*a2e2270fSchristosparse_addr16 (CGEN_CPU_DESC cd, 261*a2e2270fSchristos const char **strp, 262*a2e2270fSchristos int opindex, 263*a2e2270fSchristos unsigned long *valuep) 264*a2e2270fSchristos{ 265*a2e2270fSchristos const char *errmsg; 266*a2e2270fSchristos enum cgen_parse_operand_result result_type; 267*a2e2270fSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 268*a2e2270fSchristos bfd_vma value; 269*a2e2270fSchristos 270*a2e2270fSchristos if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16H) 271*a2e2270fSchristos code = BFD_RELOC_IP2K_HI8DATA; 272*a2e2270fSchristos else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16L) 273*a2e2270fSchristos code = BFD_RELOC_IP2K_LO8DATA; 274*a2e2270fSchristos else 275*a2e2270fSchristos { 276*a2e2270fSchristos /* Something is very wrong. opindex has to be one of the above. */ 277*a2e2270fSchristos errmsg = _("parse_addr16: invalid opindex."); 278*a2e2270fSchristos return errmsg; 279*a2e2270fSchristos } 280*a2e2270fSchristos 281*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, 282*a2e2270fSchristos & result_type, & value); 283*a2e2270fSchristos if (errmsg == NULL) 284*a2e2270fSchristos { 285*a2e2270fSchristos /* We either have a relocation or a number now. */ 286*a2e2270fSchristos if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 287*a2e2270fSchristos { 288*a2e2270fSchristos /* We got a number back. */ 289*a2e2270fSchristos if (code == BFD_RELOC_IP2K_HI8DATA) 290*a2e2270fSchristos value >>= 8; 291*a2e2270fSchristos else 292*a2e2270fSchristos /* code = BFD_RELOC_IP2K_LOW8DATA. */ 293*a2e2270fSchristos value &= 0x00FF; 294*a2e2270fSchristos } 295*a2e2270fSchristos *valuep = value; 296*a2e2270fSchristos } 297*a2e2270fSchristos 298*a2e2270fSchristos return errmsg; 299*a2e2270fSchristos} 300*a2e2270fSchristos 301*a2e2270fSchristosstatic const char * 302*a2e2270fSchristosparse_addr16_cjp (CGEN_CPU_DESC cd, 303*a2e2270fSchristos const char **strp, 304*a2e2270fSchristos int opindex, 305*a2e2270fSchristos unsigned long *valuep) 306*a2e2270fSchristos{ 307*a2e2270fSchristos const char *errmsg; 308*a2e2270fSchristos enum cgen_parse_operand_result result_type; 309*a2e2270fSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 310*a2e2270fSchristos bfd_vma value; 311*a2e2270fSchristos 312*a2e2270fSchristos if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP) 313*a2e2270fSchristos code = BFD_RELOC_IP2K_ADDR16CJP; 314*a2e2270fSchristos else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P) 315*a2e2270fSchristos code = BFD_RELOC_IP2K_PAGE3; 316*a2e2270fSchristos 317*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, 318*a2e2270fSchristos & result_type, & value); 319*a2e2270fSchristos if (errmsg == NULL) 320*a2e2270fSchristos { 321*a2e2270fSchristos if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) 322*a2e2270fSchristos { 323*a2e2270fSchristos if ((value & 0x1) == 0) /* If the address is even .... */ 324*a2e2270fSchristos { 325*a2e2270fSchristos if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP) 326*a2e2270fSchristos *valuep = (value >> 1) & 0x1FFF; /* Should mask be 1FFF? */ 327*a2e2270fSchristos else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P) 328*a2e2270fSchristos *valuep = (value >> 14) & 0x7; 329*a2e2270fSchristos } 330*a2e2270fSchristos else 331*a2e2270fSchristos errmsg = _("Byte address required. - must be even."); 332*a2e2270fSchristos } 333*a2e2270fSchristos else if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED) 334*a2e2270fSchristos { 335*a2e2270fSchristos /* This will happen for things like (s2-s1) where s2 and s1 336*a2e2270fSchristos are labels. */ 337*a2e2270fSchristos *valuep = value; 338*a2e2270fSchristos } 339*a2e2270fSchristos else 340*a2e2270fSchristos errmsg = _("cgen_parse_address returned a symbol. Literal required."); 341*a2e2270fSchristos } 342*a2e2270fSchristos return errmsg; 343*a2e2270fSchristos} 344*a2e2270fSchristos 345*a2e2270fSchristosstatic const char * 346*a2e2270fSchristosparse_lit8 (CGEN_CPU_DESC cd, 347*a2e2270fSchristos const char **strp, 348*a2e2270fSchristos int opindex, 349*a2e2270fSchristos long *valuep) 350*a2e2270fSchristos{ 351*a2e2270fSchristos const char *errmsg; 352*a2e2270fSchristos enum cgen_parse_operand_result result_type; 353*a2e2270fSchristos bfd_reloc_code_real_type code = BFD_RELOC_NONE; 354*a2e2270fSchristos bfd_vma value; 355*a2e2270fSchristos 356*a2e2270fSchristos /* Parse %OP relocating operators. */ 357*a2e2270fSchristos if (strncmp (*strp, "%bank", 5) == 0) 358*a2e2270fSchristos { 359*a2e2270fSchristos *strp += 5; 360*a2e2270fSchristos code = BFD_RELOC_IP2K_BANK; 361*a2e2270fSchristos } 362*a2e2270fSchristos else if (strncmp (*strp, "%lo8data", 8) == 0) 363*a2e2270fSchristos { 364*a2e2270fSchristos *strp += 8; 365*a2e2270fSchristos code = BFD_RELOC_IP2K_LO8DATA; 366*a2e2270fSchristos } 367*a2e2270fSchristos else if (strncmp (*strp, "%hi8data", 8) == 0) 368*a2e2270fSchristos { 369*a2e2270fSchristos *strp += 8; 370*a2e2270fSchristos code = BFD_RELOC_IP2K_HI8DATA; 371*a2e2270fSchristos } 372*a2e2270fSchristos else if (strncmp (*strp, "%ex8data", 8) == 0) 373*a2e2270fSchristos { 374*a2e2270fSchristos *strp += 8; 375*a2e2270fSchristos code = BFD_RELOC_IP2K_EX8DATA; 376*a2e2270fSchristos } 377*a2e2270fSchristos else if (strncmp (*strp, "%lo8insn", 8) == 0) 378*a2e2270fSchristos { 379*a2e2270fSchristos *strp += 8; 380*a2e2270fSchristos code = BFD_RELOC_IP2K_LO8INSN; 381*a2e2270fSchristos } 382*a2e2270fSchristos else if (strncmp (*strp, "%hi8insn", 8) == 0) 383*a2e2270fSchristos { 384*a2e2270fSchristos *strp += 8; 385*a2e2270fSchristos code = BFD_RELOC_IP2K_HI8INSN; 386*a2e2270fSchristos } 387*a2e2270fSchristos 388*a2e2270fSchristos /* Parse %op operand. */ 389*a2e2270fSchristos if (code != BFD_RELOC_NONE) 390*a2e2270fSchristos { 391*a2e2270fSchristos errmsg = cgen_parse_address (cd, strp, opindex, code, 392*a2e2270fSchristos & result_type, & value); 393*a2e2270fSchristos if ((errmsg == NULL) && 394*a2e2270fSchristos (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)) 395*a2e2270fSchristos errmsg = _("percent-operator operand is not a symbol"); 396*a2e2270fSchristos 397*a2e2270fSchristos *valuep = value; 398*a2e2270fSchristos } 399*a2e2270fSchristos /* Parse as a number. */ 400*a2e2270fSchristos else 401*a2e2270fSchristos { 402*a2e2270fSchristos errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep); 403*a2e2270fSchristos 404*a2e2270fSchristos /* Truncate to eight bits to accept both signed and unsigned input. */ 405*a2e2270fSchristos if (errmsg == NULL) 406*a2e2270fSchristos *valuep &= 0xFF; 407*a2e2270fSchristos } 408*a2e2270fSchristos 409*a2e2270fSchristos return errmsg; 410*a2e2270fSchristos} 411*a2e2270fSchristos 412*a2e2270fSchristosstatic const char * 413*a2e2270fSchristosparse_bit3 (CGEN_CPU_DESC cd, 414*a2e2270fSchristos const char **strp, 415*a2e2270fSchristos int opindex, 416*a2e2270fSchristos unsigned long *valuep) 417*a2e2270fSchristos{ 418*a2e2270fSchristos const char *errmsg; 419*a2e2270fSchristos char mode = 0; 420*a2e2270fSchristos long count = 0; 421*a2e2270fSchristos unsigned long value; 422*a2e2270fSchristos 423*a2e2270fSchristos if (strncmp (*strp, "%bit", 4) == 0) 424*a2e2270fSchristos { 425*a2e2270fSchristos *strp += 4; 426*a2e2270fSchristos mode = 1; 427*a2e2270fSchristos } 428*a2e2270fSchristos else if (strncmp (*strp, "%msbbit", 7) == 0) 429*a2e2270fSchristos { 430*a2e2270fSchristos *strp += 7; 431*a2e2270fSchristos mode = 1; 432*a2e2270fSchristos } 433*a2e2270fSchristos else if (strncmp (*strp, "%lsbbit", 7) == 0) 434*a2e2270fSchristos { 435*a2e2270fSchristos *strp += 7; 436*a2e2270fSchristos mode = 2; 437*a2e2270fSchristos } 438*a2e2270fSchristos 439*a2e2270fSchristos errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); 440*a2e2270fSchristos if (errmsg) 441*a2e2270fSchristos return errmsg; 442*a2e2270fSchristos 443*a2e2270fSchristos if (mode) 444*a2e2270fSchristos { 445*a2e2270fSchristos value = * valuep; 446*a2e2270fSchristos if (value == 0) 447*a2e2270fSchristos { 448*a2e2270fSchristos errmsg = _("Attempt to find bit index of 0"); 449*a2e2270fSchristos return errmsg; 450*a2e2270fSchristos } 451*a2e2270fSchristos 452*a2e2270fSchristos if (mode == 1) 453*a2e2270fSchristos { 454*a2e2270fSchristos count = 31; 455*a2e2270fSchristos while ((value & 0x80000000) == 0) 456*a2e2270fSchristos { 457*a2e2270fSchristos count--; 458*a2e2270fSchristos value <<= 1; 459*a2e2270fSchristos } 460*a2e2270fSchristos } 461*a2e2270fSchristos else if (mode == 2) 462*a2e2270fSchristos { 463*a2e2270fSchristos count = 0; 464*a2e2270fSchristos while ((value & 0x00000001) == 0) 465*a2e2270fSchristos { 466*a2e2270fSchristos count++; 467*a2e2270fSchristos value >>= 1; 468*a2e2270fSchristos } 469*a2e2270fSchristos } 470*a2e2270fSchristos 471*a2e2270fSchristos *valuep = count; 472*a2e2270fSchristos } 473*a2e2270fSchristos 474*a2e2270fSchristos return errmsg; 475*a2e2270fSchristos} 476*a2e2270fSchristos 477*a2e2270fSchristos/* -- dis.c */ 478*a2e2270fSchristos 479*a2e2270fSchristosstatic void 480*a2e2270fSchristosprint_fr (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 481*a2e2270fSchristos void * dis_info, 482*a2e2270fSchristos long value, 483*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 484*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 485*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 486*a2e2270fSchristos{ 487*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 488*a2e2270fSchristos const CGEN_KEYWORD_ENTRY *ke; 489*a2e2270fSchristos extern CGEN_KEYWORD ip2k_cgen_opval_register_names; 490*a2e2270fSchristos long offsettest; 491*a2e2270fSchristos long offsetvalue; 492*a2e2270fSchristos 493*a2e2270fSchristos if (value == 0) /* This is (IP). */ 494*a2e2270fSchristos { 495*a2e2270fSchristos (*info->fprintf_func) (info->stream, "%s", "(IP)"); 496*a2e2270fSchristos return; 497*a2e2270fSchristos } 498*a2e2270fSchristos 499*a2e2270fSchristos offsettest = value >> 7; 500*a2e2270fSchristos offsetvalue = value & 0x7F; 501*a2e2270fSchristos 502*a2e2270fSchristos /* Check to see if first two bits are 10 -> (DP). */ 503*a2e2270fSchristos if (offsettest == 2) 504*a2e2270fSchristos { 505*a2e2270fSchristos if (offsetvalue == 0) 506*a2e2270fSchristos (*info->fprintf_func) (info->stream, "%s","(DP)"); 507*a2e2270fSchristos else 508*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue, "(DP)"); 509*a2e2270fSchristos return; 510*a2e2270fSchristos } 511*a2e2270fSchristos 512*a2e2270fSchristos /* Check to see if first two bits are 11 -> (SP). */ 513*a2e2270fSchristos if (offsettest == 3) 514*a2e2270fSchristos { 515*a2e2270fSchristos if (offsetvalue == 0) 516*a2e2270fSchristos (*info->fprintf_func) (info->stream, "%s", "(SP)"); 517*a2e2270fSchristos else 518*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%lx%s", offsetvalue,"(SP)"); 519*a2e2270fSchristos return; 520*a2e2270fSchristos } 521*a2e2270fSchristos 522*a2e2270fSchristos /* Attempt to print as a register keyword. */ 523*a2e2270fSchristos ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value); 524*a2e2270fSchristos 525*a2e2270fSchristos if (ke != NULL) 526*a2e2270fSchristos (*info->fprintf_func) (info->stream, "%s", ke->name); 527*a2e2270fSchristos else 528*a2e2270fSchristos /* Print as an address literal. */ 529*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%02lx", value); 530*a2e2270fSchristos} 531*a2e2270fSchristos 532*a2e2270fSchristosstatic void 533*a2e2270fSchristosprint_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 534*a2e2270fSchristos void * dis_info, 535*a2e2270fSchristos long value, 536*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 537*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 538*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 539*a2e2270fSchristos{ 540*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 541*a2e2270fSchristos 542*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%lx", value); 543*a2e2270fSchristos} 544*a2e2270fSchristos 545*a2e2270fSchristosstatic void 546*a2e2270fSchristosprint_dollarhex8 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 547*a2e2270fSchristos void * dis_info, 548*a2e2270fSchristos long value, 549*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 550*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 551*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 552*a2e2270fSchristos{ 553*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 554*a2e2270fSchristos 555*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%02lx", value); 556*a2e2270fSchristos} 557*a2e2270fSchristos 558*a2e2270fSchristosstatic void 559*a2e2270fSchristosprint_dollarhex_addr16h (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 560*a2e2270fSchristos void * dis_info, 561*a2e2270fSchristos long value, 562*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 563*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 564*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 565*a2e2270fSchristos{ 566*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 567*a2e2270fSchristos 568*a2e2270fSchristos /* This is a loadh instruction. Shift the value to the left 569*a2e2270fSchristos by 8 bits so that disassembled code will reassemble properly. */ 570*a2e2270fSchristos value = ((value << 8) & 0xFF00); 571*a2e2270fSchristos 572*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%04lx", value); 573*a2e2270fSchristos} 574*a2e2270fSchristos 575*a2e2270fSchristosstatic void 576*a2e2270fSchristosprint_dollarhex_addr16l (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 577*a2e2270fSchristos void * dis_info, 578*a2e2270fSchristos long value, 579*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 580*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 581*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 582*a2e2270fSchristos{ 583*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 584*a2e2270fSchristos 585*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%04lx", value); 586*a2e2270fSchristos} 587*a2e2270fSchristos 588*a2e2270fSchristosstatic void 589*a2e2270fSchristosprint_dollarhex_p (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 590*a2e2270fSchristos void * dis_info, 591*a2e2270fSchristos long value, 592*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 593*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 594*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 595*a2e2270fSchristos{ 596*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 597*a2e2270fSchristos 598*a2e2270fSchristos value = ((value << 14) & 0x1C000); 599*a2e2270fSchristos ;value = (value & 0x1FFFF); 600*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%05lx", value); 601*a2e2270fSchristos} 602*a2e2270fSchristos 603*a2e2270fSchristosstatic void 604*a2e2270fSchristosprint_dollarhex_cj (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 605*a2e2270fSchristos void * dis_info, 606*a2e2270fSchristos long value, 607*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 608*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 609*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 610*a2e2270fSchristos{ 611*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 612*a2e2270fSchristos 613*a2e2270fSchristos value = ((value << 1) & 0x1FFFF); 614*a2e2270fSchristos (*info->fprintf_func) (info->stream, "$%05lx", value); 615*a2e2270fSchristos} 616*a2e2270fSchristos 617*a2e2270fSchristosstatic void 618*a2e2270fSchristosprint_decimal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 619*a2e2270fSchristos void * dis_info, 620*a2e2270fSchristos long value, 621*a2e2270fSchristos unsigned int attrs ATTRIBUTE_UNUSED, 622*a2e2270fSchristos bfd_vma pc ATTRIBUTE_UNUSED, 623*a2e2270fSchristos int length ATTRIBUTE_UNUSED) 624*a2e2270fSchristos{ 625*a2e2270fSchristos disassemble_info *info = (disassemble_info *) dis_info; 626*a2e2270fSchristos 627*a2e2270fSchristos (*info->fprintf_func) (info->stream, "%ld", value); 628*a2e2270fSchristos} 629*a2e2270fSchristos 630*a2e2270fSchristos 631*a2e2270fSchristos 632*a2e2270fSchristos/* -- */ 633*a2e2270fSchristos 634