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