1/* 2 * Copyright (c) 2006 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: releng/10.3/tools/regression/ia64/emulated/test.c 160416 2006-07-17 00:27:12Z marcel $ 27 */ 28 29#include <sys/mman.h> 30#include <stdio.h> 31#include <string.h> 32 33/* Supported long branch types */ 34#define Call 1 35#define Cond 2 36 37/* Supported predicates */ 38#define False 1 39#define True 2 40 41/* Supported variations */ 42#define Backward 1 43#define Forward 2 44 45#if TYPE == 0 || PRED == 0 || VAR == 0 46#error Define TYPE, PRED and/or VAR 47#endif 48 49union bundle { 50 unsigned char bytes[16]; 51 long double _align; 52}; 53 54/* 55 * Machine code of a bundle containing a long branch. The predicate of the 56 * long branch is the result of the compare in the first slot. 57 * The assembly of the bundle is: 58 * { .mlx 59 * cmp.eq p0,p15= <PREDICATE>,r0 60 * (p15) brl.few <TARGET> ;; 61 * } 62 * the predicate is written to bit 18:1 63 * The branch target is written to bits 100:20, 48:39 and 123:1 64 */ 65unsigned char mc_brl_cond[16] = { 66 0x05, 0x00, 0x00, 0x00, 0x0f, 0x39, 67 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 68 0x00, 0x00, 0x00, 0xc0 69}; 70 71/* 72 * Machine code of the epilogue of a typical function returning an integer. 73 * The assembly of the epilogue is: 74 * { .mib 75 * nop.m 0 76 * addl r8 = <RETVAL>, r0 77 * br.ret.sptk.few b0 ;; 78 * } 79 * The return value is written to bits 59:7, 73:9, 68:5, and 82:1. 80 */ 81unsigned char mc_epilogue[16] = { 82 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 83 0x80, 0x00, 0x00, 0x00, 0x48, 0x80, 84 0x00, 0x00, 0x84, 0x00 85}; 86 87void 88mc_patch(union bundle *b, unsigned long val, int start, int len) 89{ 90 unsigned long mask; 91 int bit, byte, run; 92 93 byte = start >> 3; 94 bit = start & 7; 95 while (len) { 96 run = ((len > (8 - bit)) ? (8 - bit) : len); 97 mask = (1UL << run) - 1UL; 98 b->bytes[byte] |= (val & mask) << bit; 99 val >>= run; 100 len -= run; 101 byte++; 102 bit = 0; 103 } 104} 105 106void 107assemble_brl_cond(union bundle *b, int pred, unsigned long tgt) 108{ 109 unsigned long iprel; 110 111 iprel = tgt - (unsigned long)b; 112 memcpy(b->bytes, mc_brl_cond, sizeof(mc_brl_cond)); 113 mc_patch(b, pred ? 1 : 0, 18, 1); 114 mc_patch(b, iprel >> 4, 100, 20); 115 mc_patch(b, iprel >> 24, 48, 39); 116 mc_patch(b, iprel >> 63, 123, 1); 117} 118 119void 120assemble_epilogue(union bundle *b, int retval) 121{ 122 memcpy(b->bytes, mc_epilogue, sizeof(mc_epilogue)); 123 mc_patch(b, retval, 59, 7); 124 mc_patch(b, retval >> 7, 73, 9); 125 mc_patch(b, retval >> 16, 68, 5); 126 mc_patch(b, retval >> 21, 82, 1); 127} 128 129int 130doit(void *addr) 131{ 132 asm("mov b6 = %0; br.sptk b6;;" :: "r"(addr)); 133 return 1; 134} 135 136int 137test_cond(int pred, union bundle *src, union bundle *dst) 138{ 139 assemble_epilogue(dst, pred ? 0 : 2); 140 assemble_brl_cond(src, pred ? 1 : 0, (unsigned long)dst); 141 assemble_epilogue(src + 1, !pred ? 0 : 2); 142 return doit(src); 143} 144 145int 146main() 147{ 148 static union bundle blob_low[2]; 149 union bundle *blob_high; 150 void *addr; 151 152 addr = (void *)0x7FFFFFFF00000000L; 153 blob_high = mmap(addr, 32, PROT_EXEC | PROT_READ | PROT_WRITE, 154 MAP_ANON, -1, 0L); 155 if (blob_high != addr) 156 printf("NOTICE: blob_high is at %p, not at %p\n", blob_high, 157 addr); 158 159#if TYPE == Call 160 return (test_call(blob_high, blob_low)); 161#elif TYPE == Cond 162 #if VAR == Forward 163 return (test_cond(PRED - 1, blob_low, blob_high)); 164 #elif VAR == Backward 165 return (test_cond(PRED - 1, blob_high, blob_low)); 166 #else 167 return (1); 168 #endif 169#else 170 return (1); 171#endif 172} 173