diff options
author | tmm <tmm@FreeBSD.org> | 2001-11-06 20:13:44 +0000 |
---|---|---|
committer | tmm <tmm@FreeBSD.org> | 2001-11-06 20:13:44 +0000 |
commit | 594c8e829ba40deb4c6ba3f1cac483af55625718 (patch) | |
tree | 7cf05885f0a2ec73b1bb39d8ef6a5fe58c444e0b /sys | |
parent | bd13886bd85b6d5cac62ae81da44b43eeae279de (diff) | |
download | FreeBSD-src-594c8e829ba40deb4c6ba3f1cac483af55625718.zip FreeBSD-src-594c8e829ba40deb4c6ba3f1cac483af55625718.tar.gz |
Add code to emulate unimplemented (non-fp) instructions and to fixup
unaligned accesses, and instr.h, which contrains definitions for the
sparc64 instruction set (partly from NetBSD).
Make use of some definitions from instr.h in db_disasm.c.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/sparc64/include/frame.h | 5 | ||||
-rw-r--r-- | sys/sparc64/include/instr.h | 620 | ||||
-rw-r--r-- | sys/sparc64/sparc64/db_disasm.c | 402 | ||||
-rw-r--r-- | sys/sparc64/sparc64/emul.c | 298 | ||||
-rw-r--r-- | sys/sparc64/sparc64/trap.c | 16 |
5 files changed, 1095 insertions, 246 deletions
diff --git a/sys/sparc64/include/frame.h b/sys/sparc64/include/frame.h index 5151ef2..d297d4e 100644 --- a/sys/sparc64/include/frame.h +++ b/sys/sparc64/include/frame.h @@ -43,6 +43,11 @@ struct trapframe { uintptr_t tf_arg; }; #define tf_sp tf_out[6] + +#define TF_DONE(tf) do { \ + tf->tf_tpc = tf->tf_tnpc; \ + tf->tf_tnpc += 4; \ +} while (0) struct mmuframe { u_long mf_sfar; diff --git a/sys/sparc64/include/instr.h b/sys/sparc64/include/instr.h new file mode 100644 index 0000000..b6a8ec1 --- /dev/null +++ b/sys/sparc64/include/instr.h @@ -0,0 +1,620 @@ +/* + * Copyright (c) 1994 David S. Miller, davem@nadzieja.rutgers.edu + * Copyright (c) 1995 Paul Kranenburg + * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by David Miller. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: NetBSD: db_disasm.c,v 1.9 2000/08/16 11:29:42 pk Exp + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_INSTR_H_ +#define _MACHINE_INSTR_H_ + +/* + * Definitions for all instruction formats + */ +#define IF_OP_SHIFT 30 +#define IF_OP_BITS 2 +#define IF_IMM_SHIFT 0 /* Immediate/Displacement */ + +/* + * Definitions for format 2 + */ +#define IF_F2_RD_SHIFT 25 +#define IF_F2_RD_BITS 5 +#define IF_F2_A_SHIFT 29 +#define IF_F2_A_BITS 1 +#define IF_F2_COND_SHIFT 25 +#define IF_F2_COND_BITS 4 +#define IF_F2_RCOND_SHIFT 25 +#define IF_F2_RCOND_BITS 3 +#define IF_F2_OP2_SHIFT 22 +#define IF_F2_OP2_BITS 3 +#define IF_F2_CC1_SHIFT 21 +#define IF_F2_CC1_BITS 1 +#define IF_F2_CC0_SHIFT 20 +#define IF_F2_CC0_BITS 1 +#define IF_F2_D16HI_SHIFT 20 +#define IF_F2_D16HI_BITS 2 +#define IF_F2_P_SHIFT 19 +#define IF_F2_P_BITS 1 +#define IF_F2_RS1_SHIFT 14 +#define IF_F2_RS1_BITS 5 + +/* + * Definitions for format 3 + */ +#define IF_F3_OP3_SHIFT 19 +#define IF_F3_OP3_BITS 6 +#define IF_F3_RD_SHIFT IF_F2_RD_SHIFT +#define IF_F3_RD_BITS IF_F2_RD_BITS +#define IF_F3_FCN_SHIFT 25 +#define IF_F3_FCN_BITS 5 +#define IF_F3_CC1_SHIFT 26 +#define IF_F3_CC1_BITS 1 +#define IF_F3_CC0_SHIFT 25 +#define IF_F3_CC0_BITS 1 +#define IF_F3_RS1_SHIFT IF_F2_RS1_SHIFT +#define IF_F3_RS1_BITS IF_F2_RS1_BITS +#define IF_F3_I_SHIFT 13 +#define IF_F3_I_BITS 1 +#define IF_F3_X_SHIFT 12 +#define IF_F3_X_BITS 1 +#define IF_F3_RCOND_SHIFT 10 +#define IF_F3_RCOND_BITS 3 +#define IF_F3_IMM_ASI_SHIFT 5 +#define IF_F3_IMM_ASI_BITS 8 +#define IF_F3_OPF_SHIFT 5 +#define IF_F3_OPF_BITS 9 +#define IF_F3_CMASK_SHIFT 4 +#define IF_F3_CMASK_BITS 3 +#define IF_F3_RS2_SHIFT 0 +#define IF_F3_RS2_BITS 5 +#define IF_F3_SHCNT32_SHIFT 0 +#define IF_F3_SHCNT32_BITS 5 +#define IF_F3_SHCNT64_SHIFT 0 +#define IF_F3_SHCNT64_BITS 6 + +/* + * Definitions for format 4 + */ +#define IF_F4_OP3_SHIFT IF_F3_OP3_SHIFT +#define IF_F4_OP3_BITS IF_F3_OP3_BITS +#define IF_F4_RD_SHIFT IF_F2_RD_SHIFT +#define IF_F4_RD_BITS IF_F2_RD_BITS +#define IF_F4_RS1_SHIFT IF_F2_RS1_SHIFT +#define IF_F4_RS1_BITS IF_F2_RS1_BITS +#define IF_F4_TCOND_SHIFT IF_F2_COND_SHIFT /* cond for Tcc */ +#define IF_F4_TCOND_BITS IF_F2_COND_BITS +#define IF_F4_CC2_SHIFT 18 +#define IF_F4_CC2_BITS 1 +#define IF_F4_COND_SHIFT 14 +#define IF_F4_COND_BITS 4 +#define IF_F4_I_SHIFT IF_F3_I_SHIFT +#define IF_F4_I_BITS IF_F3_I_BITS +#define IF_F4_OPF_CC_SHIFT 11 +#define IF_F4_OPF_CC_BITS 3 +#define IF_F4_CC1_SHIFT 12 +#define IF_F4_CC1_BITS 1 +#define IF_F4_CC0_SHIFT 11 +#define IF_F4_CC0_BITS 1 +#define IF_F4_RCOND_SHIFT IF_F3_RCOND_SHIFT +#define IF_F4_RCOND_BITS IF_F3_RCOND_BITS +#define IF_F4_OPF_LOW_SHIFT 5 +#define IF_F4_RS2_SHIFT IF_F3_RS2_SHIFT +#define IF_F4_RS2_BITS IF_F3_RS2_BITS +#define IF_F4_SW_TRAP_SHIFT 0 +#define IF_F4_SW_TRAP_BITS 7 + +/* + * Macros to decode instructions + */ +/* Extract a field */ +#define IF_EXTRACT(x, s, w) (((x) >> (s)) & ((1 << (w)) - 1)) +#define IF_DECODE(x, f) \ + IF_EXTRACT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS) + +/* Sign-extend a field of width W */ +#define IF_SEXT(x, w) \ + (((x) & (1 << ((w) - 1))) != 0 ? (-1L - ((x) ^ ((1 << (w)) - 1))) : (x)) + +#if 0 +/* + * The following C variant is from db_disassemble.c, and surely faster, but it + * relies on behaviour that is undefined by the C standard (>> in conjunction + * with signed negative arguments). + */ +#define IF_SEXT(v, w) ((((long long)(v)) << (64 - w)) >> (64 - w)) +/* Assembler version of the above */ +#define IF_SEXT(v, w) \ + { u_long t; ( __asm __volatile("sllx %1, %2, %0; srax %0, %2, %0" : + "=r" (t) : "r" (v) : "i" (64 - w)); t)} +#endif + +/* All instruction formats */ +#define IF_OP(i) IF_DECODE(i, OP) + +/* Instruction format 2 */ +#define IF_F2_RD(i) IF_DECODE((i), F2_RD) +#define IF_F2_A(i) IF_DECODE((i), F2_A) +#define IF_F2_COND(i) IF_DECODE((i), F2_COND) +#define IF_F2_RCOND(i) IF_DECODE((i), F2_RCOND) +#define IF_F2_OP2(i) IF_DECODE((i), F2_OP2) +#define IF_F2_CC1(i) IF_DECODE((i), F2_CC1) +#define IF_F2_CC0(i) IF_DECODE((i), F2_CC0) +#define IF_F2_D16HI(i) IF_DECODE((i), F2_D16HI) +#define IF_F2_P(i) IF_DECODE((i), F2_P) +#define IF_F2_RS1(i) IF_DECODE((i), F2_RS1) + +/* Instruction format 3 */ +#define IF_F3_OP3(i) IF_DECODE((i), F3_OP3) +#define IF_F3_RD(i) IF_F2_RD((i)) +#define IF_F3_FCN(i) IF_DECODE((i), F3_FCN) +#define IF_F3_CC1(i) IF_DECODE((i), F3_CC1) +#define IF_F3_CC0(i) IF_DECODE((i), F3_CC0) +#define IF_F3_RS1(i) IF_F2_RS1((i)) +#define IF_F3_I(i) IF_DECODE((i), F3_I) +#define IF_F3_X(i) IF_DECODE((i), F3_X) +#define IF_F3_RCOND(i) IF_DECODE((i), F3_RCOND) +#define IF_F3_IMM_ASI(i) IF_DECODE((i), F3_IMM_ASI) +#define IF_F3_OPF(i) IF_DECODE((i), F3_OPF) +#define IF_F3_CMASK(i) IF_DECODE((i), F3_CMASK) +#define IF_F3_RS2(i) IF_DECODE((i), F3_RS2) +#define IF_F3_SHCNT32(i) IF_DECODE((i), F3_SHCNT32) +#define IF_F3_SHCNT64(i) IF_DECODE((i), F3_SHCNT64) + +/* Instruction format 4 */ +#define IF_F4_OP3(i) IF_F3_OP3((i)) +#define IF_F4_RD(i) IF_F3_RD((i)) +#define IF_F4_TCOND(i) IF_DECODE((i), F4_TCOND) +#define IF_F4_RS1(i) IF_F3_RS1((i)) +#define IF_F4_CC2(i) IF_DECODE((i), F4_CC2) +#define IF_F4_COND(i) IF_DECODE((i), F4_COND) +#define IF_F4_I(i) IF_F3_I((i)) +#define IF_F4_OPF_CC(i) IF_DECODE((i), F4_OPF_CC) +#define IF_F4_RCOND(i) IF_F3_RCOND((i)) +#define IF_F4_OPF_LOW(i, w) IF_EXTRACT((i), IF_F4_OPF_LOW_SHIFT, (w)) +#define IF_F4_RS2(i) IF_F3_RS2((i)) +#define IF_F4_SW_TRAP(i) IF_DECODE((i), F4_SW_TRAP) + +/* Extract an immediate from an instruction, with an without sign extension */ +#define IF_IMM(i, w) IF_EXTRACT((i), IF_IMM_SHIFT, (w)) +#define IF_SIMM(i, w) ({ u_long b = (w), x = IF_IMM((i), b); IF_SEXT((x), b); }) + +/* + * Macros to encode instructions + */ +#define IF_INSERT(x, s, w) (((x) & ((1 << (w)) - 1)) << (s)) +#define IF_ENCODE(x, f) \ + IF_INSERT((x), IF_ ## f ## _SHIFT, IF_ ## f ## _BITS) + +/* All instruction formats */ +#define EIF_OP(x) IF_ENCODE((x), OP) + +/* Instruction format 2 */ +#define EIF_F2_RD(x) IF_ENCODE((x), F2_RD) +#define EIF_F2_A(x) IF_ENCODE((x), F2_A) +#define EIF_F2_COND(x) IF_ENCODE((x), F2_COND) +#define EIF_F2_RCOND(x) IF_ENCODE((x), F2_RCOND) +#define EIF_F2_OP2(x) IF_ENCODE((x), F2_OP2) +#define EIF_F2_CC1(x) IF_ENCODE((x), F2_CC1) +#define EIF_F2_CC0(x) IF_ENCODE((x), F2_CC0) +#define EIF_F2_D16HI(x) IF_ENCODE((x), F2_D16HI) +#define EIF_F2_P(x) IF_ENCODE((x), F2_P) +#define EIF_F2_RS1(x) IF_ENCODE((x), F2_RS1) + +/* Instruction format 3 */ +#define EIF_F3_OP3(x) IF_ENCODE((x), F3_OP3) +#define EIF_F3_RD(x) EIF_F2_RD((x)) +#define EIF_F3_FCN(x) IF_ENCODE((x), F3_FCN) +#define EIF_F3_CC1(x) IF_ENCODE((x), F3_CC1) +#define EIF_F3_CC0(x) IF_ENCODE((x), F3_CC0) +#define EIF_F3_RS1(x) EIF_F2_RS1((x)) +#define EIF_F3_I(x) IF_ENCODE((x), F3_I) +#define EIF_F3_X(x) IF_ENCODE((x), F3_X) +#define EIF_F3_RCOND(x) IF_ENCODE((x), F3_RCOND) +#define EIF_F3_IMM_ASI(x) IF_ENCODE((x), F3_IMM_ASI) +#define EIF_F3_OPF(x) IF_ENCODE((x), F3_OPF) +#define EIF_F3_CMASK(x) IF_ENCODE((x), F3_CMASK) +#define EIF_F3_RS2(x) IF_ENCODE((x), F3_RS2) +#define EIF_F3_SHCNT32(x) IF_ENCODE((x), F3_SHCNT32) +#define EIF_F3_SHCNT64(x) IF_ENCODE((x), F3_SHCNT64) + +/* Instruction format 4 */ +#define EIF_F4_OP3(x) EIF_F3_OP3((x)) +#define EIF_F4_RD(x) EIF_F2_RD((x)) +#define EIF_F4_TCOND(x) IF_ENCODE((x), F4_TCOND) +#define EIF_F4_RS1(x) EIF_F2_RS1((x)) +#define EIF_F4_CC2(x) IF_ENCODE((x), F4_CC2) +#define EIF_F4_COND(x) IF_ENCODE((x), F4_COND) +#define EIF_F4_I(x) EIF_F3_I((x)) +#define EIF_F4_OPF_CC(x) IF_ENCODE((x), F4_OPF_CC) +#define EIF_F4_RCOND(x) EIF_F3_RCOND((x)) +#define EIF_F4_OPF_LOW(i, w) IF_INSERT((x), IF_F4_OPF_CC_SHIFT, (w)) +#define EIF_F4_RS2(x) EIF_F3_RS2((x)) +#define EIF_F4_SW_TRAP(x) IF_ENCODE((x), F4_SW_TRAP) + +/* Immediates */ +#define EIF_IMM(x, w) IF_INSERT((x), IF_IMM_SHIFT, (w)) +#define EIF_SIMM(x, w) IF_EIMM((x), (w)) + +/* + * OP field values (specifying the instruction format) + */ +#define IOP_FORM2 0x00 /* Format 2: sethi, branches */ +#define IOP_CALL 0x01 /* Format 1: call */ +#define IOP_MISC 0x02 /* Format 3 or 4: arith & misc */ +#define IOP_LDST 0x03 /* Format 4: loads and stores */ + +/* + * OP2/OP3 values (specifying the actual instruction) + */ +/* OP2 values for format 2 (OP = 0) */ +#define INS0_ILLTRAP 0x00 +#define INS0_BPcc 0x01 +#define INS0_Bicc 0x02 +#define INS0_BPr 0x03 +#define INS0_SETHI 0x04 /* with rd = 0 and imm22 = 0, nop */ +#define INS0_FBPfcc 0x05 +#define INS0_FBfcc 0x06 +/* undefined 0x07 */ + +/* OP3 values for Format 3 and 4 (OP = 2) */ +#define INS2_ADD 0x00 +#define INS2_AND 0x01 +#define INS2_OR 0x02 +#define INS2_XOR 0x03 +#define INS2_SUB 0x04 +#define INS2_ANDN 0x05 +#define INS2_ORN 0x06 +#define INS2_XNOR 0x07 +#define INS2_ADDC 0x08 +#define INS2_MULX 0x09 +#define INS2_UMUL 0x0a +#define INS2_SMUL 0x0b +#define INS2_SUBC 0x0c +#define INS2_UDIVX 0x0d +#define INS2_UDIV 0x0e +#define INS2_SDIV 0x0f +#define INS2_ADDcc 0x10 +#define INS2_ANDcc 0x11 +#define INS2_ORcc 0x12 +#define INS2_XORcc 0x13 +#define INS2_SUBcc 0x14 +#define INS2_ANDNcc 0x15 +#define INS2_ORNcc 0x16 +#define INS2_XNORcc 0x17 +#define INS2_ADDCcc 0x18 +/* undefined 0x19 */ +#define INS2_UMULcc 0x1a +#define INS2_SMULcc 0x1b +#define INS2_SUBCcc 0x1c +/* undefined 0x1d */ +#define INS2_UDIVcc 0x1e +#define INS2_SDIVcc 0x1f +#define INS2_TADDcc 0x20 +#define INS2_TSUBcc 0x21 +#define INS2_TADDccTV 0x22 +#define INS2_TSUBccTV 0x23 +#define INS2_MULScc 0x24 +#define INS2_SSL 0x25 /* SLLX when IF_X(i) == 1 */ +#define INS2_SRL 0x26 /* SRLX when IF_X(i) == 1 */ +#define INS2_SRA 0x27 /* SRAX when IF_X(i) == 1 */ +#define INS2_RD 0x28 /* and MEMBAR, STBAR */ +/* undefined 0x29 */ +#define INS2_RDPR 0x2a +#define INS2_FLUSHW 0x2b +#define INS2_MOVcc 0x2c +#define INS2_SDIVX 0x2d +#define INS2_POPC 0x2e /* undefined if IF_RS1(i) != 0 */ +#define INS2_MOVr 0x2f +#define INS2_WR 0x30 /* and SIR */ +#define INS2_SV_RSTR 0x31 /* saved, restored */ +#define INS2_WRPR 0x32 +/* undefined 0x33 */ +#define INS2_FPop1 0x34 /* further encoded in opf field */ +#define INS2_FPop2 0x35 /* further encoded in opf field */ +#define INS2_IMPLDEP1 0x36 +#define INS2_IMPLDEP2 0x37 +#define INS2_JMPL 0x38 +#define INS2_RETURN 0x39 +#define INS2_Tcc 0x3a +#define INS2_FLUSH 0x3b +#define INS2_SAVE 0x3c +#define INS2_RESTORE 0x3d +#define INS2_DONE_RETR 0x3e /* done, retry */ +/* undefined 0x3f */ + +/* OP3 values for format 3 (OP = 3) */ +#define INS3_LDUW 0x00 +#define INS3_LDUB 0x01 +#define INS3_LDUH 0x02 +#define INS3_LDD 0x03 +#define INS3_STW 0x04 +#define INS3_STB 0x05 +#define INS3_STH 0x06 +#define INS3_STD 0x07 +#define INS3_LDSW 0x08 +#define INS3_LDSB 0x09 +#define INS3_LDSH 0x0a +#define INS3_LDX 0x0b +/* undefined 0x0c */ +#define INS3_LDSTUB 0x0d +#define INS3_STX 0x0e +#define INS3_SWAP 0x0f +#define INS3_LDUWA 0x10 +#define INS3_LDUBA 0x11 +#define INS3_LDUHA 0x12 +#define INS3_LDDA 0x13 +#define INS3_STWA 0x14 +#define INS3_STBA 0x15 +#define INS3_STHA 0x16 +#define INS3_STDA 0x17 +#define INS3_LDSWA 0x18 +#define INS3_LDSBA 0x19 +#define INS3_LDSHA 0x1a +#define INS3_LDXA 0x1b +/* undefined 0x1c */ +#define INS3_LDSTUBA 0x1d +#define INS3_STXA 0x1e +#define INS3_SWAPA 0x1f +#define INS3_LDF 0x20 +#define INS3_LDFSR 0x21 /* and LDXFSR */ +#define INS3_LDQF 0x22 +#define INS3_LDDF 0x23 +#define INS3_STF 0x24 +#define INS3_STFSR 0x25 /* and STXFSR */ +#define INS3_STQF 0x26 +#define INS3_STDF 0x27 +/* undefined 0x28 - 0x2c */ +#define INS3_PREFETCH 0x2d +/* undefined 0x2e - 0x2f */ +#define INS3_LDFA 0x30 +/* undefined 0x31 */ +#define INS3_LDQFA 0x32 +#define INS3_LDDFA 0x33 +#define INS3_STFA 0x34 +/* undefined 0x35 */ +#define INS3_STQFA 0x36 +#define INS3_STDFA 0x37 +/* undefined 0x38 - 0x3b */ +#define INS3_CASA 0x39 +#define INS3_PREFETCHA 0x3a +#define INS3_CASXA 0x3b + +/* + * OPF values (floating point instructions, IMPLDEP) + */ +/* FPop1 */ +#define INSFP1_FMOVs 0x001 +#define INSFP1_FMOVd 0x002 +#define INSFP1_FMOVq 0x003 +#define INSFP1_FNEGs 0x005 +#define INSFP1_FNEGd 0x006 +#define INSFP1_FNEGq 0x007 +#define INSFP1_FABSs 0x009 +#define INSFP1_FABSd 0x00a +#define INSFP1_FABSq 0x00b +#define INSFP1_FSQRTs 0x029 +#define INSFP1_FSQRTd 0x02a +#define INSFP1_FSQRTq 0x02b +#define INSFP1_FADDs 0x041 +#define INSFP1_FADDd 0x042 +#define INSFP1_FADDq 0x043 +#define INSFP1_FSUBs 0x045 +#define INSFP1_FSUBd 0x046 +#define INSFP1_FSUBq 0x047 +#define INSFP1_FMULs 0x049 +#define INSFP1_FMULd 0x04a +#define INSFP1_FMULq 0x04b +#define INSFP1_FDIVs 0x04d +#define INSFP1_FDIVd 0x04e +#define INSFP1_FDIVq 0x04f +#define INSFP1_FsMULd 0x069 +#define INSFP1_FdMULq 0x06e +#define INSFP1_FsTOx 0x081 +#define INSFP1_FdTOx 0x082 +#define INSFP1_FqTOx 0x083 +#define INSFP1_FxTOs 0x084 +#define INSFP1_FxTOd 0x088 +#define INSFP1_FxTOq 0x08c +#define INSFP1_FiTOs 0x0c4 +#define INSFP1_FdTOs 0x0c6 +#define INSFP1_FqTOs 0x0c7 +#define INSFP1_FiTOd 0x0c8 +#define INSFP1_FsTOd 0x0c9 +#define INSFP1_FqTOd 0x0cb +#define INSFP1_FiTOq 0x0cc +#define INSFP1_FsTOq 0x0cd +#define INSFP1_FdTOq 0x0ce + +/* FPop2 */ +#define INSFP2_FMOV_CCMUL 0x40 +/* use the IFCC_* constants for cc */ +#define INSFP2_FMOV_CC(i, cc) (i + (cc) * INSFP2_FMOV_CCMUL) +#define INSFP2_FMOVs(cc) INSFP2_FMOV_CC(0x01, (cc)) +#define INSFP2_FMOVd(cc) INSFP2_FMOV_CC(0x02, (cc)) +#define INSFP2_FMOVq(cc) INSFP2_FMOV_CC(0x03, (cc)) + +/* use the IRCOND_* constants for rc */ +#define INSFP2_FMOV_RCMUL 0x20 +#define INSFP2_FMOV_RC(i, rc) (i + (rc) * INSFP2_FMOV_RCMUL) +#define INSFP2_FMOVRsZ(rc) INSFP2_FMOV_RC(0x05, (rc)) +#define INSFP2_FMOVRdZ(rc) INSFP2_FMOV_RC(0x06, (rc)) +#define INSFP2_FMOVRqZ(rc) INSFP2_FMOV_RC(0x07, (rc)) +#define INSFP2_FCMPs 0x051 +#define INSFP2_FCMPd 0x052 +#define INSFP2_FCMPq 0x053 +#define INSFP2_FCMPEs 0x055 +#define INSFP2_FCMPEd 0x056 +#define INSFP2_FCMPEq 0x057 + +/* IMPLDEP1 for Sun UltraSparc */ +#define IIDP1_EDGE8 0x00 +#define IIDP1_EDGE8L 0x02 +#define IIDP1_EDGE16 0x04 +#define IIDP1_EDGE16L 0x06 +#define IIDP1_EDGE32 0x08 +#define IIDP1_EDGE32L 0x0a +#define IIDP1_ARRAY8 0x10 +#define IIDP1_ARRAY16 0x12 +#define IIDP1_ARRAY32 0x14 +#define IIDP1_ALIGNADDRESS 0x18 +#define IIDP1_ALIGNADDRESS_L 0x1a +#define IIDP1_FCMPLE16 0x20 +#define IIDP1_FCMPNE16 0x22 +#define IIDP1_FCMPLE32 0x24 +#define IIDP1_FCMPNE32 0x26 +#define IIDP1_FCMPGT16 0x28 +#define IIDP1_FCMPEQ16 0x2a +#define IIDP1_FCMPGT32 0x2c +#define IIDP1_FCMPEQ32 0x2e +#define IIDP1_FMUL8x16 0x31 +#define IIDP1_FMUL8x16AU 0x33 +#define IIDP1_FMUL8X16AL 0x35 +#define IIDP1_FMUL8SUx16 0x36 +#define IIDP1_FMUL8ULx16 0x37 +#define IIDP1_FMULD8SUx16 0x38 +#define IIDP1_FMULD8ULx16 0x39 +#define IIDP1_FPACK32 0x3a +#define IIDP1_FPACK16 0x3b +#define IIDP1_FPACKFIX 0x3d +#define IIDP1_PDIST 0x3e +#define IIDP1_FALIGNDATA 0x48 +#define IIDP1_FPMERGE 0x4b +#define IIDP1_FEXPAND 0x4d +#define IIDP1_FPADD16 0x50 +#define IIDP1_FPADD16S 0x51 +#define IIDP1_FPADD32 0x52 +#define IIDP1_FPADD32S 0x53 +#define IIDP1_SUB16 0x54 +#define IIDP1_SUB16S 0x55 +#define IIDP1_SUB32 0x56 +#define IIDP1_SUB32S 0x57 +#define IIDP1_FZERO 0x60 +#define IIDP1_FZEROS 0x61 +#define IIDP1_FNOR 0x62 +#define IIDP1_FNORS 0x63 +#define IIDP1_FANDNOT2 0x64 +#define IIDP1_FANDNOT2S 0x65 +#define IIDP1_NOT2 0x66 +#define IIDP1_NOT2S 0x67 +#define IIDP1_FANDNOT1 0x68 +#define IIDP1_FANDNOT1S 0x69 +#define IIDP1_FNOT1 0x6a +#define IIDP1_FNOT1S 0x6b +#define IIDP1_FXOR 0x6c +#define IIDP1_FXORS 0x6d +#define IIDP1_FNAND 0x6e +#define IIDP1_FNANDS 0x6f +#define IIDP1_FAND 0x70 +#define IIDP1_FANDS 0x71 +#define IIDP1_FXNOR 0x72 +#define IIDP1_FXNORS 0x73 +#define IIDP1_FSRC1 0x74 +#define IIDP1_FSRC1S 0x75 +#define IIDP1_FORNOT2 0x76 +#define IIDP1_FORNOT2S 0x77 +#define IIDP1_FSRC2 0x78 +#define IIDP1_FSRC2S 0x79 +#define IIDP1_FORNOT1 0x7a +#define IIDP1_FORNOT1S 0x7b +#define IIDP1_FOR 0x7c +#define IIDP1_FORS 0x7d +#define IIDP1_FONE 0x7e +#define IIDP1_FONES 0x7f +#define IIDP1_SHUTDOWN 0x80 + +/* + * Instruction modifiers + */ +/* cond values for integer ccr's */ +#define IICOND_N 0x00 +#define IICOND_E 0x01 +#define IICOND_LE 0x02 +#define IICOND_L 0x03 +#define IICOND_LEU 0x04 +#define IICOND_CS 0x05 +#define IICOND_NEG 0x06 +#define IICOND_VS 0x07 +#define IICOND_A 0x08 +#define IICOND_NE 0x09 +#define IICOND_G 0x0a +#define IICOND_GE 0x0b +#define IICOND_GU 0x0c +#define IICOND_CC 0x0d +#define IICOND_POS 0x0e +#define IICOND_VC 0x0f + +/* cond values for fp ccr's */ +#define IFCOND_N 0x00 +#define IFCOND_NE 0x01 +#define IFCOND_LG 0x02 +#define IFCOND_UL 0x03 +#define IFCOND_L 0x04 +#define IFCOND_UG 0x05 +#define IFCOND_G 0x06 +#define IFCOND_U 0x07 +#define IFCOND_A 0x08 +#define IFCOND_E 0x09 +#define IFCOND_UE 0x0a +#define IFCOND_GE 0x0b +#define IFCOND_UGE 0x0c +#define IFCOND_LE 0x0d +#define IFCOND_ULE 0x0e +#define IFCOND_O 0x0f + +/* rcond values for BPr, MOVr, FMOVr */ +#define IRCOND_RZ 0x01 +#define IRCOND_LEZ 0x02 +#define IRCOND_LZ 0x03 +#define IRCOND_NZ 0x05 +#define IRCOND_GZ 0x06 +#define IRCOND_GEZ 0x07 + +/* cc values for MOVcc and FMOVcc */ +#define IFCC_ICC 0x04 +#define IFCC_XCC 0x06 +/* if true, the lower 2 bits are the fcc number */ +#define IFCC_FCC(c) (((c) & 4) == 0) + +/* cc values for BPc and Tcc */ +#define IBCC_ICC 0x00 +#define IBCC_XCC 0x02 + +/* + * Integer registers + */ +#define IREG_G0 0x00 +#define IREG_O0 0x08 +#define IREG_L0 0x10 +#define IREQ_I0 0x18 + +#endif /* !_MACHINE_INSTR_H_ */ diff --git a/sys/sparc64/sparc64/db_disasm.c b/sys/sparc64/sparc64/db_disasm.c index eb157c8..532fd82 100644 --- a/sys/sparc64/sparc64/db_disasm.c +++ b/sys/sparc64/sparc64/db_disasm.c @@ -38,17 +38,8 @@ #include <ddb/db_sym.h> #include <machine/db_machdep.h> +#include <machine/instr.h> -#ifndef V9 -#define V9 -#endif - -/* Sign extend values */ -#ifdef V9 -#define SIGNEX(v,width) ((((long long)(v))<<(64-width))>>(64-width)) -#else -#define SIGNEX(v,width) ((((int)(v))<<(32-width))>>(32-width)) -#endif #define SIGN(v) (((v)<0)?"-":"") /* @@ -68,40 +59,12 @@ * 0000 0000 0000 0000 0001 0000 0000 0000 X bit, format 3 only */ -#define OP(x) (((x) & 0x3) << 30) -#define OP2(x) (((x) & 0x7) << 22) -#define OP3(x) (((x) & 0x3f) << 19) -#define OPF(x) (((x) & 0x1ff) << 5) -#define F3I(x) (((x) & 0x1) << 13) - -/* various other fields */ - -#define A(x) (((x) & 0x1) << 29) -#define P(x) (((x) & 0x1) << 19) -#define X(x) (((x) & 0x1) << 12) -#define FCN(x) (((x) & 0x1f) << 25) -#define RCOND2(x) (((x) & 0x7) << 25) -#define RCOND34(x) (((x) & 0x7) << 10) -#define COND(x) (((x) & 0xf) << 25) -#define SW_TRAP(x) ((x) & 0x7f) -#define SHCNT32(x) ((x) & 0x1f) -#define SHCNT64(x) ((x) & 0x3f) -#define IMM11(x) ((x) & 0x7ff) -#define IMM22(x) ((x) & 0x3fffff) -#define DISP19(x) ((x) & 0x7ffff) -#define DISP22(x) ((x) & 0x3fffff) -#define DISP30(x) ((x) & 0x3fffffffL) - -/* Register Operand Fields */ -#define RS1(x) (((x) & 0x1f) << 14) -#define RS2(x) ((x) & 0x1f) -#define RD(x) (((x) & 0x1f) << 25) - /* FORMAT macros used in sparc_i table to decode each opcode */ -#define FORMAT1(a) (OP(a)) -#define FORMAT2(a,b) (OP(a) | OP2(b)) -#define FORMAT3(a,b,c) (OP(a) | OP3(b) | F3I(c)) -#define FORMAT3F(a,b,c) (OP(a) | OP3(b) | OPF(c)) +#define FORMAT1(a) (EIF_OP(a)) +#define FORMAT2(a,b) (EIF_OP(a) | EIF_F2_OP2(b)) +/* For formats 3 and 4 */ +#define FORMAT3(a,b,c) (EIF_OP(a) | EIF_F3_OP3(b) | EIF_F3_I(c)) +#define FORMAT3F(a,b,c) (EIF_OP(a) | EIF_F3_OP3(b) | EIF_F3_OPF(c)) /* Helper macros to construct OP3 & OPF */ #define OP3_X(x,y) ((((x) & 3) << 4) | ((y) & 0xf)) @@ -215,84 +178,85 @@ struct sparc_insn sparc_i[] = { {(FORMAT2(0, 0x4)), "sethi", "Cd"}, /* Branch on Integer Co`ndition Codes "Bicc" */ - {(FORMAT2(0, 2) | COND(8)), "ba", "a,m"}, - {(FORMAT2(0, 2) | COND(0)), "bn", "a,m"}, - {(FORMAT2(0, 2) | COND(9)), "bne", "a,m"}, - {(FORMAT2(0, 2) | COND(1)), "be", "a,m"}, - {(FORMAT2(0, 2) | COND(10)), "bg", "a,m"}, - {(FORMAT2(0, 2) | COND(2)), "ble", "a,m"}, - {(FORMAT2(0, 2) | COND(11)), "bge", "a,m"}, - {(FORMAT2(0, 2) | COND(3)), "bl", "a,m"}, - {(FORMAT2(0, 2) | COND(12)), "bgu", "a,m"}, - {(FORMAT2(0, 2) | COND(4)), "bleu", "a,m"}, - {(FORMAT2(0, 2) | COND(13)), "bcc", "a,m"}, - {(FORMAT2(0, 2) | COND(5)), "bcs", "a,m"}, - {(FORMAT2(0, 2) | COND(14)), "bpos", "a,m"}, - {(FORMAT2(0, 2) | COND(6)), "bneg", "a,m"}, - {(FORMAT2(0, 2) | COND(15)), "bvc", "a,m"}, - {(FORMAT2(0, 2) | COND(7)), "bvs", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(8)), "ba", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(0)), "bn", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(9)), "bne", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(1)), "be", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(10)), "bg", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(2)), "ble", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(11)), "bge", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(3)), "bl", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(12)), "bgu", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(4)), "bleu", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(13)), "bcc", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(5)), "bcs", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(14)), "bpos", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(6)), "bneg", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(15)), "bvc", "a,m"}, + {(FORMAT2(0, 2) | EIF_F2_COND(7)), "bvs", "a,m"}, /* Branch on Integer Condition Codes with Prediction "BPcc" */ - {(FORMAT2(0, 1) | COND(8)), "ba", "ap,u"}, - {(FORMAT2(0, 1) | COND(0)), "bn", "ap,u"}, - {(FORMAT2(0, 1) | COND(9)), "bne", "ap,u"}, - {(FORMAT2(0, 1) | COND(1)), "be", "ap,u"}, - {(FORMAT2(0, 1) | COND(10)), "bg", "ap,u"}, - {(FORMAT2(0, 1) | COND(2)), "ble", "ap,u"}, - {(FORMAT2(0, 1) | COND(11)), "bge", "ap,u"}, - {(FORMAT2(0, 1) | COND(3)), "bl", "ap,u"}, - {(FORMAT2(0, 1) | COND(12)), "bgu", "ap,u"}, - {(FORMAT2(0, 1) | COND(4)), "bleu", "ap,u"}, - {(FORMAT2(0, 1) | COND(13)), "bcc", "ap,u"}, - {(FORMAT2(0, 1) | COND(5)), "bcs", "ap,u"}, - {(FORMAT2(0, 1) | COND(14)), "bpos", "ap,u"}, - {(FORMAT2(0, 1) | COND(6)), "bneg", "ap,u"}, - {(FORMAT2(0, 1) | COND(15)), "bvc", "ap,u"}, - {(FORMAT2(0, 1) | COND(7)), "bvs", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(8)), "ba", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(0)), "bn", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(9)), "bne", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(1)), "be", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(10)), "bg", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(2)), "ble", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(11)), "bge", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(3)), "bl", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(12)), "bgu", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(4)), "bleu", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(13)), "bcc", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(5)), "bcs", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(14)), "bpos", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(6)), "bneg", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(15)), "bvc", "ap,u"}, + {(FORMAT2(0, 1) | EIF_F2_COND(7)), "bvs", "ap,u"}, /* Branch on Integer Register with Prediction "BPr" */ - {(FORMAT2(0, 3) | RCOND2(1)), "brz", "ap,1l"}, - {(FORMAT2(0, 3) | A(1) | P(1) | RCOND2(2)), "brlex", "ap,1l"}, - {(FORMAT2(0, 3) | RCOND2(3)), "brlz", "ap,1l"}, - {(FORMAT2(0, 3) | RCOND2(5)), "brnz", "ap,1l"}, - {(FORMAT2(0, 3) | RCOND2(6)), "brgz", "ap,1l"}, - {(FORMAT2(0, 3) | RCOND2(7)), "brgez", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_RCOND(1)), "brz", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_A(1) | EIF_F2_P(1) | + EIF_F2_RCOND(2)), "brlex", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_RCOND(3)), "brlz", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_RCOND(5)), "brnz", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_RCOND(6)), "brgz", "ap,1l"}, + {(FORMAT2(0, 3) | EIF_F2_RCOND(7)), "brgez", "ap,1l"}, /* Branch on Floating-Point Condition Codes with Prediction "FBPfcc" */ - {(FORMAT2(0, 5) | COND(8)), "fba", "ap,m"}, - {(FORMAT2(0, 5) | COND(0)), "fbn", "ap,m"}, - {(FORMAT2(0, 5) | COND(7)), "fbu", "ap,m"}, - {(FORMAT2(0, 5) | COND(6)), "fbg", "ap,m"}, - {(FORMAT2(0, 5) | COND(5)), "fbug", "ap,m"}, - {(FORMAT2(0, 5) | COND(4)), "fbl", "ap,m"}, - {(FORMAT2(0, 5) | COND(3)), "fbul", "ap,m"}, - {(FORMAT2(0, 5) | COND(2)), "fblg", "ap,m"}, - {(FORMAT2(0, 5) | COND(1)), "fbne", "ap,m"}, - {(FORMAT2(0, 5) | COND(9)), "fbe", "ap,m"}, - {(FORMAT2(0, 5) | COND(10)), "fbue", "ap,m"}, - {(FORMAT2(0, 5) | COND(11)), "fbge", "ap,m"}, - {(FORMAT2(0, 5) | COND(12)), "fbuge", "ap,m"}, - {(FORMAT2(0, 5) | COND(13)), "fble", "ap,m"}, - {(FORMAT2(0, 5) | COND(14)), "fbule", "ap,m"}, - {(FORMAT2(0, 5) | COND(15)), "fbo", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(8)), "fba", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(0)), "fbn", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(7)), "fbu", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(6)), "fbg", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(5)), "fbug", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(4)), "fbl", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(3)), "fbul", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(2)), "fblg", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(1)), "fbne", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(9)), "fbe", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(10)), "fbue", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(11)), "fbge", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(12)), "fbuge", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(13)), "fble", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(14)), "fbule", "ap,m"}, + {(FORMAT2(0, 5) | EIF_F2_COND(15)), "fbo", "ap,m"}, /* Branch on Floating-Point Condition Codes "FBfcc" */ - {(FORMAT2(0, 6) | COND(8)), "fba", "a,m"}, - {(FORMAT2(0, 6) | COND(0)), "fbn", "a,m"}, - {(FORMAT2(0, 6) | COND(7)), "fbu", "a,m"}, - {(FORMAT2(0, 6) | COND(6)), "fbg", "a,m"}, - {(FORMAT2(0, 6) | COND(5)), "fbug", "a,m"}, - {(FORMAT2(0, 6) | COND(4)), "fbl", "a,m"}, - {(FORMAT2(0, 6) | COND(3)), "fbul", "a,m"}, - {(FORMAT2(0, 6) | COND(2)), "fblg", "a,m"}, - {(FORMAT2(0, 6) | COND(1)), "fbne", "a,m"}, - {(FORMAT2(0, 6) | COND(9)), "fbe", "a,m"}, - {(FORMAT2(0, 6) | COND(10)), "fbue", "a,m"}, - {(FORMAT2(0, 6) | COND(11)), "fbge", "a,m"}, - {(FORMAT2(0, 6) | COND(12)), "fbuge", "a,m"}, - {(FORMAT2(0, 6) | COND(13)), "fble", "a,m"}, - {(FORMAT2(0, 6) | COND(14)), "fbule", "a,m"}, - {(FORMAT2(0, 6) | COND(15)), "fbo", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(8)), "fba", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(0)), "fbn", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(7)), "fbu", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(6)), "fbg", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(5)), "fbug", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(4)), "fbl", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(3)), "fbul", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(2)), "fblg", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(1)), "fbne", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(9)), "fbe", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(10)), "fbue", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(11)), "fbge", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(12)), "fbuge", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(13)), "fble", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(14)), "fbule", "a,m"}, + {(FORMAT2(0, 6) | EIF_F2_COND(15)), "fbo", "a,m"}, @@ -305,14 +269,9 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,0), 1), "addcc", "1id"}, {FORMAT3(2, OP3_X(2,0), 0), "taddcc", "12d"}, {FORMAT3(2, OP3_X(2,0), 1), "taddcc", "1id"}, -#ifdef V9 - {(FORMAT3(2, 0x30, 1) | RD(0xf)), "sir", "i"}, + {(FORMAT3(2, 0x30, 1) | EIF_F3_RD(0xf)), "sir", "i"}, {FORMAT3(2, OP3_X(3,0), 0), "wr", "12H"}, {FORMAT3(2, OP3_X(3,0), 1), "wr", "1iH"}, -#else - {FORMAT3(2, OP3_X(3,0), 0), "wr", "12Y"}, /* wr 1, 2, %y */ - {FORMAT3(2, OP3_X(3,0), 1), "wr", "1iY"}, /* wr 1, i, %y */ -#endif {FORMAT3(2, OP3_X(0,1), 0), "and", "12d"}, {FORMAT3(2, OP3_X(0,1), 1), "and", "1id"}, @@ -320,13 +279,8 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,1), 1), "andcc", "1id"}, {FORMAT3(2, OP3_X(2,1), 0), "tsubcc", "12d"}, {FORMAT3(2, OP3_X(2,1), 1), "tsubcc", "1id"}, -#ifdef V9 {FORMAT3(2, OP3_X(3,1), 0), "saved", ""}, - {FORMAT3(2, OP3_X(3,1), 0)|FCN(1), "restored", ""}, -#else - {FORMAT3(2, OP3_X(3,1), 0), "wr", "12P"}, /* wr 1, 2, %psr */ - {FORMAT3(2, OP3_X(3,1), 1), "wr", "1iP"}, /* wr 1, i, %psr */ -#endif + {FORMAT3(2, OP3_X(3,1), 0) | EIF_F3_FCN(1), "restored", ""}, {FORMAT3(2, OP3_X(0,2), 0), "or", "12d"}, {FORMAT3(2, OP3_X(0,2), 1), "or", "1id"}, @@ -334,13 +288,8 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,2), 1), "orcc", "1id"}, {FORMAT3(2, OP3_X(2,2), 0), "taddcctv", "12d"}, {FORMAT3(2, OP3_X(2,2), 1), "taddcctv", "1id"}, -#ifdef V9 {FORMAT3(2, OP3_X(3,2), 0), "wrpr", "12G"}, {FORMAT3(2, OP3_X(3,2), 1), "wrpr", "1iG"}, -#else - {FORMAT3(2, OP3_X(3,2), 0), "wr", "12W"}, /* wr 1, 2, %wim */ - {FORMAT3(2, OP3_X(3,2), 1), "wr", "1iW"}, /* wr 1, i, %wim */ -#endif {FORMAT3(2, OP3_X(0,3), 0), "xor", "12d"}, {FORMAT3(2, OP3_X(0,3), 1), "xor", "1id"}, @@ -348,12 +297,7 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,3), 1), "xorcc", "1id"}, {FORMAT3(2, OP3_X(2,3), 0), "tsubcctv", "12d"}, {FORMAT3(2, OP3_X(2,3), 1), "tsubcctv", "1id"}, -#ifdef V9 {FORMAT3(2, OP3_X(3,3), 0), "UNDEFINED", ""}, -#else - {FORMAT3(2, OP3_X(3,3), 0), "wr", "12T"}, /* wr 1, 2, %tbr */ - {FORMAT3(2, OP3_X(3,3), 1), "wr", "1iT"}, /* wr 1, i, %tbr */ -#endif {FORMAT3(2, OP3_X(0,4), 0), "sub", "12d"}, {FORMAT3(2, OP3_X(0,4), 1), "sub", "1id"}, @@ -369,8 +313,8 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,5), 1), "andncc", "1id"}, {FORMAT3(2, OP3_X(2,5), 0), "sll", "12d"}, {FORMAT3(2, OP3_X(2,5), 1), "sll", "1Dd"}, - {FORMAT3(2, OP3_X(2,5), 0)|X(1), "sllx", "12d"}, - {FORMAT3(2, OP3_X(2,5), 1)|X(1), "sllx", "1Ed"}, + {FORMAT3(2, OP3_X(2,5), 0) | EIF_F3_X(1), "sllx", "12d"}, + {FORMAT3(2, OP3_X(2,5), 1) | EIF_F3_X(1), "sllx", "1Ed"}, {FORMAT3(2, OP3_X(3,5), 1), "FPop2", ""}, /* see below */ {FORMAT3(2, OP3_X(0,6), 0), "orn", "12d"}, @@ -379,8 +323,8 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,6), 1), "orncc", "1id"}, {FORMAT3(2, OP3_X(2,6), 0), "srl", "12d"}, {FORMAT3(2, OP3_X(2,6), 1), "srl", "1Dd"}, - {FORMAT3(2, OP3_X(2,6), 0)|X(1), "srlx", "12d"}, - {FORMAT3(2, OP3_X(2,6), 1)|X(1), "srlx", "1Ed"}, + {FORMAT3(2, OP3_X(2,6), 0) | EIF_F3_X(1), "srlx", "12d"}, + {FORMAT3(2, OP3_X(2,6), 1) | EIF_F3_X(1), "srlx", "1Ed"}, {FORMAT3(2, OP3_X(3,6), 1), "impdep1", ""}, {FORMAT3(2, OP3_X(0,7), 0), "xorn", "12d"}, @@ -389,21 +333,17 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(1,7), 1), "xorncc", "1id"}, {FORMAT3(2, OP3_X(2,7), 0), "sra", "12d"}, {FORMAT3(2, OP3_X(2,7), 1), "sra", "1Dd"}, - {FORMAT3(2, OP3_X(2,7), 0)|X(1), "srax", "12d"}, - {FORMAT3(2, OP3_X(2,7), 1)|X(1), "srax", "1Ed"}, + {FORMAT3(2, OP3_X(2,7), 0) | EIF_F3_X(1), "srax", "12d"}, + {FORMAT3(2, OP3_X(2,7), 1) | EIF_F3_X(1), "srax", "1Ed"}, {FORMAT3(2, OP3_X(3,7), 1), "impdep2", ""}, {FORMAT3(2, OP3_X(0,8), 0), "addc", "12d"}, {FORMAT3(2, OP3_X(0,8), 1), "addc", "1id"}, {FORMAT3(2, OP3_X(1,8), 0), "addccc", "12d"}, {FORMAT3(2, OP3_X(1,8), 1), "addccc", "1id"}, -#ifdef V9 - {(FORMAT3(2, 0x28, 1) | RS1(15)), "membar", "9"}, - {(FORMAT3(2, 0x28, 0) | RS1(15)), "stbar", ""}, + {(FORMAT3(2, 0x28, 1) | EIF_F3_RS1(15)), "membar", "9"}, + {(FORMAT3(2, 0x28, 0) | EIF_F3_RS1(15)), "stbar", ""}, {FORMAT3(2, OP3_X(2,8), 0), "rd", "Bd"}, -#else - {FORMAT3(2, OP3_X(2,8), 0), "rd", "Yd"}, -#endif {FORMAT3(2, OP3_X(3,8), 0), "jmpl", "pd"}, {FORMAT3(2, OP3_X(3,8), 1), "jmpl", "qd"}, @@ -411,11 +351,7 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(0,9), 0), "mulx", "12d"}, {FORMAT3(2, OP3_X(0,9), 1), "mulx", "1id"}, {FORMAT3(2, OP3_X(1,9), 0), "UNDEFINED", ""}, -#ifdef V9 {FORMAT3(2, OP3_X(2,9), 0), "UNDEFINED", ""}, -#else - {FORMAT3(2, OP3_X(2,9), 0), "rd", "Pd"}, -#endif {FORMAT3(2, OP3_X(3,9), 0), "return", "p"}, {FORMAT3(2, OP3_X(3,9), 1), "return", "q"}, @@ -423,56 +359,48 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(0,10), 1), "umul", "1id"}, {FORMAT3(2, OP3_X(1,10), 0), "umulcc", "12d"}, {FORMAT3(2, OP3_X(1,10), 1), "umulcc", "1id"}, -#ifdef V9 {FORMAT3(2, OP3_X(2,10), 0), "rdpr", "Ad"}, -#else - {FORMAT3(2, OP3_X(2,10), 0), "rd", "Wd"}, -#endif /* * OP3 = (3,10): TCC: Trap on Integer Condition Codes */ - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x8)), "ta", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x8)), "ta", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x0)), "tn", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x0)), "tn", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x9)), "tne", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x9)), "tne", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x1)), "te", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x1)), "te", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xa)), "tg", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xa)), "tg", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x2)), "tle", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x2)), "tle", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xb)), "tge", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xb)), "tge", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x3)), "tl", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x3)), "tl", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xc)), "tgu", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xc)), "tgu", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x4)), "tleu", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x4)), "tleu", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xd)), "tcc", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xd)), "tcc", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x5)), "tcs", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x5)), "tcs", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xe)), "tpos", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xe)), "tpos", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x6)), "tneg", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x6)), "tneg", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0xf)), "tvc", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0xf)), "tvc", "0F"}, - {(FORMAT3(2, OP3_X(3,10), 0) | COND(0x7)), "tvs", "12F"}, - {(FORMAT3(2, OP3_X(3,10), 1) | COND(0x7)), "tvs", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x8)), "ta", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x8)), "ta", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x0)), "tn", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x0)), "tn", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x9)), "tne", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x9)), "tne", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x1)), "te", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x1)), "te", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xa)), "tg", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xa)), "tg", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x2)), "tle", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x2)), "tle", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xb)), "tge", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xb)), "tge", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x3)), "tl", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x3)), "tl", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xc)), "tgu", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xc)), "tgu", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x4)), "tleu", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x4)), "tleu", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xd)), "tcc", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xd)), "tcc", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x5)), "tcs", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x5)), "tcs", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xe)), "tpos", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xe)), "tpos", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x6)), "tneg", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x6)), "tneg", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0xf)), "tvc", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0xf)), "tvc", "0F"}, + {(FORMAT3(2, OP3_X(3,10), 0) | EIF_F4_TCOND(0x7)), "tvs", "12F"}, + {(FORMAT3(2, OP3_X(3,10), 1) | EIF_F4_TCOND(0x7)), "tvs", "0F"}, {FORMAT3(2, OP3_X(0,11), 0), "smul", "12d"}, {FORMAT3(2, OP3_X(0,11), 1), "smul", "1id"}, {FORMAT3(2, OP3_X(1,11), 0), "smulcc", "12d"}, {FORMAT3(2, OP3_X(1,11), 1), "smulcc", "1id"}, -#ifdef V9 {FORMAT3(2, OP3_X(2,11), 0), "flushw", ""}, -#else - {FORMAT3(2, OP3_X(2,11), 0), "rd", "Td"}, -#endif {FORMAT3(2, OP3_X(3,11), 0), "flush", "p"}, {FORMAT3(2, OP3_X(3,11), 1), "flush", "q"}, @@ -570,7 +498,7 @@ struct sparc_insn sparc_i[] = { {FORMAT3(2, OP3_X(2,14), 1), "popc", "id"}, {FORMAT3(2, OP3_X(3,14), 0), "done", ""}, - {FORMAT3(2, OP3_X(3,14)|FCN(1), 1), "retry", ""}, + {FORMAT3(2, OP3_X(3,14) | EIF_F3_FCN(1), 1), "retry", ""}, {FORMAT3(2, OP3_X(0,15), 0), "sdiv", "12d"}, {FORMAT3(2, OP3_X(0,15), 1), "sdiv", "1id"}, @@ -580,18 +508,18 @@ struct sparc_insn sparc_i[] = { * OP3 = (2,15): MOVr: * Move Integer Register on Register Condition */ - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(1)), "movrz", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(1)), "movrz", "12d"}, - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(2)), "movrlez", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(2)), "movrlez", "12d"}, - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(3)), "movrlz", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(3)), "movrlz", "12d"}, - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(5)), "movrnz", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(5)), "movrnz", "12d"}, - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(6)), "movrgz", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(6)), "movrgz", "12d"}, - {(FORMAT3(2, OP3_X(2,15), 1) | RCOND34(7)), "movrgez", "1jd"}, - {(FORMAT3(2, OP3_X(2,15), 0) | RCOND34(7)), "movrgez", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(1)), "movrz", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(1)), "movrz", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(2)), "movrlez", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(2)), "movrlez", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(3)), "movrlz", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(3)), "movrlz", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(5)), "movrnz", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(5)), "movrnz", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(6)), "movrgz", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(6)), "movrgz", "12d"}, + {(FORMAT3(2, OP3_X(2,15), 1) | EIF_F3_RCOND(7)), "movrgez", "1jd"}, + {(FORMAT3(2, OP3_X(2,15), 0) | EIF_F3_RCOND(7)), "movrgez", "12d"}, {FORMAT3(2, OP3_X(3,15), 0), "UNDEFINED", ""}, @@ -614,10 +542,10 @@ struct sparc_insn sparc_i[] = { {(FORMAT3(3, OP3_X(0,1), 1)), "ldub", "qd"}, {(FORMAT3(3, OP3_X(1,1), 0)), "lduba", "7d"}, {(FORMAT3(3, OP3_X(1,1), 1)), "lduba", "8d"}, - {(FORMAT3(3, OP3_X(2,1), 0) | RD(0)), "ld", "p5"}, - {(FORMAT3(3, OP3_X(2,1), 1) | RD(0)), "ld", "q5"}, - {(FORMAT3(3, OP3_X(2,1), 0) | RD(1)), "ldx", "p6"}, - {(FORMAT3(3, OP3_X(2,1), 1) | RD(1)), "ldx", "q6"}, + {(FORMAT3(3, OP3_X(2,1), 0) | EIF_F3_RD(0)), "ld", "p5"}, + {(FORMAT3(3, OP3_X(2,1), 1) | EIF_F3_RD(0)), "ld", "q5"}, + {(FORMAT3(3, OP3_X(2,1), 0) | EIF_F3_RD(1)), "ldx", "p6"}, + {(FORMAT3(3, OP3_X(2,1), 1) | EIF_F3_RD(1)), "ldx", "q6"}, {(FORMAT3(3, OP3_X(0,2), 0)), "lduh", "pd"}, {(FORMAT3(3, OP3_X(0,2), 1)), "lduh", "qd"}, @@ -652,8 +580,8 @@ struct sparc_insn sparc_i[] = { {(FORMAT3(3, OP3_X(1,5), 1)), "stba", "d8"}, {(FORMAT3(3, OP3_X(2,5), 0)), "st", "5p"}, {(FORMAT3(3, OP3_X(2,5), 1)), "st", "5q"}, - {(FORMAT3(3, OP3_X(2,5), 0)|RD(1)), "stx", "6p"}, - {(FORMAT3(3, OP3_X(2,5), 1)|RD(1)), "stx", "6q"}, + {(FORMAT3(3, OP3_X(2,5), 0) | EIF_F3_RD(1)), "stx", "6p"}, + {(FORMAT3(3, OP3_X(2,5), 1) | EIF_F3_RD(1)), "stx", "6q"}, {(FORMAT3(3, OP3_X(0,6), 0)), "sth", "dp"}, {(FORMAT3(3, OP3_X(0,6), 1)), "sth", "dq"}, @@ -825,12 +753,12 @@ struct sparc_insn sparc_i[] = { /* Move F-P Register on Integer Register Condition "FMOVr" */ /* FIXME: check for short, double, and quad's */ - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(1)), "fmovre", "14e"}, - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(2)), "fmovrlez", "14e"}, - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(3)), "fmovrlz", "14e"}, - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(5)), "fmovrne", "14e"}, - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(6)), "fmovrgz", "14e"}, - {(FORMAT3(2, OP3_X(3,5), 0) | RCOND34(7)), "fmovrgez", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(1)), "fmovre", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(2)), "fmovrlez", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(3)), "fmovrlz", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(5)), "fmovrne", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(6)), "fmovrgz", "14e"}, + {(FORMAT3(2, OP3_X(3,5), 0) | EIF_F3_RCOND(7)), "fmovrgez", "14e"}, #endif /* FP logical insns -- UltraSPARC extens */ {(FORMAT3F(2, OP3_X(3,6), OPF_X(6,0))), "fzero", "e"}, @@ -905,21 +833,23 @@ db_disasm(loc, altfmt) you_lose &= (FORMAT2(0x3,0x7)); } else { /* Branches */ - you_lose &= (FORMAT2(0x3,0x7)|COND(0xf)); + you_lose &= (FORMAT2(0x3,0x7) | + EIF_F2_COND(0xf)); } } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x34) /* XXX */ { /* FPop1 */ - you_lose &= (FORMAT3(0x3,0x3f,0x1) | OPF(0x1ff)); + you_lose &= (FORMAT3(0x3,0x3f,0x1) | + EIF_F3_OPF(0x1ff)); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x3a) /* XXX */ { /* Tcc */ - you_lose &= (FORMAT3(0x3,0x3f,0x1) | COND(0xf)); + you_lose &= (FORMAT3(0x3,0x3f,0x1) | EIF_F4_TCOND(0xf)); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>21) & 0xf) == 0x9 && ((bitmask>>19) & 0x3) != 0) /* XXX */ { /* shifts */ - you_lose &= (FORMAT3(0x3,0x3f,0x1))|X(1); + you_lose &= (FORMAT3(0x3,0x3f,0x1)) | EIF_F3_X(1); } else if (((bitmask>>30) & 0x3) == 0x2 && ((bitmask>>19) & 0x3f) == 0x2c) /* XXX */ { /* cmov */ @@ -953,11 +883,11 @@ db_disasm(loc, altfmt) for (;f_ptr < cp; f_ptr++) switch (*f_ptr) { case 'a': - if (insn & A(1)) + if (insn & EIF_F2_A(1)) db_printf(",a"); break; case 'p': - if (insn & P(1)) + if (insn & EIF_F2_P(1)) db_printf(",pt"); else db_printf(",pn"); @@ -992,29 +922,29 @@ db_disasm(loc, altfmt) break; case 'i': /* simm13 -- signed */ - val = SIGNEX(insn, 13); + val = IF_SIMM(insn, 13); db_printf("%s0x%x", SIGN(val), (int)abs(val)); break; case 'j': /* simm11 -- signed */ - val = SIGNEX(insn, 11); + val = IF_SIMM(insn, 11); db_printf("%s0x%x", SIGN(val), (int)abs(val)); break; case 'l': val = (((insn>>20)&0x3)<<13)|(insn & 0x1fff); - val = SIGNEX(val, 16); + val = IF_SIMM(val, 16); db_printsym((db_addr_t)(loc + (4 * val)), DB_STGY_ANY); break; case 'm': - db_printsym((db_addr_t)(loc + (4 * SIGNEX(insn, 22))), + db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 22))), DB_STGY_ANY); break; case 'u': - db_printsym((db_addr_t)(loc + (4 * SIGNEX(insn, 19))), + db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 19))), DB_STGY_ANY); break; case 'n': - db_printsym((db_addr_t)(loc + (4 * SIGNEX(insn, 30))), + db_printsym((db_addr_t)(loc + (4 * IF_SIMM(insn, 30))), DB_STGY_PROC); break; case 's': @@ -1036,7 +966,7 @@ db_disasm(loc, altfmt) break; case 'q': case '8': - val = SIGNEX(insn, 13); + val = IF_SIMM(insn, 13); db_printf("[%%%s %c 0x%x]", regs[((insn >> 14) & 0x1f)], (int)((val<0)?'-':'+'), @@ -1087,20 +1017,6 @@ db_disasm(loc, altfmt) case 'H': db_printf("%%%s", state_regs[((insn >> 25) & 0x1f)]); break; -#ifndef V9 - case 'P': - db_printf("%%psr"); - break; - case 'T': - db_printf("%%tbr"); - break; - case 'W': - db_printf("%%wim"); - break; - case 'Y': - db_printf("%%y"); - break; -#endif default: db_printf("(UNKNOWN)"); break; diff --git a/sys/sparc64/sparc64/emul.c b/sys/sparc64/sparc64/emul.c new file mode 100644 index 0000000..a46f206 --- /dev/null +++ b/sys/sparc64/sparc64/emul.c @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/proc.h> +#include <sys/signal.h> +#include <sys/sysctl.h> +#include <sys/systm.h> + +#include <machine/frame.h> +#include <machine/instr.h> + +int unaligned_fixup(struct thread *td, struct trapframe *tf); +int emulate_insn(struct thread *td, struct trapframe *tf); + +/* + * Alpha-compatible sysctls to control the alignment fixup. + */ +static int unaligned_print = 1; /* warn about unaligned accesses */ +static int unaligned_fix = 1; /* fix up unaligned accesses */ +static int unaligned_sigbus = 0; /* don't SIGBUS on fixed-up accesses */ + +SYSCTL_INT(_machdep, OID_AUTO, unaligned_print, CTLFLAG_RW, + &unaligned_print, 0, ""); + +SYSCTL_INT(_machdep, OID_AUTO, unaligned_fix, CTLFLAG_RW, + &unaligned_fix, 0, ""); + +SYSCTL_INT(_machdep, OID_AUTO, unaligned_sigbus, CTLFLAG_RW, + &unaligned_sigbus, 0, ""); + +static int +fetch_reg(struct trapframe *tf, int reg, u_long *val) +{ + u_long offs; + + CTR1(KTR_TRAP, "fetch_reg: register %d", reg); + if (reg == IREG_G0) + *val = 0; + else if (reg < IREG_O0) /* global */ + *val = tf->tf_global[reg]; + else if (reg < IREG_L0) /* out */ + *val = tf->tf_out[reg - IREG_O0]; + else { /* local, in */ + /* + * The in registers are immediately after the locals in + * the frame. + */ + offs = offsetof(struct frame, f_local[reg - IREG_L0]); + return (copyin((void *)(tf->tf_sp + SPOFF + offs), val, + sizeof(*val))); + } + return (0); +} + +static int +store_reg(struct trapframe *tf, int reg, u_long val) +{ + u_long offs; + + CTR1(KTR_TRAP, "store_reg: register %d", reg); + if (reg == IREG_G0) + return (0); + if (reg < IREG_O0) /* global */ + tf->tf_global[reg] = val; + else if (reg < IREG_L0) /* out */ + tf->tf_out[reg - IREG_O0] = val; + else { /* local, in */ + /* + * The in registers are immediately after the locals in + * the frame. + */ + offs = offsetof(struct frame, f_local[reg - IREG_L0]); + return (copyout(&val, (void *)(tf->tf_sp + SPOFF + offs), + sizeof(val))); + } + return (0); +} + +/* Retrieve rs2 or use the immediate value from the instruction */ +static int +f3_op2(struct trapframe *tf, u_int insn, u_long *op2) +{ + int error; + + if (IF_F3_I(insn) != 0) + *op2 = IF_SIMM(insn, 13); + else { + if ((error = fetch_reg(tf, IF_F3_RS2(insn), op2)) != 0) + return (error); + } + return (0); +} + +/* + * XXX: should the addr from the sfar be used instead of decoding the + * instruction? + */ +static int +f3_memop_addr(struct trapframe *tf, u_int insn, u_long *addr) +{ + u_long addr1; + int error; + + if ((error = f3_op2(tf, insn, &addr1)) != 0) + return (error); + CTR2(KTR_TRAP, "f3_memop_addr: addr1: %#lx (imm %d)", addr1, IF_F3_I(insn)); + error = fetch_reg(tf, IF_F3_RS1(insn), addr); + *addr += addr1; + return (error); +} + +static int +fixup_st(struct trapframe *tf, u_int insn, int size) +{ + u_long addr, reg; + int error; + + if ((error = f3_memop_addr(tf, insn, &addr)) != 0) + return (error); + if ((error = fetch_reg(tf, IF_F3_RD(insn), ®)) != 0) + return (error); + reg <<= 8 * (8 - size); + CTR1(KTR_TRAP, "fixup_st: writing to %#lx", addr); + return (copyout(®, (void *)addr, size)); +} + +static int +fixup_ld(struct trapframe *tf, u_int insn, int size, int sign) +{ + u_long addr, reg; + int error; + + if ((error = f3_memop_addr(tf, insn, &addr)) != 0) + return (error); + reg = 0; + CTR1(KTR_TRAP, "fixup_ld: reading from %#lx", addr); + if ((error = copyin((void *)addr, ®, size)) != 0) + return (error); + reg >>= 8 * (8 - size); + if (sign && size < 8) { + /* Need to sign-extend. */ + reg = IF_SEXT(reg, size * 8); + } + return (store_reg(tf, IF_F3_RD(insn), reg)); +} + +/* + * NOTE: fixed up loads and stores are not atomical any more (in some cases, + * they could be made, though, but that is not implemented yet). This means + * that in some sorts of programs, this emulation could cause bugs. + * XXX: this is still very incomplete! + */ +int +unaligned_fixup(struct thread *td, struct trapframe *tf) +{ + struct mmuframe *mf; + struct proc *p; + u_int insn; + int fixed, error; + + p = td->td_proc; + mf = (struct mmuframe *)tf->tf_arg; + + if (rwindow_save(td) != 0) { + /* + * The process will need to be killed without sending a + * signal; let the signal code do that. + */ + return (SIGBUS); + } + if (copyin((void *)tf->tf_tpc, &insn, sizeof(insn)) != 0) + return (SIGBUS); + + CTR1(KTR_TRAP, "unaligned_fixup: insn %x", insn); + fixed = 0; + if (unaligned_fix) { + error = 0; + if (IF_OP(insn) == IOP_LDST) { + fixed = 1; + switch (IF_F3_OP3(insn)) { + case INS3_LDUH: + error = fixup_ld(tf, insn, 2, 0); + break; + case INS3_LDUW: + error = fixup_ld(tf, insn, 4, 0); + break; + case INS3_LDX: + error = fixup_ld(tf, insn, 8, 0); + break; + case INS3_LDSH: + error = fixup_ld(tf, insn, 2, 1); + break; + case INS3_LDSW: + error = fixup_ld(tf, insn, 4, 1); + break; + case INS3_STH: + error = fixup_st(tf, insn, 2); + break; + case INS3_STW: + error = fixup_st(tf, insn, 4); + break; + case INS3_STX: + error = fixup_st(tf, insn, 8); + break; + default: + fixed = 0; + } + } + if (error != 0) + return (SIGBUS); + } + + CTR5(KTR_TRAP, "unaligned_fixup: pid %d, va=%#lx pc=%#lx " + "npc=%#lx, fixed=%d", p->p_pid, mf->mf_sfar, tf->tf_tpc, + tf->tf_tnpc, fixed); + if (unaligned_print || !fixed) { + uprintf("pid %d (%s): unaligned access: va=%#lx pc=%#lx " + "npc=%#lx %s\n", p->p_pid, p->p_comm, mf->mf_sfar, + tf->tf_tpc, tf->tf_tnpc, fixed ? "(fixed)" : "(unfixable)"); + } + return (fixed && !unaligned_sigbus ? 0 : SIGBUS); +} + +static int +emul_popc(struct trapframe *tf, u_int insn) +{ + u_long reg, res; + int i; + + if (IF_F3_RS1(insn) != 0) + return (SIGILL); + if (f3_op2(tf, insn, ®) != 0) + return (SIGBUS); + res = 0; + for (i = 0; i < 64; i++) + res += (reg >> i) & 1; + if (store_reg(tf, IF_F3_RD(insn), res) != 0) + return (SIGBUS); + return (0); +} + +/* + * Emulate unimplemented instructions, if applicable. + * Only handles popc right now. + */ +int +emulate_insn(struct thread *td, struct trapframe *tf) +{ + u_int insn; + + if (rwindow_save(td) != 0) { + /* + * The process will need to be killed without sending a + * signal; let the signal code do that. + */ + return (SIGBUS); + } + if (copyin((void *)tf->tf_tpc, &insn, sizeof(insn)) != 0) + return (SIGBUS); + + CTR1(KTR_TRAP, "emulate_insn: insn %x", insn); + switch (IF_OP(insn)) { + case IOP_MISC: + switch (IF_F3_OP3(insn)) { + case INS2_POPC: + return (emul_popc(tf, insn)); + } + break; + } + return (SIGILL); +} diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index bf99279..032ca2a 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -126,6 +126,9 @@ const char *trap_msg[] = { "trap instruction", }; +int unaligned_fixup(struct thread *td, struct trapframe *tf); +int emulate_insn(struct thread *td, struct trapframe *tf); + void trap(struct trapframe *tf) { @@ -175,6 +178,11 @@ trap(struct trapframe *tf) * User Mode Traps */ case T_ALIGN: + if ((sig = unaligned_fixup(td, tf)) == 0) { + TF_DONE(tf); + goto user; + } + goto trapsig; case T_ALIGN_LDDF: case T_ALIGN_STDF: sig = SIGBUS; @@ -222,7 +230,10 @@ trap(struct trapframe *tf) } goto userout; case T_INSN_ILLEGAL: - sig = SIGILL; + if ((sig = emulate_insn(td, tf)) == 0) { + TF_DONE(tf); + goto user; + } goto trapsig; case T_PRIV_ACTION: case T_PRIV_OPCODE: @@ -521,8 +532,7 @@ syscall(struct trapframe *tf) * (usually), instead we need to advance one instruction. */ tpc = tf->tf_tpc; - tf->tf_tpc = tf->tf_tnpc; - tf->tf_tnpc += 4; + TF_DONE(tf); if (p->p_sysent->sv_prepsyscall) { /* |