1 /*
2  * Ptrace interface test helper functions
3  *
4  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 #include <inttypes.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <malloc.h>
16 #include <errno.h>
17 #include <time.h>
18 #include <sys/ptrace.h>
19 #include <sys/ioctl.h>
20 #include <sys/uio.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <sys/signal.h>
24 #include <sys/ipc.h>
25 #include <sys/shm.h>
26 #include <sys/user.h>
27 #include <linux/elf.h>
28 #include <linux/types.h>
29 #include <linux/auxvec.h>
30 #include "reg.h"
31 #include "utils.h"
32 
33 #define TEST_PASS 0
34 #define TEST_FAIL 1
35 
36 struct fpr_regs {
37 	unsigned long fpr[32];
38 	unsigned long fpscr;
39 };
40 
41 struct tm_spr_regs {
42 	unsigned long tm_tfhar;
43 	unsigned long tm_texasr;
44 	unsigned long tm_tfiar;
45 };
46 
47 #ifndef NT_PPC_TAR
48 #define NT_PPC_TAR	0x103
49 #define NT_PPC_PPR	0x104
50 #define NT_PPC_DSCR	0x105
51 #define NT_PPC_EBB	0x106
52 #define NT_PPC_PMU	0x107
53 #define NT_PPC_TM_CGPR	0x108
54 #define NT_PPC_TM_CFPR	0x109
55 #define NT_PPC_TM_CVMX	0x10a
56 #define NT_PPC_TM_CVSX	0x10b
57 #define NT_PPC_TM_SPR	0x10c
58 #define NT_PPC_TM_CTAR	0x10d
59 #define NT_PPC_TM_CPPR	0x10e
60 #define NT_PPC_TM_CDSCR	0x10f
61 #endif
62 
63 /* Basic ptrace operations */
64 int start_trace(pid_t child)
65 {
66 	int ret;
67 
68 	ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
69 	if (ret) {
70 		perror("ptrace(PTRACE_ATTACH) failed");
71 		return TEST_FAIL;
72 	}
73 	ret = waitpid(child, NULL, 0);
74 	if (ret != child) {
75 		perror("waitpid() failed");
76 		return TEST_FAIL;
77 	}
78 	return TEST_PASS;
79 }
80 
81 int stop_trace(pid_t child)
82 {
83 	int ret;
84 
85 	ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
86 	if (ret) {
87 		perror("ptrace(PTRACE_DETACH) failed");
88 		return TEST_FAIL;
89 	}
90 	return TEST_PASS;
91 }
92 
93 int cont_trace(pid_t child)
94 {
95 	int ret;
96 
97 	ret = ptrace(PTRACE_CONT, child, NULL, NULL);
98 	if (ret) {
99 		perror("ptrace(PTRACE_CONT) failed");
100 		return TEST_FAIL;
101 	}
102 	return TEST_PASS;
103 }
104 
105 int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[],
106 		     int n)
107 {
108 	struct iovec iov;
109 	long ret;
110 
111 	FAIL_IF(start_trace(child));
112 
113 	iov.iov_base = regs;
114 	iov.iov_len = n * sizeof(unsigned long);
115 
116 	ret = ptrace(PTRACE_GETREGSET, child, type, &iov);
117 	if (ret)
118 		return ret;
119 
120 	FAIL_IF(stop_trace(child));
121 
122 	return TEST_PASS;
123 }
124 
125 long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[],
126 		       int n)
127 {
128 	struct iovec iov;
129 	long ret;
130 
131 	FAIL_IF(start_trace(child));
132 
133 	iov.iov_base = regs;
134 	iov.iov_len = n * sizeof(unsigned long);
135 
136 	ret = ptrace(PTRACE_SETREGSET, child, type, &iov);
137 
138 	FAIL_IF(stop_trace(child));
139 
140 	return ret;
141 }
142 
143 /* TAR, PPR, DSCR */
144 int show_tar_registers(pid_t child, unsigned long *out)
145 {
146 	struct iovec iov;
147 	unsigned long *reg;
148 	int ret;
149 
150 	reg = malloc(sizeof(unsigned long));
151 	if (!reg) {
152 		perror("malloc() failed");
153 		return TEST_FAIL;
154 	}
155 	iov.iov_base = (u64 *) reg;
156 	iov.iov_len = sizeof(unsigned long);
157 
158 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TAR, &iov);
159 	if (ret) {
160 		perror("ptrace(PTRACE_GETREGSET) failed");
161 		goto fail;
162 	}
163 	if (out)
164 		out[0] = *reg;
165 
166 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_PPR, &iov);
167 	if (ret) {
168 		perror("ptrace(PTRACE_GETREGSET) failed");
169 		goto fail;
170 	}
171 	if (out)
172 		out[1] = *reg;
173 
174 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_DSCR, &iov);
175 	if (ret) {
176 		perror("ptrace(PTRACE_GETREGSET) failed");
177 		goto fail;
178 	}
179 	if (out)
180 		out[2] = *reg;
181 
182 	free(reg);
183 	return TEST_PASS;
184 fail:
185 	free(reg);
186 	return TEST_FAIL;
187 }
188 
189 int write_tar_registers(pid_t child, unsigned long tar,
190 		unsigned long ppr, unsigned long dscr)
191 {
192 	struct iovec iov;
193 	unsigned long *reg;
194 	int ret;
195 
196 	reg = malloc(sizeof(unsigned long));
197 	if (!reg) {
198 		perror("malloc() failed");
199 		return TEST_FAIL;
200 	}
201 
202 	iov.iov_base = (u64 *) reg;
203 	iov.iov_len = sizeof(unsigned long);
204 
205 	*reg = tar;
206 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TAR, &iov);
207 	if (ret) {
208 		perror("ptrace(PTRACE_SETREGSET) failed");
209 		goto fail;
210 	}
211 
212 	*reg = ppr;
213 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_PPR, &iov);
214 	if (ret) {
215 		perror("ptrace(PTRACE_SETREGSET) failed");
216 		goto fail;
217 	}
218 
219 	*reg = dscr;
220 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_DSCR, &iov);
221 	if (ret) {
222 		perror("ptrace(PTRACE_SETREGSET) failed");
223 		goto fail;
224 	}
225 
226 	free(reg);
227 	return TEST_PASS;
228 fail:
229 	free(reg);
230 	return TEST_FAIL;
231 }
232 
233 int show_tm_checkpointed_state(pid_t child, unsigned long *out)
234 {
235 	struct iovec iov;
236 	unsigned long *reg;
237 	int ret;
238 
239 	reg = malloc(sizeof(unsigned long));
240 	if (!reg) {
241 		perror("malloc() failed");
242 		return TEST_FAIL;
243 	}
244 
245 	iov.iov_base = (u64 *) reg;
246 	iov.iov_len = sizeof(unsigned long);
247 
248 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CTAR, &iov);
249 	if (ret) {
250 		perror("ptrace(PTRACE_GETREGSET) failed");
251 		goto fail;
252 	}
253 	if (out)
254 		out[0] = *reg;
255 
256 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CPPR, &iov);
257 	if (ret) {
258 		perror("ptrace(PTRACE_GETREGSET) failed");
259 		goto fail;
260 	}
261 	if (out)
262 		out[1] = *reg;
263 
264 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CDSCR, &iov);
265 	if (ret) {
266 		perror("ptrace(PTRACE_GETREGSET) failed");
267 		goto fail;
268 	}
269 	if (out)
270 		out[2] = *reg;
271 
272 	free(reg);
273 	return TEST_PASS;
274 
275 fail:
276 	free(reg);
277 	return TEST_FAIL;
278 }
279 
280 int write_ckpt_tar_registers(pid_t child, unsigned long tar,
281 		unsigned long ppr, unsigned long dscr)
282 {
283 	struct iovec iov;
284 	unsigned long *reg;
285 	int ret;
286 
287 	reg = malloc(sizeof(unsigned long));
288 	if (!reg) {
289 		perror("malloc() failed");
290 		return TEST_FAIL;
291 	}
292 
293 	iov.iov_base = (u64 *) reg;
294 	iov.iov_len = sizeof(unsigned long);
295 
296 	*reg = tar;
297 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CTAR, &iov);
298 	if (ret) {
299 		perror("ptrace(PTRACE_GETREGSET) failed");
300 		goto fail;
301 	}
302 
303 	*reg = ppr;
304 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CPPR, &iov);
305 	if (ret) {
306 		perror("ptrace(PTRACE_GETREGSET) failed");
307 		goto fail;
308 	}
309 
310 	*reg = dscr;
311 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CDSCR, &iov);
312 	if (ret) {
313 		perror("ptrace(PTRACE_GETREGSET) failed");
314 		goto fail;
315 	}
316 
317 	free(reg);
318 	return TEST_PASS;
319 fail:
320 	free(reg);
321 	return TEST_FAIL;
322 }
323 
324 /* FPR */
325 int show_fpr(pid_t child, unsigned long *fpr)
326 {
327 	struct fpr_regs *regs;
328 	int ret, i;
329 
330 	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
331 	ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
332 	if (ret) {
333 		perror("ptrace(PTRACE_GETREGSET) failed");
334 		return TEST_FAIL;
335 	}
336 
337 	if (fpr) {
338 		for (i = 0; i < 32; i++)
339 			fpr[i] = regs->fpr[i];
340 	}
341 	return TEST_PASS;
342 }
343 
344 int write_fpr(pid_t child, unsigned long val)
345 {
346 	struct fpr_regs *regs;
347 	int ret, i;
348 
349 	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
350 	ret = ptrace(PTRACE_GETFPREGS, child, NULL, regs);
351 	if (ret) {
352 		perror("ptrace(PTRACE_GETREGSET) failed");
353 		return TEST_FAIL;
354 	}
355 
356 	for (i = 0; i < 32; i++)
357 		regs->fpr[i] = val;
358 
359 	ret = ptrace(PTRACE_SETFPREGS, child, NULL, regs);
360 	if (ret) {
361 		perror("ptrace(PTRACE_GETREGSET) failed");
362 		return TEST_FAIL;
363 	}
364 	return TEST_PASS;
365 }
366 
367 int show_ckpt_fpr(pid_t child, unsigned long *fpr)
368 {
369 	struct fpr_regs *regs;
370 	struct iovec iov;
371 	int ret, i;
372 
373 	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
374 	iov.iov_base = regs;
375 	iov.iov_len = sizeof(struct fpr_regs);
376 
377 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
378 	if (ret) {
379 		perror("ptrace(PTRACE_GETREGSET) failed");
380 		return TEST_FAIL;
381 	}
382 
383 	if (fpr) {
384 		for (i = 0; i < 32; i++)
385 			fpr[i] = regs->fpr[i];
386 	}
387 
388 	return TEST_PASS;
389 }
390 
391 int write_ckpt_fpr(pid_t child, unsigned long val)
392 {
393 	struct fpr_regs *regs;
394 	struct iovec iov;
395 	int ret, i;
396 
397 	regs = (struct fpr_regs *) malloc(sizeof(struct fpr_regs));
398 	iov.iov_base = regs;
399 	iov.iov_len = sizeof(struct fpr_regs);
400 
401 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
402 	if (ret) {
403 		perror("ptrace(PTRACE_GETREGSET) failed");
404 		return TEST_FAIL;
405 	}
406 
407 	for (i = 0; i < 32; i++)
408 		regs->fpr[i] = val;
409 
410 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CFPR, &iov);
411 	if (ret) {
412 		perror("ptrace(PTRACE_GETREGSET) failed");
413 		return TEST_FAIL;
414 	}
415 	return TEST_PASS;
416 }
417 
418 /* GPR */
419 int show_gpr(pid_t child, unsigned long *gpr)
420 {
421 	struct pt_regs *regs;
422 	int ret, i;
423 
424 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
425 	if (!regs) {
426 		perror("malloc() failed");
427 		return TEST_FAIL;
428 	}
429 
430 	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
431 	if (ret) {
432 		perror("ptrace(PTRACE_GETREGSET) failed");
433 		return TEST_FAIL;
434 	}
435 
436 	if (gpr) {
437 		for (i = 14; i < 32; i++)
438 			gpr[i-14] = regs->gpr[i];
439 	}
440 
441 	return TEST_PASS;
442 }
443 
444 int write_gpr(pid_t child, unsigned long val)
445 {
446 	struct pt_regs *regs;
447 	int i, ret;
448 
449 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
450 	if (!regs) {
451 		perror("malloc() failed");
452 		return TEST_FAIL;
453 	}
454 
455 	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
456 	if (ret) {
457 		perror("ptrace(PTRACE_GETREGSET) failed");
458 		return TEST_FAIL;
459 	}
460 
461 	for (i = 14; i < 32; i++)
462 		regs->gpr[i] = val;
463 
464 	ret = ptrace(PTRACE_SETREGS, child, NULL, regs);
465 	if (ret) {
466 		perror("ptrace(PTRACE_GETREGSET) failed");
467 		return TEST_FAIL;
468 	}
469 	return TEST_PASS;
470 }
471 
472 int show_ckpt_gpr(pid_t child, unsigned long *gpr)
473 {
474 	struct pt_regs *regs;
475 	struct iovec iov;
476 	int ret, i;
477 
478 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
479 	if (!regs) {
480 		perror("malloc() failed");
481 		return TEST_FAIL;
482 	}
483 
484 	iov.iov_base = (u64 *) regs;
485 	iov.iov_len = sizeof(struct pt_regs);
486 
487 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
488 	if (ret) {
489 		perror("ptrace(PTRACE_GETREGSET) failed");
490 		return TEST_FAIL;
491 	}
492 
493 	if (gpr) {
494 		for (i = 14; i < 32; i++)
495 			gpr[i-14] = regs->gpr[i];
496 	}
497 
498 	return TEST_PASS;
499 }
500 
501 int write_ckpt_gpr(pid_t child, unsigned long val)
502 {
503 	struct pt_regs *regs;
504 	struct iovec iov;
505 	int ret, i;
506 
507 	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
508 	if (!regs) {
509 		perror("malloc() failed\n");
510 		return TEST_FAIL;
511 	}
512 	iov.iov_base = (u64 *) regs;
513 	iov.iov_len = sizeof(struct pt_regs);
514 
515 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
516 	if (ret) {
517 		perror("ptrace(PTRACE_GETREGSET) failed");
518 		return TEST_FAIL;
519 	}
520 
521 	for (i = 14; i < 32; i++)
522 		regs->gpr[i] = val;
523 
524 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CGPR, &iov);
525 	if (ret) {
526 		perror("ptrace(PTRACE_GETREGSET) failed");
527 		return TEST_FAIL;
528 	}
529 	return TEST_PASS;
530 }
531 
532 /* VMX */
533 int show_vmx(pid_t child, unsigned long vmx[][2])
534 {
535 	int ret;
536 
537 	ret = ptrace(PTRACE_GETVRREGS, child, 0, vmx);
538 	if (ret) {
539 		perror("ptrace(PTRACE_GETVRREGS) failed");
540 		return TEST_FAIL;
541 	}
542 	return TEST_PASS;
543 }
544 
545 int show_vmx_ckpt(pid_t child, unsigned long vmx[][2])
546 {
547 	unsigned long regs[34][2];
548 	struct iovec iov;
549 	int ret;
550 
551 	iov.iov_base = (u64 *) regs;
552 	iov.iov_len = sizeof(regs);
553 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVMX, &iov);
554 	if (ret) {
555 		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVMX) failed");
556 		return TEST_FAIL;
557 	}
558 	memcpy(vmx, regs, sizeof(regs));
559 	return TEST_PASS;
560 }
561 
562 
563 int write_vmx(pid_t child, unsigned long vmx[][2])
564 {
565 	int ret;
566 
567 	ret = ptrace(PTRACE_SETVRREGS, child, 0, vmx);
568 	if (ret) {
569 		perror("ptrace(PTRACE_SETVRREGS) failed");
570 		return TEST_FAIL;
571 	}
572 	return TEST_PASS;
573 }
574 
575 int write_vmx_ckpt(pid_t child, unsigned long vmx[][2])
576 {
577 	unsigned long regs[34][2];
578 	struct iovec iov;
579 	int ret;
580 
581 	memcpy(regs, vmx, sizeof(regs));
582 	iov.iov_base = (u64 *) regs;
583 	iov.iov_len = sizeof(regs);
584 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVMX, &iov);
585 	if (ret) {
586 		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVMX) failed");
587 		return TEST_FAIL;
588 	}
589 	return TEST_PASS;
590 }
591 
592 /* VSX */
593 int show_vsx(pid_t child, unsigned long *vsx)
594 {
595 	int ret;
596 
597 	ret = ptrace(PTRACE_GETVSRREGS, child, 0, vsx);
598 	if (ret) {
599 		perror("ptrace(PTRACE_GETVSRREGS) failed");
600 		return TEST_FAIL;
601 	}
602 	return TEST_PASS;
603 }
604 
605 int show_vsx_ckpt(pid_t child, unsigned long *vsx)
606 {
607 	unsigned long regs[32];
608 	struct iovec iov;
609 	int ret;
610 
611 	iov.iov_base = (u64 *) regs;
612 	iov.iov_len = sizeof(regs);
613 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CVSX, &iov);
614 	if (ret) {
615 		perror("ptrace(PTRACE_GETREGSET, NT_PPC_TM_CVSX) failed");
616 		return TEST_FAIL;
617 	}
618 	memcpy(vsx, regs, sizeof(regs));
619 	return TEST_PASS;
620 }
621 
622 int write_vsx(pid_t child, unsigned long *vsx)
623 {
624 	int ret;
625 
626 	ret = ptrace(PTRACE_SETVSRREGS, child, 0, vsx);
627 	if (ret) {
628 		perror("ptrace(PTRACE_SETVSRREGS) failed");
629 		return TEST_FAIL;
630 	}
631 	return TEST_PASS;
632 }
633 
634 int write_vsx_ckpt(pid_t child, unsigned long *vsx)
635 {
636 	unsigned long regs[32];
637 	struct iovec iov;
638 	int ret;
639 
640 	memcpy(regs, vsx, sizeof(regs));
641 	iov.iov_base = (u64 *) regs;
642 	iov.iov_len = sizeof(regs);
643 	ret = ptrace(PTRACE_SETREGSET, child, NT_PPC_TM_CVSX, &iov);
644 	if (ret) {
645 		perror("ptrace(PTRACE_SETREGSET, NT_PPC_TM_CVSX) failed");
646 		return TEST_FAIL;
647 	}
648 	return TEST_PASS;
649 }
650 
651 /* TM SPR */
652 int show_tm_spr(pid_t child, struct tm_spr_regs *out)
653 {
654 	struct tm_spr_regs *regs;
655 	struct iovec iov;
656 	int ret;
657 
658 	regs = (struct tm_spr_regs *) malloc(sizeof(struct tm_spr_regs));
659 	if (!regs) {
660 		perror("malloc() failed");
661 		return TEST_FAIL;
662 	}
663 
664 	iov.iov_base = (u64 *) regs;
665 	iov.iov_len = sizeof(struct tm_spr_regs);
666 
667 	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
668 	if (ret) {
669 		perror("ptrace(PTRACE_GETREGSET) failed");
670 		return TEST_FAIL;
671 	}
672 
673 	if (out)
674 		memcpy(out, regs, sizeof(struct tm_spr_regs));
675 
676 	return TEST_PASS;
677 }
678 
679 
680 
681 /* Analyse TEXASR after TM failure */
682 inline unsigned long get_tfiar(void)
683 {
684 	unsigned long ret;
685 
686 	asm volatile("mfspr %0,%1" : "=r" (ret) : "i" (SPRN_TFIAR));
687 	return ret;
688 }
689 
690 void analyse_texasr(unsigned long texasr)
691 {
692 	printf("TEXASR: %16lx\t", texasr);
693 
694 	if (texasr & TEXASR_FP)
695 		printf("TEXASR_FP  ");
696 
697 	if (texasr & TEXASR_DA)
698 		printf("TEXASR_DA  ");
699 
700 	if (texasr & TEXASR_NO)
701 		printf("TEXASR_NO  ");
702 
703 	if (texasr & TEXASR_FO)
704 		printf("TEXASR_FO  ");
705 
706 	if (texasr & TEXASR_SIC)
707 		printf("TEXASR_SIC  ");
708 
709 	if (texasr & TEXASR_NTC)
710 		printf("TEXASR_NTC  ");
711 
712 	if (texasr & TEXASR_TC)
713 		printf("TEXASR_TC  ");
714 
715 	if (texasr & TEXASR_TIC)
716 		printf("TEXASR_TIC  ");
717 
718 	if (texasr & TEXASR_IC)
719 		printf("TEXASR_IC  ");
720 
721 	if (texasr & TEXASR_IFC)
722 		printf("TEXASR_IFC  ");
723 
724 	if (texasr & TEXASR_ABT)
725 		printf("TEXASR_ABT  ");
726 
727 	if (texasr & TEXASR_SPD)
728 		printf("TEXASR_SPD  ");
729 
730 	if (texasr & TEXASR_HV)
731 		printf("TEXASR_HV  ");
732 
733 	if (texasr & TEXASR_PR)
734 		printf("TEXASR_PR  ");
735 
736 	if (texasr & TEXASR_FS)
737 		printf("TEXASR_FS  ");
738 
739 	if (texasr & TEXASR_TE)
740 		printf("TEXASR_TE  ");
741 
742 	if (texasr & TEXASR_ROT)
743 		printf("TEXASR_ROT  ");
744 
745 	printf("TFIAR :%lx\n", get_tfiar());
746 }
747 
748 void store_gpr(unsigned long *addr);
749 void store_fpr(float *addr);
750