brintos

brintos / llvm-project-archived public Read only

0
0
Text · 1.4 KiB · 0a9a9c5 Raw
47 lines · c
1#include <asm/hwcap.h>2#include <stdint.h>3#include <sys/auxv.h>4 5#ifndef HWCAP2_FPMR6#define HWCAP2_FPMR (1UL << 48)7#endif8 9uint64_t get_fpmr(void) {10  uint64_t fpmr = 0;11  __asm__ volatile("mrs %0, s3_3_c4_c4_2" : "=r"(fpmr));12  return fpmr;13}14 15void set_fpmr(uint64_t value) {16  __asm__ volatile("msr s3_3_c4_c4_2, %0" ::"r"(value));17}18 19// Set F8S1 (bits 0-2) and LSCALE2 (bits 37-32) (to prove we treat fpmr as 6420// bit).21const uint64_t original_fpmr = (uint64_t)0b101010 << 32 | (uint64_t)0b101;22 23void expr_func() { set_fpmr(original_fpmr); }24 25int main(int argc, char *argv[]) {26  if (!(getauxval(AT_HWCAP2) & HWCAP2_FPMR))27    return 1;28 29  // As FPMR controls a bunch of floating point options that are quite30  // extensive, we're not going to run any floating point ops here. Instead just31  // update the value from the debugger and check it from this program, and vice32  // versa.33  set_fpmr(original_fpmr);34 35  // Here the debugger checks it read back the value above, then writes in a new36  // value. Note that the bits are flipped in the new value.37  uint64_t new_fpmr = get_fpmr(); // Set break point at this line.38  uint64_t expected_fpmr = ((uint64_t)0b010101 << 32) | (uint64_t)0b010;39 40  // If the debugger failed to update the value, exit uncleanly.41  // This also allows you to run this program standalone to create a core file.42  if (new_fpmr != expected_fpmr)43    __builtin_trap();44 45  return 0;46}47