00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef _LIBHPPA_H
00025 #define _LIBHPPA_H
00026
00027 #define BYTES_IN_WORD 4
00028 #define PA_PAGESIZE 0x1000
00029
00030
00031 enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20, pa20w = 25};
00032
00033
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
00060
00061
00062
00063
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
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
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
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
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
00157
00158
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
00178
00179
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
00197
00198
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
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
00287
00288
00289
00290
00291
00292
00293
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
00308 break;
00309
00310 case e_nsel:
00311
00312
00313
00314
00315
00316 value = 0;
00317 break;
00318
00319 case e_lsel:
00320 case e_nlsel:
00321
00322 value = value >> 11;
00323 break;
00324
00325 case e_rsel:
00326
00327 value = value & 0x7ff;
00328 break;
00329
00330 case e_lssel:
00331
00332 value = value + 0x400;
00333 value = value >> 11;
00334 break;
00335
00336 case e_rssel:
00337
00338
00339
00340
00341 value = ((value & 0x7ff) ^ 0x400) - 0x400;
00342 break;
00343
00344 case e_ldsel:
00345
00346
00347
00348 value = value + 0x800;
00349 value = value >> 11;
00350 break;
00351
00352 case e_rdsel:
00353
00354 value = value | -0x800;
00355 break;
00356
00357 case e_lrsel:
00358 case e_nlrsel:
00359
00360 value = sym_val + ((addend + 0x1000) & -0x2000);
00361 value = value >> 11;
00362 break;
00363
00364 case e_rrsel:
00365
00366
00367
00368
00369
00370 value = (sym_val & 0x7ff) + (((addend & 0x1fff) ^ 0x1000) - 0x1000);
00371 break;
00372
00373 default:
00374 abort ();
00375 }
00376 return value;
00377 }
00378
00379
00380 #define get_opcode(insn) (((insn) >> 26) & 0x3f)
00381
00382 enum hppa_opcode_type
00383 {
00384
00385
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
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;
00503 return 14;
00504
00505 case OP_FLDW:
00506 case OP_LDWL:
00507 case OP_FSTW:
00508 case OP_STWL:
00509
00510
00511
00512 if (abfd->arch_info->mach >= 25)
00513 return -16;
00514 return -11;
00515
00516 case OP_LDD:
00517 case OP_STD:
00518 if (abfd->arch_info->mach >= 25)
00519 return -10;
00520 return 10;
00521
00522 case OP_BL:
00523 if ((insn & 0x8000) != 0)
00524 return 22;
00525
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
00542
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