1/* $OpenBSD: simm13.c,v 1.6 2014/04/18 14:38:21 guenther Exp $ */ 2 3/* 4 * Copyright (c) 2003 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * check that "popc immediate, %rd" gets the correct value. It is 31 * emulated on most SPARC v9 implementations. 32 */ 33 34#include <sys/types.h> 35#include <sys/mman.h> 36#include <machine/instr.h> 37#include <err.h> 38#include <stdio.h> 39 40#define SIGN_EXT13(v) (((int64_t)(v) << 51) >> 51) 41 42void gen_simm(u_int32_t *, int); 43int64_t a_popc_imm(void *, int); 44int64_t c_popc(int64_t); 45int main(void); 46 47void 48gen_simm(u_int32_t *p, int imm) 49{ 50 /* 51 * generate the following asm, and flush the pipeline 52 * retl 53 * popc imm, %o0 54 */ 55 p[0] = I_JMPLri(I_G0, I_O7, 8); 56 __asm volatile("iflush %0+0" : : "r" (p + 0)); 57 p[1] = _I_OP3_R_RI(I_O0, IOP3_POPC, I_G0, imm); 58 __asm volatile("iflush %0+0" : : "r" (p + 1)); 59 __asm volatile("nop;nop;nop;nop;nop"); 60} 61 62int64_t 63a_popc_imm(void *v, int i) 64{ 65 int64_t (*func)(void) = v, r; 66 67 if (mprotect(v, 2 * sizeof(union instr), PROT_READ|PROT_WRITE) == -1) 68 err(1, "mprotect"); 69 gen_simm(v, i); 70 71 if (mprotect(v, 2 * sizeof(union instr), PROT_READ|PROT_EXEC) == -1) 72 err(1, "mprotect"); 73 r = (*func)(); 74 75 if (mprotect(v, 2 * sizeof(union instr), PROT_NONE) == -1) 76 err(1, "mprotect"); 77 78 return (r); 79} 80 81int64_t 82c_popc(int64_t v) 83{ 84 int64_t bit, r; 85 86 for (bit = 1, r = 0; bit; bit <<= 1) 87 if (v & bit) 88 r++; 89 return (r); 90} 91 92int 93main() 94{ 95 void *v; 96 int i, a, c; 97 int r = 0; 98 99 v = mmap(NULL, 2 * sizeof(union instr), PROT_NONE, MAP_ANON, -1, 0); 100 if (v == MAP_FAILED) 101 err(1, "mmap"); 102 103 for (i = -4096; i <= 4095; i++) { 104 a = a_popc_imm(v, i); 105 c = c_popc(SIGN_EXT13(i)); 106 if (c != a) { 107 printf("BAD: %d: asm %d, c %d\n", i, a, c); 108 r = 1; 109 } 110 } 111 112 return (r); 113} 114