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