#include <stdint.h>
-
+#include <sys/mman.h>
/* Something of the same size as void*, so can be safely be coerced
to/from a pointer type. Also same size as the host's gp registers. */
#endif // #ifndef __powerpc64__
+/* Return a pointer to a 1-page area where is is safe to both write
+ and execute instructions. Area is filled with 'trap' insns. */
+static
+uint32_t* get_rwx_area ( void )
+{
+ int i;
+ static uint32_t* p = NULL;
+ if (p == NULL) {
+ p = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ assert(p != MAP_FAILED);
+ }
+
+ for (i = 0; i < 4096/sizeof(uint32_t); i++)
+ p[i] = 0x7fe00008; /* trap */
+
+ return p;
+}
+
/* -------------- BEGIN #include "test-ppc.h" -------------- */
/*
}
+/* Copy the 2 insn function starting at p_func_F to func_buf[], and
+ return a possibly different pointer, which, when called, runs the
+ copy in func_buf[]. */
static inline
-void init_function( test_func_t *p_func, uint32_t func_buf[] )
+test_func_t init_function( test_func_t p_func_F, uint32_t func_buf[] )
{
- uint32_t *p;
+ uint32_t* p_func = (uint32_t*)p_func_F;
#ifndef __powerpc64__
- p = (uint32_t *)*p_func;
- func_buf[0] = p[0];
- func_buf[1] = p[1];
- *p_func = (void *)func_buf;
+ func_buf[0] = p_func[0];
+ func_buf[1] = p_func[1];
+ return (test_func_t)&func_buf[0];
#else
- p = (uint32_t *)((uint64_t *)*p_func)[0];
- func_buf[0] = p[0];
- func_buf[1] = p[1];
- ((uint64_t *)*p_func)[0] = (uint64_t)&func_buf[0];
+ /* p_func points to a function descriptor, the first word of which
+ points to the real code. Copy the code itself but not the
+ descriptor, and just swizzle the descriptor's entry pointer. */
+ uint64_t* descr = (uint64_t*)p_func;
+ uint32_t* entry = (uint32_t*)(descr[0]);
+ func_buf[0] = entry[0];
+ func_buf[1] = entry[1];
+ descr[0] = (uint64_t)&func_buf[0];
+ return (test_func_t)descr;
#endif // #ifndef __powerpc64__
}
static void test_int_one_reg_imm16 (const char* name,
- test_func_t func,
+ test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j;
for (i=0; i<nb_iargs; i++) {
for (j=0; j<nb_ii16; j++) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm16(&func_buf[0], ii16[j]);
r14 = iargs[i];
* sradi rA,rS,SH
*/
-static void rlwi_cb (const char* name, test_func_t func,
+static void rlwi_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, l, arg_step;
for (k=0; k<32; k+=arg_step) {
for (l=0; l<32; l+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
_patch_op_imm(&func_buf[0], j, 11, 5);
_patch_op_imm(&func_buf[0], k, 6, 5);
patch_op_imm(&func_buf[0], l, 1, 5);
}
}
-static void rlwnm_cb (const char* name, test_func_t func,
+static void rlwnm_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, l, arg_step;
for (k=0; k<32; k+=arg_step) {
for (l=0; l<32; l+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
_patch_op_imm(&func_buf[0], k, 6, 5);
patch_op_imm(&func_buf[0], l, 1, 5);
}
}
-static void srawi_cb (const char* name, test_func_t func,
+static void srawi_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, arg_step;
for (i=0; i<nb_iargs; i++) {
for (j=0; j<32; j+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], j, 11, 5);
r14 = iargs[i];
}
}
-static void mcrf_cb (const char* name, test_func_t func,
+static void mcrf_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, arg_step;
for (j=0; j<8; j+=arg_step) {
for (k=0; k<8; k+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
_patch_op_imm(&func_buf[0], j, 23, 3);
patch_op_imm(&func_buf[0], k, 18, 3);
#endif
-static void mcrxr_cb (const char* name, test_func_t func,
+static void mcrxr_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, arg_step;
j = i << 28;
for (k=0; k<8; k+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], k, 23, 3);
r14 = j;
}
#endif
-static void mtcrf_cb (const char* name, test_func_t func,
+static void mtcrf_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, arg_step;
for (i=0; i<nb_iargs; i++) {
for (j=0; j<256; j+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], j, 12, 8);
r14 = iargs[i];
}
#ifdef __powerpc64__
-static void rldc_cb (const char* name, test_func_t func,
+static void rldc_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, arg_step;
for (j=0; j<nb_iargs; j++) {
for (k=0; k<64; k+=arg_step) {
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], (((k & 0x1F)<<1) | ((k>>5)&1)), 5, 6);
r14 = iargs[i];
}
}
-static void rldi_cb (const char* name, test_func_t func,
+static void rldi_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, k, arg_step;
for (j=0; j<64; j+=arg_step) { // SH
for (k=0; k<64; k+=arg_step) { // MB|ME
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
_patch_op_imm(&func_buf[0], (j & 0x1F), 11, 5);
_patch_op_imm(&func_buf[0], ((j>>5)&1), 1, 1);
patch_op_imm(&func_buf[0], (((k & 0x1F)<<1) | ((k>>5)&1)), 5, 6);
}
}
-static void sradi_cb (const char* name, test_func_t func,
+static void sradi_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, j, arg_step;
for (i=0; i<nb_iargs; i++) {
for (j=0; j<64; j+=arg_step) { // SH
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
_patch_op_imm(&func_buf[0], (j & 0x1F), 11, 5);
patch_op_imm(&func_buf[0], ((j>>5)&1), 1, 1);
static void test_int_ld_one_reg_imm16 (const char* name,
- test_func_t func,
+ test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile HWord_t res, base;
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, offs, is_lwa=0;
offs = i * sizeof(HWord_t);
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
if (is_lwa)
patch_op_imm(&func_buf[0], offs>>2, 2, 14);
else
offs = i * sizeof(HWord_t);
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func, func_buf );
patch_op_imm16(&func_buf[0], offs);
r14 = base;
}
static void test_int_st_two_regs_imm16 (const char* name,
- test_func_t func,
+ test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, xer, tmpcr, tmpxer;
int i, offs, k;
HWord_t *iargs_priv, base;
offs = i * sizeof(HWord_t);
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm16(&func_buf[0], offs);
r14 = iargs[i]; // read from iargs
offs = i * sizeof(HWord_t);
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func, func_buf );
patch_op_imm16(&func_buf[0], offs);
r14 = iargs[nb_iargs-1+i]; // read from iargs
static void test_float_ld_one_reg_imm16 (const char* name,
- test_func_t func,
+ test_func_t func_IN,
unused uint32_t test_flags)
{
- uint32_t base, func_buf[2];
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
+ uint32_t base;
volatile uint32_t flags, xer, tmpcr, tmpxer;
volatile double src, res;
int i, offs;
}
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm16(&func_buf[0], offs);
// load from fargs[idx] => r14 + offs
}
static void test_float_st_two_regs_imm16 (const char* name,
- test_func_t func,
+ test_func_t func_IN,
unused uint32_t test_flags)
{
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
HWord_t base;
- uint32_t func_buf[2];
volatile uint32_t flags, xer, tmpcr, tmpxer;
double src, *p_dst;
int i, offs;
*p_dst = 0; // clear dst
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm16(&func_buf[0], offs);
// read from fargs[idx] => f14
}
}
-static void vsplt_cb (const char* name, test_func_t func,
+static void vsplt_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, tmpcr;
volatile vector unsigned int tmpvscr;
volatile vector unsigned int vec_in1, vec_out, vscr;
- uint32_t func_buf[2];
unsigned int *src1, *dst;
int i,j;
#if defined TEST_VSCR_SAT
vec_out = (vector unsigned int){ 0,0,0,0 };
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], j, 16, 5);
/* Save flags */
}
}
-static void vspltis_cb (const char* name, test_func_t func,
+static void vspltis_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, tmpcr;
volatile vector unsigned int tmpvscr;
volatile vector unsigned int vec_out, vscr;
- uint32_t func_buf[2];
unsigned int *dst;
int i;
#if defined TEST_VSCR_SAT
vec_out = (vector unsigned int){ 0,0,0,0 };
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], i, 16, 5);
/* Save flags */
}
}
-static void vsldoi_cb (const char* name, test_func_t func,
+static void vsldoi_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, tmpcr;
volatile vector unsigned int tmpvscr;
volatile vector unsigned int vec_in1, vec_in2, vec_out, vscr;
- uint32_t func_buf[2];
unsigned int *src1, *src2, *dst;
int i,j,k;
#if defined TEST_VSCR_SAT
vec_out = (vector unsigned int){ 0,0,0,0 };
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], k, 6, 4);
/* Save flags */
}
}
-static void vcvt_cb (const char* name, test_func_t func,
+static void vcvt_cb (const char* name, test_func_t func_IN,
unused uint32_t test_flags)
{
+ volatile test_func_t func;
+ uint32_t* func_buf = get_rwx_area();
volatile uint32_t flags, tmpcr;
volatile vector unsigned int tmpvscr;
volatile vector unsigned int vec_in, vec_out, vscr;
- uint32_t func_buf[2];
unsigned int *src, *dst;
int i,j;
#if defined TEST_VSCR_SAT
vec_out = (vector unsigned int){ 0,0,0,0 };
/* Patch up the instruction */
- init_function( &func, func_buf );
+ func = init_function( func_IN, func_buf );
patch_op_imm(&func_buf[0], j, 16, 5);
/* Save flags */