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