195587Sjake/*- 295587Sjake * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>. 395587Sjake * All rights reserved. 495587Sjake * 595587Sjake * Redistribution and use in source and binary forms, with or without 695587Sjake * modification, are permitted provided that the following conditions 795587Sjake * are met: 895587Sjake * 1. Redistributions of source code must retain the above copyright 995587Sjake * notice, this list of conditions and the following disclaimer. 1095587Sjake * 2. Redistributions in binary form must reproduce the above copyright 1195587Sjake * notice, this list of conditions and the following disclaimer in the 1295587Sjake * documentation and/or other materials provided with the distribution. 1395587Sjake * 1495587Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1595587Sjake * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1695587Sjake * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1795587Sjake * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 1895587Sjake * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1995587Sjake * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2095587Sjake * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 2195587Sjake * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2295587Sjake * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2395587Sjake * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2495587Sjake */ 2595587Sjake 2695587Sjake#include <sys/cdefs.h> 2795587Sjake__FBSDID("$FreeBSD$"); 2895587Sjake 2995587Sjake#include <sys/types.h> 3095587Sjake#include <machine/cpufunc.h> 3195587Sjake#include <machine/frame.h> 3295587Sjake#include <machine/instr.h> 3395587Sjake 3495587Sjake#include <signal.h> 3595587Sjake 3695587Sjake#include "__sparc_utrap_private.h" 3795587Sjake#include "fpu_reg.h" 3895587Sjake 3995587Sjakeint 4095587Sjake__emul_insn(struct utrapframe *uf) 4195587Sjake{ 4295587Sjake u_long reg, res; 4395587Sjake u_long *addr; 4495587Sjake u_int insn; 4595587Sjake int sig; 4695587Sjake int rd; 4795587Sjake int i; 4895587Sjake 4995587Sjake sig = 0; 5095587Sjake insn = *(u_int *)uf->uf_pc; 5195587Sjake flushw(); 5295587Sjake switch (IF_OP(insn)) { 5395587Sjake case IOP_MISC: 5495587Sjake switch (IF_F3_OP3(insn)) { 5595587Sjake case INS2_POPC: 5695587Sjake if (IF_F3_RS1(insn) != 0) { 5795587Sjake sig = SIGILL; 5895587Sjake break; 5995587Sjake } 6095587Sjake reg = __emul_f3_op2(uf, insn); 6195587Sjake for (i = 0; i < 64; i++) 6295587Sjake res += (reg >> i) & 1; 6395587Sjake __emul_store_reg(uf, IF_F3_RD(insn), res); 6495587Sjake break; 6595587Sjake default: 6695587Sjake sig = SIGILL; 6795587Sjake break; 6895587Sjake } 6995587Sjake break; 7095587Sjake case IOP_LDST: 7195587Sjake switch (IF_F3_OP3(insn)) { 7295587Sjake case INS3_LDQF: 7396422Sjake rd = INSFPdq_RN(IF_F3_RD(insn)); 7495587Sjake addr = (u_long *)__emul_f3_memop_addr(uf, insn); 7595587Sjake __fpu_setreg64(rd, addr[0]); 7695587Sjake __fpu_setreg64(rd + 2, addr[1]); 7795587Sjake break; 7895587Sjake case INS3_STQF: 7996422Sjake rd = INSFPdq_RN(IF_F3_RD(insn)); 8095587Sjake addr = (u_long *)__emul_f3_memop_addr(uf, insn); 8195587Sjake addr[0] = __fpu_getreg64(rd); 8295587Sjake addr[1] = __fpu_getreg64(rd + 2); 8395587Sjake break; 8495587Sjake default: 8595587Sjake sig = SIGILL; 8695587Sjake break; 8795587Sjake } 8895587Sjake break; 8995587Sjake default: 9095587Sjake sig = SIGILL; 9195587Sjake break; 9295587Sjake } 9395587Sjake return (sig); 9495587Sjake} 9595587Sjake 9695587Sjakeu_long 9795587Sjake__emul_fetch_reg(struct utrapframe *uf, int reg) 9895587Sjake{ 9995587Sjake struct frame *frm; 10095587Sjake 10195587Sjake if (reg == IREG_G0) 10295587Sjake return (0); 10395587Sjake else if (reg < IREG_O0) /* global */ 10495587Sjake return (uf->uf_global[reg]); 10595587Sjake else if (reg < IREG_L0) /* out */ 10695587Sjake return (uf->uf_out[reg - IREG_O0]); 10795587Sjake else { /* local, in */ 10895587Sjake /* 10995587Sjake * The in registers are immediately after the locals in 11095587Sjake * the frame. 11195587Sjake */ 11295587Sjake frm = (struct frame *)(uf->uf_out[6] + SPOFF); 11395587Sjake return (frm->fr_local[reg - IREG_L0]); 11495587Sjake } 11595587Sjake} 11695587Sjake 11795587Sjakevoid 11895587Sjake__emul_store_reg(struct utrapframe *uf, int reg, u_long val) 11995587Sjake{ 12095587Sjake struct frame *frm; 12195587Sjake 12295587Sjake if (reg == IREG_G0) 12395587Sjake return; 12495587Sjake if (reg < IREG_O0) /* global */ 12595587Sjake uf->uf_global[reg] = val; 12695587Sjake else if (reg < IREG_L0) /* out */ 12795587Sjake uf->uf_out[reg - IREG_O0] = val; 12895587Sjake else { 12995587Sjake /* 13095587Sjake * The in registers are immediately after the locals in 13195587Sjake * the frame. 13295587Sjake */ 13395587Sjake frm = (struct frame *)(uf->uf_out[6] + SPOFF); 13495587Sjake frm->fr_local[reg - IREG_L0] = val; 13595587Sjake } 13695587Sjake} 13795587Sjake 13895587Sjakeu_long 13995587Sjake__emul_f3_op2(struct utrapframe *uf, u_int insn) 14095587Sjake{ 14195587Sjake 14295587Sjake if (IF_F3_I(insn) != 0) 14395587Sjake return (IF_SIMM(insn, 13)); 14495587Sjake else 14595587Sjake return (__emul_fetch_reg(uf, IF_F3_RS2(insn))); 14695587Sjake} 14795587Sjake 14895587Sjakeu_long 14995587Sjake__emul_f3_memop_addr(struct utrapframe *uf, u_int insn) 15095587Sjake{ 15195587Sjake u_long addr; 15295587Sjake 15395587Sjake addr = __emul_f3_op2(uf, insn) + __emul_fetch_reg(uf, IF_F3_RS1(insn)); 15495587Sjake return (addr); 15595587Sjake} 156