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