libhppa.h revision 1.2
1/* HP PA-RISC SOM object file format: definitions internal to BFD. 2 Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. 3 4 Contributed by the Center for Software Science at the 5 University of Utah (pa-gdb-bugs@cs.utah.edu). 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23#ifndef _HPPA_H 24#define _HPPA_H 25 26#define BYTES_IN_WORD 4 27#define PA_PAGESIZE 0x1000 28 29#ifndef INLINE 30#ifdef __GNUC__ 31#define INLINE inline 32#else 33#define INLINE 34#endif /* GNU C? */ 35#endif /* INLINE */ 36 37#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 7 38/* Declare the functions with the unused attribute to avoid warnings. */ 39static INLINE unsigned int assemble_3 (unsigned int) 40 __attribute__ ((__unused__)); 41static INLINE void dis_assemble_3 (unsigned int, unsigned int *) 42 __attribute__ ((__unused__)); 43static INLINE unsigned int assemble_12 (unsigned int, unsigned int) 44 __attribute__ ((__unused__)); 45static INLINE void dis_assemble_12 (unsigned int, unsigned int *, 46 unsigned int *) 47 __attribute__ ((__unused__)); 48static INLINE unsigned long assemble_17 (unsigned int, unsigned int, 49 unsigned int) 50 __attribute__ ((__unused__)); 51static INLINE void dis_assemble_17 (unsigned int, unsigned int *, 52 unsigned int *, unsigned int *) 53 __attribute__ ((__unused__)); 54static INLINE unsigned long assemble_21 (unsigned int) 55 __attribute ((__unused__)); 56static INLINE void dis_assemble_21 (unsigned int, unsigned int *) 57 __attribute__ ((__unused__)); 58static INLINE unsigned long sign_extend (unsigned int, unsigned int) 59 __attribute__ ((__unused__)); 60static INLINE unsigned int ones (int) __attribute ((__unused__)); 61static INLINE void sign_unext (unsigned int, unsigned int, unsigned int *) 62 __attribute__ ((__unused__)); 63static INLINE unsigned long low_sign_extend (unsigned int, unsigned int) 64 __attribute__ ((__unused__)); 65static INLINE void low_sign_unext (unsigned int, unsigned int, unsigned int *) 66 __attribute__ ((__unused__)); 67static INLINE unsigned long hppa_field_adjust (unsigned long, unsigned long, 68 unsigned short) 69 __attribute__ ((__unused__)); 70static INLINE char bfd_hppa_insn2fmt (unsigned long) 71 __attribute__ ((__unused__)); 72static INLINE unsigned long hppa_rebuild_insn (bfd *, unsigned long, 73 unsigned long, unsigned long) 74 __attribute__ ((__unused__)); 75#endif /* gcc 2.7 or higher */ 76 77/* The PA instruction set variants. */ 78enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20}; 79 80/* HP PA-RISC relocation types */ 81 82enum hppa_reloc_field_selector_type 83 { 84 R_HPPA_FSEL = 0x0, 85 R_HPPA_LSSEL = 0x1, 86 R_HPPA_RSSEL = 0x2, 87 R_HPPA_LSEL = 0x3, 88 R_HPPA_RSEL = 0x4, 89 R_HPPA_LDSEL = 0x5, 90 R_HPPA_RDSEL = 0x6, 91 R_HPPA_LRSEL = 0x7, 92 R_HPPA_RRSEL = 0x8, 93 R_HPPA_NSEL = 0x9, 94 R_HPPA_NLSEL = 0xa, 95 R_HPPA_NLRSEL = 0xb, 96 R_HPPA_PSEL = 0xc, 97 R_HPPA_LPSEL = 0xd, 98 R_HPPA_RPSEL = 0xe, 99 R_HPPA_TSEL = 0xf, 100 R_HPPA_LTSEL = 0x10, 101 R_HPPA_RTSEL = 0x11 102 }; 103 104/* /usr/include/reloc.h defines these to constants. We want to use 105 them in enums, so #undef them before we start using them. We might 106 be able to fix this another way by simply managing not to include 107 /usr/include/reloc.h, but currently GDB picks up these defines 108 somewhere. */ 109#undef e_fsel 110#undef e_lssel 111#undef e_rssel 112#undef e_lsel 113#undef e_rsel 114#undef e_ldsel 115#undef e_rdsel 116#undef e_lrsel 117#undef e_rrsel 118#undef e_nsel 119#undef e_nlsel 120#undef e_nlrsel 121#undef e_psel 122#undef e_lpsel 123#undef e_rpsel 124#undef e_tsel 125#undef e_ltsel 126#undef e_rtsel 127#undef e_one 128#undef e_two 129#undef e_pcrel 130#undef e_con 131#undef e_plabel 132#undef e_abs 133 134/* for compatibility */ 135enum hppa_reloc_field_selector_type_alt 136 { 137 e_fsel = R_HPPA_FSEL, 138 e_lssel = R_HPPA_LSSEL, 139 e_rssel = R_HPPA_RSSEL, 140 e_lsel = R_HPPA_LSEL, 141 e_rsel = R_HPPA_RSEL, 142 e_ldsel = R_HPPA_LDSEL, 143 e_rdsel = R_HPPA_RDSEL, 144 e_lrsel = R_HPPA_LRSEL, 145 e_rrsel = R_HPPA_RRSEL, 146 e_nsel = R_HPPA_NSEL, 147 e_nlsel = R_HPPA_NLSEL, 148 e_nlrsel = R_HPPA_NLRSEL, 149 e_psel = R_HPPA_PSEL, 150 e_lpsel = R_HPPA_LPSEL, 151 e_rpsel = R_HPPA_RPSEL, 152 e_tsel = R_HPPA_TSEL, 153 e_ltsel = R_HPPA_LTSEL, 154 e_rtsel = R_HPPA_RTSEL 155 }; 156 157enum hppa_reloc_expr_type 158 { 159 R_HPPA_E_ONE = 0, 160 R_HPPA_E_TWO = 1, 161 R_HPPA_E_PCREL = 2, 162 R_HPPA_E_CON = 3, 163 R_HPPA_E_PLABEL = 7, 164 R_HPPA_E_ABS = 18 165 }; 166 167/* for compatibility */ 168enum hppa_reloc_expr_type_alt 169 { 170 e_one = R_HPPA_E_ONE, 171 e_two = R_HPPA_E_TWO, 172 e_pcrel = R_HPPA_E_PCREL, 173 e_con = R_HPPA_E_CON, 174 e_plabel = R_HPPA_E_PLABEL, 175 e_abs = R_HPPA_E_ABS 176 }; 177 178 179/* Relocations for function calls must be accompanied by parameter 180 relocation bits. These bits describe exactly where the caller has 181 placed the function's arguments and where it expects to find a return 182 value. 183 184 Both ELF and SOM encode this information within the addend field 185 of the call relocation. (Note this could break very badly if one 186 was to make a call like bl foo + 0x12345678). 187 188 The high order 10 bits contain parameter relocation information, 189 the low order 22 bits contain the constant offset. */ 190 191#define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF) 192#define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10) 193#define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF)) 194 195/* Some functions to manipulate PA instructions. */ 196static INLINE unsigned int 197assemble_3 (x) 198 unsigned int x; 199{ 200 return (((x & 1) << 2) | ((x & 6) >> 1)) & 7; 201} 202 203static INLINE void 204dis_assemble_3 (x, r) 205 unsigned int x; 206 unsigned int *r; 207{ 208 *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7; 209} 210 211static INLINE unsigned int 212assemble_12 (x, y) 213 unsigned int x, y; 214{ 215 return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff; 216} 217 218static INLINE void 219dis_assemble_12 (as12, x, y) 220 unsigned int as12; 221 unsigned int *x, *y; 222{ 223 *y = (as12 & 0x800) >> 11; 224 *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10); 225} 226 227static INLINE unsigned long 228assemble_17 (x, y, z) 229 unsigned int x, y, z; 230{ 231 unsigned long temp; 232 233 temp = ((z & 1) << 16) | 234 ((x & 0x1f) << 11) | 235 ((y & 1) << 10) | 236 ((y & 0x7fe) >> 1); 237 return temp & 0x1ffff; 238} 239 240static INLINE void 241dis_assemble_17 (as17, x, y, z) 242 unsigned int as17; 243 unsigned int *x, *y, *z; 244{ 245 246 *z = (as17 & 0x10000) >> 16; 247 *x = (as17 & 0x0f800) >> 11; 248 *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff; 249} 250 251static INLINE unsigned long 252assemble_21 (x) 253 unsigned int x; 254{ 255 unsigned long temp; 256 257 temp = ((x & 1) << 20) | 258 ((x & 0xffe) << 8) | 259 ((x & 0xc000) >> 7) | 260 ((x & 0x1f0000) >> 14) | 261 ((x & 0x003000) >> 12); 262 return temp & 0x1fffff; 263} 264 265static INLINE void 266dis_assemble_21 (as21, x) 267 unsigned int as21, *x; 268{ 269 unsigned long temp; 270 271 272 temp = (as21 & 0x100000) >> 20; 273 temp |= (as21 & 0x0ffe00) >> 8; 274 temp |= (as21 & 0x000180) << 7; 275 temp |= (as21 & 0x00007c) << 14; 276 temp |= (as21 & 0x000003) << 12; 277 *x = temp; 278} 279 280static INLINE unsigned long 281sign_extend (x, len) 282 unsigned int x, len; 283{ 284 return (int)(x >> (len - 1) ? (-1 << len) | x : x); 285} 286 287static INLINE unsigned int 288ones (n) 289 int n; 290{ 291 unsigned int len_ones; 292 int i; 293 294 i = 0; 295 len_ones = 0; 296 while (i < n) 297 { 298 len_ones = (len_ones << 1) | 1; 299 i++; 300 } 301 302 return len_ones; 303} 304 305static INLINE void 306sign_unext (x, len, result) 307 unsigned int x, len; 308 unsigned int *result; 309{ 310 unsigned int len_ones; 311 312 len_ones = ones (len); 313 314 *result = x & len_ones; 315} 316 317static INLINE unsigned long 318low_sign_extend (x, len) 319 unsigned int x, len; 320{ 321 return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1); 322} 323 324static INLINE void 325low_sign_unext (x, len, result) 326 unsigned int x, len; 327 unsigned int *result; 328{ 329 unsigned int temp; 330 unsigned int sign; 331 unsigned int rest; 332 unsigned int one_bit_at_len; 333 unsigned int len_ones; 334 335 len_ones = ones (len); 336 one_bit_at_len = 1 << (len - 1); 337 338 sign_unext (x, len, &temp); 339 sign = temp & one_bit_at_len; 340 sign >>= (len - 1); 341 342 rest = temp & (len_ones ^ one_bit_at_len); 343 rest <<= 1; 344 345 *result = rest | sign; 346} 347 348/* Handle field selectors for PA instructions. */ 349 350static INLINE unsigned long 351hppa_field_adjust (value, constant_value, r_field) 352 unsigned long value; 353 unsigned long constant_value; 354 unsigned short r_field; 355{ 356 switch (r_field) 357 { 358 case e_fsel: /* F : no change */ 359 case e_nsel: /* N : no change */ 360 value += constant_value; 361 break; 362 363 case e_lssel: /* LS : if (bit 21) then add 0x800 364 arithmetic shift right 11 bits */ 365 value += constant_value; 366 if (value & 0x00000400) 367 value += 0x800; 368 value = (value & 0xfffff800) >> 11; 369 break; 370 371 case e_rssel: /* RS : Sign extend from bit 21 */ 372 value += constant_value; 373 if (value & 0x00000400) 374 value |= 0xfffff800; 375 else 376 value &= 0x7ff; 377 break; 378 379 case e_lsel: /* L : Arithmetic shift right 11 bits */ 380 case e_nlsel: /* NL : Arithmetic shift right 11 bits */ 381 value += constant_value; 382 value = (value & 0xfffff800) >> 11; 383 break; 384 385 case e_rsel: /* R : Set bits 0-20 to zero */ 386 value += constant_value; 387 value = value & 0x7ff; 388 break; 389 390 case e_ldsel: /* LD : Add 0x800, arithmetic shift 391 right 11 bits */ 392 value += constant_value; 393 value += 0x800; 394 value = (value & 0xfffff800) >> 11; 395 break; 396 397 case e_rdsel: /* RD : Set bits 0-20 to one */ 398 value += constant_value; 399 value |= 0xfffff800; 400 break; 401 402 case e_lrsel: /* LR : L with "rounded" constant */ 403 case e_nlrsel: /* NLR : NL with "rounded" constant */ 404 value = value + ((constant_value + 0x1000) & 0xffffe000); 405 value = (value & 0xfffff800) >> 11; 406 break; 407 408 case e_rrsel: /* RR : R with "rounded" constant */ 409 value = value + ((constant_value + 0x1000) & 0xffffe000); 410 value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000); 411 break; 412 413 default: 414 abort (); 415 } 416 return value; 417 418} 419 420/* PA-RISC OPCODES */ 421#define get_opcode(insn) ((insn) & 0xfc000000) >> 26 422 423/* FIXME: this list is incomplete. It should also be an enumerated 424 type rather than #defines. */ 425 426#define LDO 0x0d 427#define LDB 0x10 428#define LDH 0x11 429#define LDW 0x12 430#define LDWM 0x13 431#define STB 0x18 432#define STH 0x19 433#define STW 0x1a 434#define STWM 0x1b 435#define COMICLR 0x24 436#define SUBI 0x25 437#define SUBIO 0x25 438#define ADDIT 0x2c 439#define ADDITO 0x2c 440#define ADDI 0x2d 441#define ADDIO 0x2d 442#define LDIL 0x08 443#define ADDIL 0x0a 444 445#define MOVB 0x32 446#define MOVIB 0x33 447#define COMBT 0x20 448#define COMBF 0x22 449#define COMIBT 0x21 450#define COMIBF 0x23 451#define ADDBT 0x28 452#define ADDBF 0x2a 453#define ADDIBT 0x29 454#define ADDIBF 0x2b 455#define BVB 0x30 456#define BB 0x31 457 458#define BL 0x3a 459#define BLE 0x39 460#define BE 0x38 461 462 463/* Given a machine instruction, return its format. 464 465 FIXME: opcodes which do not map to a known format 466 should return an error of some sort. */ 467 468static INLINE char 469bfd_hppa_insn2fmt (insn) 470 unsigned long insn; 471{ 472 char fmt = -1; 473 unsigned char op = get_opcode (insn); 474 475 switch (op) 476 { 477 case ADDI: 478 case ADDIT: 479 case SUBI: 480 fmt = 11; 481 break; 482 case MOVB: 483 case MOVIB: 484 case COMBT: 485 case COMBF: 486 case COMIBT: 487 case COMIBF: 488 case ADDBT: 489 case ADDBF: 490 case ADDIBT: 491 case ADDIBF: 492 case BVB: 493 case BB: 494 fmt = 12; 495 break; 496 case LDO: 497 case LDB: 498 case LDH: 499 case LDW: 500 case LDWM: 501 case STB: 502 case STH: 503 case STW: 504 case STWM: 505 fmt = 14; 506 break; 507 case BL: 508 case BE: 509 case BLE: 510 fmt = 17; 511 break; 512 case LDIL: 513 case ADDIL: 514 fmt = 21; 515 break; 516 default: 517 fmt = 32; 518 break; 519 } 520 return fmt; 521} 522 523 524/* Insert VALUE into INSN using R_FORMAT to determine exactly what 525 bits to change. */ 526 527static INLINE unsigned long 528hppa_rebuild_insn (abfd, insn, value, r_format) 529 bfd *abfd; 530 unsigned long insn; 531 unsigned long value; 532 unsigned long r_format; 533{ 534 unsigned long const_part; 535 unsigned long rebuilt_part; 536 537 switch (r_format) 538 { 539 case 11: 540 { 541 unsigned w1, w; 542 543 const_part = insn & 0xffffe002; 544 dis_assemble_12 (value, &w1, &w); 545 rebuilt_part = (w1 << 2) | w; 546 return const_part | rebuilt_part; 547 } 548 549 case 12: 550 { 551 unsigned w1, w; 552 553 const_part = insn & 0xffffe002; 554 dis_assemble_12 (value, &w1, &w); 555 rebuilt_part = (w1 << 2) | w; 556 return const_part | rebuilt_part; 557 } 558 559 case 14: 560 { 561 unsigned int ext; 562 563 const_part = insn & 0xffffc000; 564 low_sign_unext (value, 14, &ext); 565 return const_part | ext; 566 } 567 568 case 17: 569 { 570 unsigned w1, w2, w; 571 572 const_part = insn & 0xffe0e002; 573 dis_assemble_17 (value, &w1, &w2, &w); 574 rebuilt_part = (w2 << 2) | (w1 << 16) | w; 575 return const_part | rebuilt_part; 576 } 577 578 case 21: 579 { 580 unsigned int w; 581 582 const_part = insn & 0xffe00000; 583 dis_assemble_21 (value, &w); 584 return const_part | w; 585 } 586 587 case 32: 588 const_part = 0; 589 return value; 590 591 default: 592 abort (); 593 } 594 return insn; 595} 596 597#endif /* _HPPA_H */ 598