Make UEFI boot-platform build again
[haiku.git] / src / libs / libunwind / ia64 / Gregs.c
blobac6f738a6cdbdb7d38516dde653af21bd6a470a9
1 /* libunwind - a platform-independent unwind library
2 Copyright (C) 2001-2005 Hewlett-Packard Co
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5 This file is part of libunwind.
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
26 #include "offsets.h"
27 #include "regs.h"
28 #include "unwind_i.h"
30 static inline ia64_loc_t
31 linux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
33 #if !defined(UNW_LOCAL_ONLY) || defined(__linux)
34 unw_word_t addr = c->sigcontext_addr, flags, tmp_addr;
35 int i;
37 if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_SIGTRAMP
38 || ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_SIGTRAMP)
40 switch (reg)
42 case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
43 case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
44 /* Linux sigcontext contains the NaT bit of scratch register
45 N in bit position N of the sc_nat member. */
46 *nat_bitnr = (reg - UNW_IA64_NAT);
47 addr += LINUX_SC_NAT_OFF;
48 break;
50 case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
51 case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31:
52 addr += LINUX_SC_GR_OFF + 8 * (reg - UNW_IA64_GR);
53 break;
55 case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
56 addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR);
57 return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
59 case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
60 if (ia64_get (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0),
61 &flags) < 0)
62 return IA64_NULL_LOC;
64 if (!(flags & IA64_SC_FLAG_FPH_VALID))
66 /* initialize fph partition: */
67 tmp_addr = addr + LINUX_SC_FR_OFF + 32*16;
68 for (i = 32; i < 128; ++i, tmp_addr += 16)
69 if (ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0),
70 unw.read_only.f0) < 0)
71 return IA64_NULL_LOC;
72 /* mark fph partition as valid: */
73 if (ia64_put (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0),
74 flags | IA64_SC_FLAG_FPH_VALID) < 0)
75 return IA64_NULL_LOC;
78 addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR);
79 return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
81 case UNW_IA64_BR + 0: addr += LINUX_SC_BR_OFF + 0; break;
82 case UNW_IA64_BR + 6: addr += LINUX_SC_BR_OFF + 6*8; break;
83 case UNW_IA64_BR + 7: addr += LINUX_SC_BR_OFF + 7*8; break;
84 case UNW_IA64_AR_RSC: addr += LINUX_SC_AR_RSC_OFF; break;
85 case UNW_IA64_AR_CSD: addr += LINUX_SC_AR_CSD_OFF; break;
86 case UNW_IA64_AR_SSD: addr += LINUX_SC_AR_SSD_OFF; break;
87 case UNW_IA64_AR_CCV: addr += LINUX_SC_AR_CCV; break;
89 default:
90 if (unw_is_fpreg (reg))
91 return IA64_FPREG_LOC (c, reg);
92 else
93 return IA64_REG_LOC (c, reg);
95 return IA64_LOC_ADDR (addr, 0);
97 else
99 int is_nat = 0;
101 if ((unsigned) (reg - UNW_IA64_NAT) < 128)
103 is_nat = 1;
104 reg -= (UNW_IA64_NAT - UNW_IA64_GR);
106 if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_INTERRUPT)
108 switch (reg)
110 case UNW_IA64_BR + 6 ... UNW_IA64_BR + 7:
111 addr += LINUX_PT_B6_OFF + 8 * (reg - (UNW_IA64_BR + 6));
112 break;
114 case UNW_IA64_AR_CSD: addr += LINUX_PT_CSD_OFF; break;
115 case UNW_IA64_AR_SSD: addr += LINUX_PT_SSD_OFF; break;
117 case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11:
118 addr += LINUX_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8));
119 break;
121 case UNW_IA64_IP: addr += LINUX_PT_IIP_OFF; break;
122 case UNW_IA64_CFM: addr += LINUX_PT_IFS_OFF; break;
123 case UNW_IA64_AR_UNAT: addr += LINUX_PT_UNAT_OFF; break;
124 case UNW_IA64_AR_PFS: addr += LINUX_PT_PFS_OFF; break;
125 case UNW_IA64_AR_RSC: addr += LINUX_PT_RSC_OFF; break;
126 case UNW_IA64_AR_RNAT: addr += LINUX_PT_RNAT_OFF; break;
127 case UNW_IA64_AR_BSPSTORE: addr += LINUX_PT_BSPSTORE_OFF; break;
128 case UNW_IA64_PR: addr += LINUX_PT_PR_OFF; break;
129 case UNW_IA64_BR + 0: addr += LINUX_PT_B0_OFF; break;
131 case UNW_IA64_GR + 1:
132 /* The saved r1 value is valid only in the frame in which
133 it was saved; for everything else we need to look up
134 the appropriate gp value. */
135 if (c->sigcontext_addr != c->sp + 0x10)
136 return IA64_NULL_LOC;
137 addr += LINUX_PT_R1_OFF;
138 break;
140 case UNW_IA64_GR + 12: addr += LINUX_PT_R12_OFF; break;
141 case UNW_IA64_GR + 13: addr += LINUX_PT_R13_OFF; break;
142 case UNW_IA64_AR_FPSR: addr += LINUX_PT_FPSR_OFF; break;
143 case UNW_IA64_GR + 15: addr += LINUX_PT_R15_OFF; break;
144 case UNW_IA64_GR + 14: addr += LINUX_PT_R14_OFF; break;
145 case UNW_IA64_GR + 2: addr += LINUX_PT_R2_OFF; break;
146 case UNW_IA64_GR + 3: addr += LINUX_PT_R3_OFF; break;
148 case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31:
149 addr += LINUX_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16));
150 break;
152 case UNW_IA64_AR_CCV: addr += LINUX_PT_CCV_OFF; break;
154 case UNW_IA64_FR + 6 ... UNW_IA64_FR + 11:
155 addr += LINUX_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6));
156 return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
158 default:
159 if (unw_is_fpreg (reg))
160 return IA64_FPREG_LOC (c, reg);
161 else
162 return IA64_REG_LOC (c, reg);
165 else if (ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_INTERRUPT)
167 switch (reg)
169 case UNW_IA64_GR + 1:
170 /* The saved r1 value is valid only in the frame in which
171 it was saved; for everything else we need to look up
172 the appropriate gp value. */
173 if (c->sigcontext_addr != c->sp + 0x10)
174 return IA64_NULL_LOC;
175 addr += LINUX_OLD_PT_R1_OFF;
176 break;
178 case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
179 addr += LINUX_OLD_PT_R2_OFF + 8 * (reg - (UNW_IA64_GR + 2));
180 break;
182 case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11:
183 addr += LINUX_OLD_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8));
184 break;
186 case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31:
187 addr += LINUX_OLD_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16));
188 break;
190 case UNW_IA64_FR + 6 ... UNW_IA64_FR + 9:
191 addr += LINUX_OLD_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6));
192 return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP);
194 case UNW_IA64_BR + 0: addr += LINUX_OLD_PT_B0_OFF; break;
195 case UNW_IA64_BR + 6: addr += LINUX_OLD_PT_B6_OFF; break;
196 case UNW_IA64_BR + 7: addr += LINUX_OLD_PT_B7_OFF; break;
198 case UNW_IA64_AR_RSC: addr += LINUX_OLD_PT_RSC_OFF; break;
199 case UNW_IA64_AR_CCV: addr += LINUX_OLD_PT_CCV_OFF; break;
201 default:
202 if (unw_is_fpreg (reg))
203 return IA64_FPREG_LOC (c, reg);
204 else
205 return IA64_REG_LOC (c, reg);
208 if (is_nat)
210 /* For Linux pt-regs structure, bit number is determined by
211 the UNaT slot number (as determined by st8.spill) and the
212 bits are saved wherever the (primary) UNaT was saved. */
213 *nat_bitnr = ia64_unat_slot_num (addr);
214 return c->loc[IA64_REG_PRI_UNAT_MEM];
216 return IA64_LOC_ADDR (addr, 0);
218 #endif
219 return IA64_NULL_LOC;
222 static inline ia64_loc_t
223 hpux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
225 #if !defined(UNW_LOCAL_ONLY) || defined(__hpux)
226 return IA64_LOC_UC_REG (reg, c->sigcontext_addr);
227 #else
228 return IA64_NULL_LOC;
229 #endif
232 HIDDEN ia64_loc_t
233 ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr)
235 if (c->sigcontext_addr)
237 if (ia64_get_abi (c) == ABI_LINUX)
238 return linux_scratch_loc (c, reg, nat_bitnr);
239 else if (ia64_get_abi (c) == ABI_HPUX)
240 return hpux_scratch_loc (c, reg, nat_bitnr);
241 else
242 return IA64_NULL_LOC;
244 else
245 return IA64_REG_LOC (c, reg);
248 static inline int
249 update_nat (struct cursor *c, ia64_loc_t nat_loc, unw_word_t mask,
250 unw_word_t *valp, int write)
252 unw_word_t nat_word;
253 int ret;
255 ret = ia64_get (c, nat_loc, &nat_word);
256 if (ret < 0)
257 return ret;
259 if (write)
261 if (*valp)
262 nat_word |= mask;
263 else
264 nat_word &= ~mask;
265 ret = ia64_put (c, nat_loc, nat_word);
267 else
268 *valp = (nat_word & mask) != 0;
269 return ret;
272 static int
273 access_nat (struct cursor *c,
274 ia64_loc_t nat_loc, ia64_loc_t reg_loc, uint8_t nat_bitnr,
275 unw_word_t *valp, int write)
277 unw_word_t mask = 0;
278 unw_fpreg_t tmp;
279 int ret;
281 if (IA64_IS_FP_LOC (reg_loc))
283 /* NaT bit is saved as a NaTVal. This happens when a general
284 register is saved to a floating-point register. */
285 if (write)
287 if (*valp)
289 if (ia64_is_big_endian (c))
290 ret = ia64_putfp (c, reg_loc, unw.nat_val_be);
291 else
292 ret = ia64_putfp (c, reg_loc, unw.nat_val_le);
294 else
296 unw_word_t *src, *dst;
297 unw_fpreg_t tmp;
299 ret = ia64_getfp (c, reg_loc, &tmp);
300 if (ret < 0)
301 return ret;
303 /* Reset the exponent to 0x1003e so that the significand
304 will be interpreted as an integer value. */
305 src = (unw_word_t *) &unw.int_val_be;
306 dst = (unw_word_t *) &tmp;
307 if (!ia64_is_big_endian (c))
308 ++src, ++dst;
309 *dst = *src;
311 ret = ia64_putfp (c, reg_loc, tmp);
314 else
316 ret = ia64_getfp (c, reg_loc, &tmp);
317 if (ret < 0)
318 return ret;
320 if (ia64_is_big_endian (c))
321 *valp = (memcmp (&tmp, &unw.nat_val_be, sizeof (tmp)) == 0);
322 else
323 *valp = (memcmp (&tmp, &unw.nat_val_le, sizeof (tmp)) == 0);
325 return ret;
328 if ((IA64_IS_REG_LOC (nat_loc)
329 && (unsigned) (IA64_GET_REG (nat_loc) - UNW_IA64_NAT) < 128)
330 || IA64_IS_UC_LOC (reg_loc))
332 if (write)
333 return ia64_put (c, nat_loc, *valp);
334 else
335 return ia64_get (c, nat_loc, valp);
338 if (IA64_IS_NULL_LOC (nat_loc))
340 /* NaT bit is not saved. This happens if a general register is
341 saved to a branch register. Since the NaT bit gets lost, we
342 need to drop it here, too. Note that if the NaT bit had been
343 set when the save occurred, it would have caused a NaT
344 consumption fault. */
345 if (write)
347 if (*valp)
348 return -UNW_EBADREG; /* can't set NaT bit */
350 else
351 *valp = 0;
352 return 0;
355 mask = (unw_word_t) 1 << nat_bitnr;
356 return update_nat (c, nat_loc, mask, valp, write);
359 HIDDEN int
360 tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
361 int write)
363 ia64_loc_t loc, reg_loc, nat_loc;
364 unw_word_t mask, val;
365 uint8_t nat_bitnr;
366 int ret;
368 switch (reg)
370 /* frame registers: */
372 case UNW_IA64_BSP:
373 if (write)
374 c->bsp = *valp;
375 else
376 *valp = c->bsp;
377 return 0;
379 case UNW_REG_SP:
380 if (write)
381 c->sp = *valp;
382 else
383 *valp = c->sp;
384 return 0;
386 case UNW_REG_IP:
387 if (write)
389 c->ip = *valp; /* also update the IP cache */
390 if (c->pi_valid && (*valp < c->pi.start_ip || *valp >= c->pi.end_ip))
391 c->pi_valid = 0; /* new IP outside of current proc */
393 loc = c->loc[IA64_REG_IP];
394 break;
396 /* preserved registers: */
398 case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
399 loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))];
400 break;
402 case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7:
403 loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))];
404 reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))];
405 nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)];
406 return access_nat (c, loc, reg_loc, nat_bitnr, valp, write);
408 case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break;
409 case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break;
410 case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break;
411 case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break;
412 case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break;
413 case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break;
414 case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break;
415 case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break;
416 case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break;
417 case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break;
418 case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break;
419 case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break;
421 case UNW_IA64_CFM:
422 if (write)
423 c->cfm = *valp; /* also update the CFM cache */
424 loc = c->cfm_loc;
425 break;
427 case UNW_IA64_PR:
429 * Note: broad-side access to the predicates is NOT rotated
430 * (i.e., it is done as if CFM.rrb.pr == 0.
432 if (write)
434 c->pr = *valp; /* update the predicate cache */
435 return ia64_put (c, c->loc[IA64_REG_PR], *valp);
437 else
438 return ia64_get (c, c->loc[IA64_REG_PR], valp);
440 case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */
441 reg = rotate_gr (c, reg - UNW_IA64_GR);
442 if (reg < 0)
443 return -UNW_EBADREG;
444 ret = ia64_get_stacked (c, reg, &loc, NULL);
445 if (ret < 0)
446 return ret;
447 break;
449 case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */
450 reg = rotate_gr (c, reg - UNW_IA64_NAT);
451 if (reg < 0)
452 return -UNW_EBADREG;
453 ret = ia64_get_stacked (c, reg, &loc, &nat_loc);
454 if (ret < 0)
455 return ret;
456 assert (!IA64_IS_REG_LOC (loc));
457 mask = (unw_word_t) 1 << rse_slot_num (IA64_GET_ADDR (loc));
458 return update_nat (c, nat_loc, mask, valp, write);
460 case UNW_IA64_AR_EC:
461 if ((ret = ia64_get (c, c->ec_loc, &val)) < 0)
462 return ret;
464 if (write)
466 val = ((val & ~((unw_word_t) 0x3f << 52)) | ((*valp & 0x3f) << 52));
467 return ia64_put (c, c->ec_loc, val);
469 else
471 *valp = (val >> 52) & 0x3f;
472 return 0;
475 /* scratch & special registers: */
477 case UNW_IA64_GR + 0:
478 if (write)
479 return -UNW_EREADONLYREG;
480 *valp = 0;
481 return 0;
483 case UNW_IA64_NAT + 0:
484 if (write)
485 return -UNW_EREADONLYREG;
486 *valp = 0;
487 return 0;
489 case UNW_IA64_NAT + 1:
490 case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3:
491 case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31:
492 loc = ia64_scratch_loc (c, reg, &nat_bitnr);
493 if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_NAT + 1)
495 /* access to GP */
496 if (write)
497 return -UNW_EREADONLYREG;
498 *valp = 0;
499 return 0;
501 if (!(IA64_IS_REG_LOC (loc) || IA64_IS_UC_LOC (loc)
502 || IA64_IS_FP_LOC (loc)))
503 /* We're dealing with a NaT bit stored in memory. */
504 return update_nat(c, loc, (unw_word_t) 1 << nat_bitnr, valp, write);
505 break;
507 case UNW_IA64_GR + 15 ... UNW_IA64_GR + 18:
508 mask = 1 << (reg - (UNW_IA64_GR + 15));
509 if (write)
511 c->eh_args[reg - (UNW_IA64_GR + 15)] = *valp;
512 c->eh_valid_mask |= mask;
513 return 0;
515 else if ((c->eh_valid_mask & mask) != 0)
517 *valp = c->eh_args[reg - (UNW_IA64_GR + 15)];
518 return 0;
520 else
521 loc = ia64_scratch_loc (c, reg, NULL);
522 break;
524 case UNW_IA64_GR + 1: /* global pointer */
525 case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3:
526 case UNW_IA64_GR + 8 ... UNW_IA64_GR + 14:
527 case UNW_IA64_GR + 19 ... UNW_IA64_GR + 31:
528 case UNW_IA64_BR + 0:
529 case UNW_IA64_BR + 6:
530 case UNW_IA64_BR + 7:
531 case UNW_IA64_AR_RSC:
532 case UNW_IA64_AR_CSD:
533 case UNW_IA64_AR_SSD:
534 case UNW_IA64_AR_CCV:
535 loc = ia64_scratch_loc (c, reg, NULL);
536 if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_GR + 1)
538 /* access to GP */
539 if (write)
540 return -UNW_EREADONLYREG;
542 /* ensure c->pi is up-to-date: */
543 if ((ret = ia64_make_proc_info (c)) < 0)
544 return ret;
545 *valp = c->pi.gp;
546 return 0;
548 break;
550 default:
551 Debug (1, "bad register number %d\n", reg);
552 return -UNW_EBADREG;
555 if (write)
556 return ia64_put (c, loc, *valp);
557 else
558 return ia64_get (c, loc, valp);
561 HIDDEN int
562 tdep_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp,
563 int write)
565 ia64_loc_t loc;
567 switch (reg)
569 case UNW_IA64_FR + 0:
570 if (write)
571 return -UNW_EREADONLYREG;
572 *valp = unw.read_only.f0;
573 return 0;
575 case UNW_IA64_FR + 1:
576 if (write)
577 return -UNW_EREADONLYREG;
579 if (ia64_is_big_endian (c))
580 *valp = unw.read_only.f1_be;
581 else
582 *valp = unw.read_only.f1_le;
583 return 0;
585 case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break;
586 case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break;
587 case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break;
588 case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break;
590 case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
591 loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))];
592 break;
594 case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15:
595 loc = ia64_scratch_loc (c, reg, NULL);
596 break;
598 case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127:
599 reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR;
600 loc = ia64_scratch_loc (c, reg, NULL);
601 break;
603 default:
604 Debug (1, "bad register number %d\n", reg);
605 return -UNW_EBADREG;
608 if (write)
609 return ia64_putfp (c, loc, *valp);
610 else
611 return ia64_getfp (c, loc, valp);