196492Sjake/*-
296492Sjake * Copyright (c) 2002 Jake Burkholder.
396492Sjake * All rights reserved.
496492Sjake *
596492Sjake * Redistribution and use in source and binary forms, with or without
696492Sjake * modification, are permitted provided that the following conditions
796492Sjake * are met:
896492Sjake * 1. Redistributions of source code must retain the above copyright
996492Sjake *    notice, this list of conditions and the following disclaimer.
1096492Sjake * 2. Redistributions in binary form must reproduce the above copyright
1196492Sjake *    notice, this list of conditions and the following disclaimer in the
1296492Sjake *    documentation and/or other materials provided with the distribution.
1396492Sjake *
1496492Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1596492Sjake * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1696492Sjake * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1796492Sjake * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
1896492Sjake * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1996492Sjake * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2096492Sjake * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2196492Sjake * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2296492Sjake * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2396492Sjake * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2496492Sjake */
2596492Sjake
2696492Sjake#include <sys/cdefs.h>
2796492Sjake__FBSDID("$FreeBSD$");
2896492Sjake
2996492Sjake#include <sys/types.h>
3096492Sjake#include <machine/cpufunc.h>
3196492Sjake#include <machine/instr.h>
3296492Sjake
3396492Sjake#include <signal.h>
3496492Sjake
3596492Sjake#include "__sparc_utrap_private.h"
3696492Sjake
3796492Sjakestatic u_long
3896492Sjake__unaligned_load(u_char *p, int size)
3996492Sjake{
4096492Sjake	u_long val;
4196492Sjake	int i;
4296492Sjake
4396492Sjake	val = 0;
4496492Sjake	for (i = 0; i < size; i++)
4596492Sjake		val = (val << 8) | p[i];
4696492Sjake	return (val);
4796492Sjake}
4896492Sjake
4996492Sjakestatic void
5096492Sjake__unaligned_store(u_char *p, u_long val, int size)
5196492Sjake{
5296492Sjake	int i;
5396492Sjake
5496492Sjake	for (i = 0; i < size; i++)
5596548Sjake		p[i] = val >> ((size - i - 1) * 8);
5696492Sjake}
5796492Sjake
5896492Sjakeint
5996492Sjake__unaligned_fixup(struct utrapframe *uf)
6096492Sjake{
6196492Sjake	u_char *addr;
6296492Sjake	u_long val;
6396492Sjake	u_int insn;
6496492Sjake	int sig;
6596492Sjake
6696492Sjake	sig = 0;
6796492Sjake	addr = (u_char *)uf->uf_sfar;
6896492Sjake	insn = *(u_int *)uf->uf_pc;
6996492Sjake	flushw();
7096492Sjake	switch (IF_OP(insn)) {
7196492Sjake	case IOP_LDST:
7296492Sjake		switch (IF_F3_OP3(insn)) {
7396492Sjake		case INS3_LDUH:
7496492Sjake			val = __unaligned_load(addr, 2);
7596492Sjake			__emul_store_reg(uf, IF_F3_RD(insn), val);
7696492Sjake			break;
7796492Sjake		case INS3_LDUW:
7896492Sjake			val = __unaligned_load(addr, 4);
7996492Sjake			__emul_store_reg(uf, IF_F3_RD(insn), val);
8096492Sjake			break;
8196492Sjake		case INS3_LDX:
8296492Sjake			val = __unaligned_load(addr, 8);
8396492Sjake			__emul_store_reg(uf, IF_F3_RD(insn), val);
8496492Sjake			break;
8596492Sjake		case INS3_LDSH:
8696492Sjake			val = __unaligned_load(addr, 2);
8796492Sjake			__emul_store_reg(uf, IF_F3_RD(insn),
8896492Sjake			    IF_SEXT(val, 16));
8996492Sjake			break;
9096492Sjake		case INS3_LDSW:
9196492Sjake			val = __unaligned_load(addr, 4);
9296492Sjake			__emul_store_reg(uf, IF_F3_RD(insn),
9396492Sjake			    IF_SEXT(val, 32));
9496492Sjake			break;
9596492Sjake		case INS3_STH:
9696492Sjake			val = __emul_fetch_reg(uf, IF_F3_RD(insn));
9796492Sjake			__unaligned_store(addr, val, 2);
9896492Sjake			break;
9996492Sjake		case INS3_STW:
10096492Sjake			val = __emul_fetch_reg(uf, IF_F3_RD(insn));
10196492Sjake			__unaligned_store(addr, val, 4);
10296492Sjake			break;
10396492Sjake		case INS3_STX:
10496492Sjake			val = __emul_fetch_reg(uf, IF_F3_RD(insn));
10596492Sjake			__unaligned_store(addr, val, 8);
10696492Sjake			break;
10796492Sjake		default:
10896492Sjake			sig = SIGILL;
10996492Sjake			break;
11096492Sjake		}
11196492Sjake		break;
11296492Sjake	default:
11396492Sjake		sig = SIGILL;
11496492Sjake		break;
11596492Sjake	}
11696492Sjake	return (sig);
11796492Sjake}
118