1160040Smarcel/*- 2160040Smarcel * Copyright (c) 2006 Marcel Moolenaar 3160040Smarcel * All rights reserved. 4160040Smarcel * 5160040Smarcel * Redistribution and use in source and binary forms, with or without 6160040Smarcel * modification, are permitted provided that the following conditions 7160040Smarcel * are met: 8160040Smarcel * 9160040Smarcel * 1. Redistributions of source code must retain the above copyright 10160040Smarcel * notice, this list of conditions and the following disclaimer. 11160040Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12160040Smarcel * notice, this list of conditions and the following disclaimer in the 13160040Smarcel * documentation and/or other materials provided with the distribution. 14160040Smarcel * 15160040Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16160040Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17160040Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18160040Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19160040Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20160040Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21160040Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22160040Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23160040Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24160040Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25160040Smarcel */ 26160040Smarcel 27160040Smarcel#include <sys/cdefs.h> 28160040Smarcel__FBSDID("$FreeBSD$"); 29160040Smarcel 30160040Smarcel#include <sys/param.h> 31160040Smarcel#include <sys/systm.h> 32160040Smarcel#include <sys/proc.h> 33160040Smarcel 34160040Smarcel#include <machine/frame.h> 35160040Smarcel#include <machine/md_var.h> 36160040Smarcel 37160040Smarcel#include <ia64/disasm/disasm.h> 38160040Smarcel 39160040Smarcelint 40160040Smarcelia64_emulate(struct trapframe *tf, struct thread *td) 41160040Smarcel{ 42160040Smarcel struct asm_bundle bundle; 43160040Smarcel struct asm_inst *i; 44160040Smarcel int slot; 45160040Smarcel 46160040Smarcel if (!asm_decode(tf->tf_special.iip, &bundle)) 47160040Smarcel return (SIGILL); 48160040Smarcel 49160040Smarcel slot = ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_0) ? 0 : 50160040Smarcel ((tf->tf_special.psr & IA64_PSR_RI) == IA64_PSR_RI_1) ? 1 : 2; 51160040Smarcel if (slot == 1 && bundle.b_templ[slot] == 'L') 52160040Smarcel slot++; 53160040Smarcel 54160040Smarcel i = bundle.b_inst + slot; 55160040Smarcel switch (i->i_op) { 56160040Smarcel case ASM_OP_BRL: 57160040Smarcel /* 58160040Smarcel * We get the fault even if the predicate is false, so we 59160040Smarcel * need to check the predicate first and simply advance to 60160040Smarcel * the next bundle in that case. 61160040Smarcel */ 62160040Smarcel if (!(tf->tf_special.pr & (1UL << i->i_oper[0].o_value))) { 63160040Smarcel tf->tf_special.psr &= ~IA64_PSR_RI; 64160040Smarcel tf->tf_special.iip += 16; 65160040Smarcel return (0); 66160040Smarcel } 67160040Smarcel /* 68160040Smarcel * The brl.cond is the simplest form. We only have to set 69160040Smarcel * the IP to the address in the instruction and return. 70160040Smarcel */ 71160040Smarcel if (i->i_cmpltr[0].c_type == ASM_CT_COND) { 72160040Smarcel tf->tf_special.psr &= ~IA64_PSR_RI; 73160040Smarcel tf->tf_special.iip += i->i_oper[1].o_value; 74160040Smarcel return (0); 75160040Smarcel } 76160040Smarcel /* Sanity check... */ 77160040Smarcel if (i->i_cmpltr[0].c_type != ASM_CT_CALL) 78160040Smarcel break; 79160040Smarcel /* 80160040Smarcel * The brl.call is more difficult as we need to set-up the 81160040Smarcel * call properly. 82160040Smarcel */ 83160040Smarcel break; 84160040Smarcel default: 85160040Smarcel break; 86160040Smarcel } 87160040Smarcel 88160040Smarcel return (SIGILL); 89160040Smarcel} 90