Back to index

cell-binutils  2.17cvs20070401
libhppa.h
Go to the documentation of this file.
00001 /* HP PA-RISC SOM object file format:  definitions internal to BFD.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
00003    2003 Free Software Foundation, Inc.
00004 
00005    Contributed by the Center for Software Science at the
00006    University of Utah (pa-gdb-bugs@cs.utah.edu).
00007 
00008    This file is part of BFD, the Binary File Descriptor library.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00023 
00024 #ifndef _LIBHPPA_H
00025 #define _LIBHPPA_H
00026 
00027 #define BYTES_IN_WORD 4
00028 #define PA_PAGESIZE 0x1000
00029 
00030 /* The PA instruction set variants.  */
00031 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
00032 
00033 /* HP PA-RISC relocation types */
00034 
00035 enum hppa_reloc_field_selector_type
00036   {
00037     R_HPPA_FSEL = 0x0,
00038     R_HPPA_LSSEL = 0x1,
00039     R_HPPA_RSSEL = 0x2,
00040     R_HPPA_LSEL = 0x3,
00041     R_HPPA_RSEL = 0x4,
00042     R_HPPA_LDSEL = 0x5,
00043     R_HPPA_RDSEL = 0x6,
00044     R_HPPA_LRSEL = 0x7,
00045     R_HPPA_RRSEL = 0x8,
00046     R_HPPA_NSEL  = 0x9,
00047     R_HPPA_NLSEL  = 0xa,
00048     R_HPPA_NLRSEL  = 0xb,
00049     R_HPPA_PSEL = 0xc,
00050     R_HPPA_LPSEL = 0xd,
00051     R_HPPA_RPSEL = 0xe,
00052     R_HPPA_TSEL = 0xf,
00053     R_HPPA_LTSEL = 0x10,
00054     R_HPPA_RTSEL = 0x11,
00055     R_HPPA_LTPSEL = 0x12,
00056     R_HPPA_RTPSEL = 0x13
00057   };
00058 
00059 /* /usr/include/reloc.h defines these to constants.  We want to use
00060    them in enums, so #undef them before we start using them.  We might
00061    be able to fix this another way by simply managing not to include
00062    /usr/include/reloc.h, but currently GDB picks up these defines
00063    somewhere.  */
00064 #undef e_fsel
00065 #undef e_lssel
00066 #undef e_rssel
00067 #undef e_lsel
00068 #undef e_rsel
00069 #undef e_ldsel
00070 #undef e_rdsel
00071 #undef e_lrsel
00072 #undef e_rrsel
00073 #undef e_nsel
00074 #undef e_nlsel
00075 #undef e_nlrsel
00076 #undef e_psel
00077 #undef e_lpsel
00078 #undef e_rpsel
00079 #undef e_tsel
00080 #undef e_ltsel
00081 #undef e_rtsel
00082 #undef e_one
00083 #undef e_two
00084 #undef e_pcrel
00085 #undef e_con
00086 #undef e_plabel
00087 #undef e_abs
00088 
00089 /* for compatibility */
00090 enum hppa_reloc_field_selector_type_alt
00091   {
00092     e_fsel = R_HPPA_FSEL,
00093     e_lssel = R_HPPA_LSSEL,
00094     e_rssel = R_HPPA_RSSEL,
00095     e_lsel = R_HPPA_LSEL,
00096     e_rsel = R_HPPA_RSEL,
00097     e_ldsel = R_HPPA_LDSEL,
00098     e_rdsel = R_HPPA_RDSEL,
00099     e_lrsel = R_HPPA_LRSEL,
00100     e_rrsel = R_HPPA_RRSEL,
00101     e_nsel = R_HPPA_NSEL,
00102     e_nlsel = R_HPPA_NLSEL,
00103     e_nlrsel = R_HPPA_NLRSEL,
00104     e_psel = R_HPPA_PSEL,
00105     e_lpsel = R_HPPA_LPSEL,
00106     e_rpsel = R_HPPA_RPSEL,
00107     e_tsel = R_HPPA_TSEL,
00108     e_ltsel = R_HPPA_LTSEL,
00109     e_rtsel = R_HPPA_RTSEL,
00110     e_ltpsel = R_HPPA_LTPSEL,
00111     e_rtpsel = R_HPPA_RTPSEL
00112   };
00113 
00114 enum hppa_reloc_expr_type
00115   {
00116     R_HPPA_E_ONE = 0,
00117     R_HPPA_E_TWO = 1,
00118     R_HPPA_E_PCREL = 2,
00119     R_HPPA_E_CON = 3,
00120     R_HPPA_E_PLABEL = 7,
00121     R_HPPA_E_ABS = 18
00122   };
00123 
00124 /* for compatibility */
00125 enum hppa_reloc_expr_type_alt
00126   {
00127     e_one = R_HPPA_E_ONE,
00128     e_two = R_HPPA_E_TWO,
00129     e_pcrel = R_HPPA_E_PCREL,
00130     e_con = R_HPPA_E_CON,
00131     e_plabel = R_HPPA_E_PLABEL,
00132     e_abs = R_HPPA_E_ABS
00133   };
00134 
00135 
00136 /* Relocations for function calls must be accompanied by parameter
00137    relocation bits.  These bits describe exactly where the caller has
00138    placed the function's arguments and where it expects to find a return
00139    value.
00140 
00141    Both ELF and SOM encode this information within the addend field
00142    of the call relocation.  (Note this could break very badly if one
00143    was to make a call like bl foo + 0x12345678).
00144 
00145    The high order 10 bits contain parameter relocation information,
00146    the low order 22 bits contain the constant offset.  */
00147 
00148 #define HPPA_R_ARG_RELOC(a) \
00149   (((a) >> 22) & 0x3ff)
00150 #define HPPA_R_CONSTANT(a)  \
00151   ((((bfd_signed_vma)(a)) << (BFD_ARCH_SIZE-22)) >> (BFD_ARCH_SIZE-22))
00152 #define HPPA_R_ADDEND(r, c) \
00153   (((r) << 22) + ((c) & 0x3fffff))
00154 
00155 
00156 /* Some functions to manipulate PA instructions.  */
00157 
00158 /* Declare the functions with the unused attribute to avoid warnings.  */
00159 static inline int sign_extend (int, int) ATTRIBUTE_UNUSED;
00160 static inline int low_sign_extend (int, int) ATTRIBUTE_UNUSED;
00161 static inline int sign_unext (int, int) ATTRIBUTE_UNUSED;
00162 static inline int low_sign_unext (int, int) ATTRIBUTE_UNUSED;
00163 static inline int re_assemble_3 (int) ATTRIBUTE_UNUSED;
00164 static inline int re_assemble_12 (int) ATTRIBUTE_UNUSED;
00165 static inline int re_assemble_14 (int) ATTRIBUTE_UNUSED;
00166 static inline int re_assemble_16 (int) ATTRIBUTE_UNUSED;
00167 static inline int re_assemble_17 (int) ATTRIBUTE_UNUSED;
00168 static inline int re_assemble_21 (int) ATTRIBUTE_UNUSED;
00169 static inline int re_assemble_22 (int) ATTRIBUTE_UNUSED;
00170 static inline bfd_signed_vma hppa_field_adjust
00171   (bfd_vma, bfd_signed_vma, enum hppa_reloc_field_selector_type_alt)
00172   ATTRIBUTE_UNUSED;
00173 static inline int bfd_hppa_insn2fmt (bfd *, int) ATTRIBUTE_UNUSED;
00174 static inline int hppa_rebuild_insn (int, int, int) ATTRIBUTE_UNUSED;
00175 
00176 
00177 /* The *sign_extend functions are used to assemble various bitfields
00178    taken from an instruction and return the resulting immediate
00179    value.  */
00180 
00181 static inline int
00182 sign_extend (int x, int len)
00183 {
00184   int signbit = (1 << (len - 1));
00185   int mask = (signbit << 1) - 1;
00186   return ((x & mask) ^ signbit) - signbit;
00187 }
00188 
00189 static inline int
00190 low_sign_extend (int x, int len)
00191 {
00192   return (x >> 1) - ((x & 1) << (len - 1));
00193 }
00194 
00195 
00196 /* The re_assemble_* functions prepare an immediate value for
00197    insertion into an opcode. pa-risc uses all sorts of weird bitfields
00198    in the instruction to hold the value.  */
00199 
00200 static inline int
00201 sign_unext (int x, int len)
00202 {
00203   int len_ones;
00204 
00205   len_ones = (1 << len) - 1;
00206 
00207   return x & len_ones;
00208 }
00209 
00210 static inline int
00211 low_sign_unext (int x, int len)
00212 {
00213   int temp;
00214   int sign;
00215 
00216   sign = (x >> (len-1)) & 1;
00217 
00218   temp = sign_unext (x, len-1);
00219 
00220   return (temp << 1) | sign;
00221 }
00222 
00223 static inline int
00224 re_assemble_3 (int as3)
00225 {
00226   return ((  (as3 & 4) << (13-2))
00227          | ((as3 & 3) << (13+1)));
00228 }
00229 
00230 static inline int
00231 re_assemble_12 (int as12)
00232 {
00233   return ((  (as12 & 0x800) >> 11)
00234          | ((as12 & 0x400) >> (10 - 2))
00235          | ((as12 & 0x3ff) << (1 + 2)));
00236 }
00237 
00238 static inline int
00239 re_assemble_14 (int as14)
00240 {
00241   return ((  (as14 & 0x1fff) << 1)
00242          | ((as14 & 0x2000) >> 13));
00243 }
00244 
00245 static inline int
00246 re_assemble_16 (int as16)
00247 {
00248   int s, t;
00249 
00250   /* Unusual 16-bit encoding, for wide mode only.  */
00251   t = (as16 << 1) & 0xffff;
00252   s = (as16 & 0x8000);
00253   return (t ^ s ^ (s >> 1)) | (s >> 15);
00254 }
00255 
00256 static inline int
00257 re_assemble_17 (int as17)
00258 {
00259   return ((  (as17 & 0x10000) >> 16)
00260          | ((as17 & 0x0f800) << (16 - 11))
00261          | ((as17 & 0x00400) >> (10 - 2))
00262          | ((as17 & 0x003ff) << (1 + 2)));
00263 }
00264 
00265 static inline int
00266 re_assemble_21 (int as21)
00267 {
00268   return ((  (as21 & 0x100000) >> 20)
00269          | ((as21 & 0x0ffe00) >> 8)
00270          | ((as21 & 0x000180) << 7)
00271          | ((as21 & 0x00007c) << 14)
00272          | ((as21 & 0x000003) << 12));
00273 }
00274 
00275 static inline int
00276 re_assemble_22 (int as22)
00277 {
00278   return ((  (as22 & 0x200000) >> 21)
00279          | ((as22 & 0x1f0000) << (21 - 16))
00280          | ((as22 & 0x00f800) << (16 - 11))
00281          | ((as22 & 0x000400) >> (10 - 2))
00282          | ((as22 & 0x0003ff) << (1 + 2)));
00283 }
00284 
00285 
00286 /* Handle field selectors for PA instructions.
00287    The L and R (and LS, RS etc.) selectors are used in pairs to form a
00288    full 32 bit address.  eg.
00289 
00290    LDIL       L'start,%r1          ; put left part into r1
00291    LDW R'start(%r1),%r2     ; add r1 and right part to form address
00292 
00293    This function returns sign extended values in all cases.
00294 */
00295 
00296 static inline bfd_signed_vma
00297 hppa_field_adjust (bfd_vma sym_val,
00298                  bfd_signed_vma addend,
00299                  enum hppa_reloc_field_selector_type_alt r_field)
00300 {
00301   bfd_signed_vma value;
00302 
00303   value = sym_val + addend;
00304   switch (r_field)
00305     {
00306     case e_fsel:
00307       /* F: No change.  */
00308       break;
00309 
00310     case e_nsel:
00311       /* N: null selector.  I don't really understand what this is all
00312         about, but HP's documentation says "this indicates that zero
00313         bits are to be used for the displacement on the instruction.
00314         This fixup is used to identify three-instruction sequences to
00315         access data (for importing shared library data)."  */
00316       value = 0;
00317       break;
00318 
00319     case e_lsel:
00320     case e_nlsel:
00321       /* L:  Select top 21 bits.  */
00322       value = value >> 11;
00323       break;
00324 
00325     case e_rsel:
00326       /* R:  Select bottom 11 bits.  */
00327       value = value & 0x7ff;
00328       break;
00329 
00330     case e_lssel:
00331       /* LS:  Round to nearest multiple of 2048 then select top 21 bits.  */
00332       value = value + 0x400;
00333       value = value >> 11;
00334       break;
00335 
00336     case e_rssel:
00337       /* RS:  Select bottom 11 bits for LS.
00338         We need to return a value such that 2048 * LS'x + RS'x == x.
00339         ie. RS'x = x - ((x + 0x400) & -0x800)
00340         this is just a sign extension from bit 21.  */
00341       value = ((value & 0x7ff) ^ 0x400) - 0x400;
00342       break;
00343 
00344     case e_ldsel:
00345       /* LD:  Round to next multiple of 2048 then select top 21 bits.
00346         Yes, if we are already on a multiple of 2048, we go up to the
00347         next one.  RD in this case will be -2048.  */
00348       value = value + 0x800;
00349       value = value >> 11;
00350       break;
00351 
00352     case e_rdsel:
00353       /* RD:  Set bits 0-20 to one.  */
00354       value = value | -0x800;
00355       break;
00356 
00357     case e_lrsel:
00358     case e_nlrsel:
00359       /* LR:  L with rounding of the addend to nearest 8k.  */
00360       value = sym_val + ((addend + 0x1000) & -0x2000);
00361       value = value >> 11;
00362       break;
00363 
00364     case e_rrsel:
00365       /* RR:  R with rounding of the addend to nearest 8k.
00366         We need to return a value such that 2048 * LR'x + RR'x == x
00367         ie. RR'x = s+a - (s + (((a + 0x1000) & -0x2000) & -0x800))
00368         .       = s+a - ((s & -0x800) + ((a + 0x1000) & -0x2000))
00369         .       = (s & 0x7ff) + a - ((a + 0x1000) & -0x2000)  */
00370       value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
00371       break;
00372 
00373     default:
00374       abort ();
00375     }
00376   return value;
00377 }
00378 
00379 /* PA-RISC OPCODES */
00380 #define get_opcode(insn)    (((insn) >> 26) & 0x3f)
00381 
00382 enum hppa_opcode_type
00383 {
00384   /* None of the opcodes in the first group generate relocs, so we
00385      aren't too concerned about them.  */
00386   OP_SYSOP   = 0x00,
00387   OP_MEMMNG  = 0x01,
00388   OP_ALU     = 0x02,
00389   OP_NDXMEM  = 0x03,
00390   OP_SPOP    = 0x04,
00391   OP_DIAG    = 0x05,
00392   OP_FMPYADD = 0x06,
00393   OP_UNDEF07 = 0x07,
00394   OP_COPRW   = 0x09,
00395   OP_COPRDW  = 0x0b,
00396   OP_COPR    = 0x0c,
00397   OP_FLOAT   = 0x0e,
00398   OP_PRDSPEC = 0x0f,
00399   OP_UNDEF15 = 0x15,
00400   OP_UNDEF1d = 0x1d,
00401   OP_FMPYSUB = 0x26,
00402   OP_FPFUSED = 0x2e,
00403   OP_SHEXDP0 = 0x34,
00404   OP_SHEXDP1 = 0x35,
00405   OP_SHEXDP2 = 0x36,
00406   OP_UNDEF37 = 0x37,
00407   OP_SHEXDP3 = 0x3c,
00408   OP_SHEXDP4 = 0x3d,
00409   OP_MULTMED = 0x3e,
00410   OP_UNDEF3f = 0x3f,
00411 
00412   OP_LDIL    = 0x08,
00413   OP_ADDIL   = 0x0a,
00414 
00415   OP_LDO     = 0x0d,
00416   OP_LDB     = 0x10,
00417   OP_LDH     = 0x11,
00418   OP_LDW     = 0x12,
00419   OP_LDWM    = 0x13,
00420   OP_STB     = 0x18,
00421   OP_STH     = 0x19,
00422   OP_STW     = 0x1a,
00423   OP_STWM    = 0x1b,
00424 
00425   OP_LDD     = 0x14,
00426   OP_STD     = 0x1c,
00427 
00428   OP_FLDW    = 0x16,
00429   OP_LDWL    = 0x17,
00430   OP_FSTW    = 0x1e,
00431   OP_STWL    = 0x1f,
00432 
00433   OP_COMBT   = 0x20,
00434   OP_COMIBT  = 0x21,
00435   OP_COMBF   = 0x22,
00436   OP_COMIBF  = 0x23,
00437   OP_CMPBDT  = 0x27,
00438   OP_ADDBT   = 0x28,
00439   OP_ADDIBT  = 0x29,
00440   OP_ADDBF   = 0x2a,
00441   OP_ADDIBF  = 0x2b,
00442   OP_CMPBDF  = 0x2f,
00443   OP_BVB     = 0x30,
00444   OP_BB      = 0x31,
00445   OP_MOVB    = 0x32,
00446   OP_MOVIB   = 0x33,
00447   OP_CMPIBD  = 0x3b,
00448 
00449   OP_COMICLR = 0x24,
00450   OP_SUBI    = 0x25,
00451   OP_ADDIT   = 0x2c,
00452   OP_ADDI    = 0x2d,
00453 
00454   OP_BE      = 0x38,
00455   OP_BLE     = 0x39,
00456   OP_BL      = 0x3a
00457 };
00458 
00459 
00460 /* Given a machine instruction, return its format.  */
00461 
00462 static inline int
00463 bfd_hppa_insn2fmt (bfd *abfd, int insn)
00464 {
00465   enum hppa_opcode_type op = get_opcode (insn);
00466 
00467   switch (op)
00468     {
00469     case OP_COMICLR:
00470     case OP_SUBI:
00471     case OP_ADDIT:
00472     case OP_ADDI:
00473       return 11;
00474 
00475     case OP_COMBT:
00476     case OP_COMIBT:
00477     case OP_COMBF:
00478     case OP_COMIBF:
00479     case OP_CMPBDT:
00480     case OP_ADDBT:
00481     case OP_ADDIBT:
00482     case OP_ADDBF:
00483     case OP_ADDIBF:
00484     case OP_CMPBDF:
00485     case OP_BVB:
00486     case OP_BB:
00487     case OP_MOVB:
00488     case OP_MOVIB:
00489     case OP_CMPIBD:
00490       return 12;
00491 
00492     case OP_LDO:
00493     case OP_LDB:
00494     case OP_LDH:
00495     case OP_LDW:
00496     case OP_LDWM:
00497     case OP_STB:
00498     case OP_STH:
00499     case OP_STW:
00500     case OP_STWM:
00501       if (abfd->arch_info->mach >= 25)
00502        return 16;    /* Wide mode, format 16.  */
00503       return 14;
00504 
00505     case OP_FLDW:
00506     case OP_LDWL:
00507     case OP_FSTW:
00508     case OP_STWL:
00509       /* This is a hack.  Unfortunately, format 11 is already taken
00510         and we're using integers rather than an enum, so it's hard
00511         to describe the 11a format.  */
00512       if (abfd->arch_info->mach >= 25)
00513        return -16;   /* Wide mode, format 16a.  */
00514       return -11;
00515 
00516     case OP_LDD:
00517     case OP_STD:
00518       if (abfd->arch_info->mach >= 25)
00519        return -10;   /* Wide mode, format 10a.  */
00520       return 10;
00521 
00522     case OP_BL:
00523       if ((insn & 0x8000) != 0)
00524        return 22;
00525       /* fall thru */
00526     case OP_BE:
00527     case OP_BLE:
00528       return 17;
00529 
00530     case OP_LDIL:
00531     case OP_ADDIL:
00532       return 21;
00533 
00534     default:
00535       break;
00536     }
00537   return 32;
00538 }
00539 
00540 
00541 /* Insert VALUE into INSN using R_FORMAT to determine exactly what
00542    bits to change.  */
00543 
00544 static inline int
00545 hppa_rebuild_insn (int insn, int value, int r_format)
00546 {
00547   switch (r_format)
00548     {
00549     case 11:
00550       return (insn & ~ 0x7ff) | low_sign_unext (value, 11);
00551 
00552     case 12:
00553       return (insn & ~ 0x1ffd) | re_assemble_12 (value);
00554 
00555 
00556     case 10:
00557       return (insn & ~ 0x3ff1) | re_assemble_14 (value & -8);
00558 
00559     case -11:
00560       return (insn & ~ 0x3ff9) | re_assemble_14 (value & -4);
00561 
00562     case 14:
00563       return (insn & ~ 0x3fff) | re_assemble_14 (value);
00564 
00565 
00566     case -10:
00567       return (insn & ~ 0xfff1) | re_assemble_16 (value & -8);
00568 
00569     case -16:
00570       return (insn & ~ 0xfff9) | re_assemble_16 (value & -4);
00571 
00572     case 16:
00573       return (insn & ~ 0xffff) | re_assemble_16 (value);
00574 
00575 
00576     case 17:
00577       return (insn & ~ 0x1f1ffd) | re_assemble_17 (value);
00578 
00579     case 21:
00580       return (insn & ~ 0x1fffff) | re_assemble_21 (value);
00581 
00582     case 22:
00583       return (insn & ~ 0x3ff1ffd) | re_assemble_22 (value);
00584 
00585     case 32:
00586       return value;
00587 
00588     default:
00589       abort ();
00590     }
00591   return insn;
00592 }
00593 
00594 #endif /* _LIBHPPA_H */