Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sparcv9 / sparcv9decode.c
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: sparcv9decode.c
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "@(#)sparcv9decode.c 1.69 07/03/19 SMI"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include "basics.h"
#include "fatal.h"
#include "simcore.h"
#include "config.h"
#include "xicache.h"
#include "tsparcv9.h"
#include "tsparcv9internal.h"
#include "sparcv9decode.h"
#include "breakpoint.h"
#include "hostnative_asm.h" /* autogenerated from hostnative_asm.S */
#include "hostnative.h" /* autogenerated from hostnative.c */
#include "execinstns.h" /* autogenerated core defined instructions */
#include "sparcv9instns.h" /* autogenerated sparcv9 instruction definitions */
static char * v9_illegal_reason_str[]={
"illegal_instruction",
"unknown_instruction",
"unknown_fp_instruction",
"bpcc_illegal_cc_specifier",
"bpr_illegal_cc_specifier",
"done_retry_illegal_fcn_field",
"saved_fcn_invalid",
"saved_reserved_field_non_zero",
"tcc_reserved_field_non_zero",
"tcc_illegal_cc_field",
"movcc_reserved_field_non_zero",
"movcc_illegal_cc_field",
"movr_illegal_cc_field",
"odd_rd_for_ldd",
"odd_rd_for_std",
"fpop_bit13_set",
"illegal_fsr_specifier",
"unimplemented_visop",
"illtrap_reserved_field_non_zero",
"fmovcc_reserved_field_non_zero",
"fmovcc_illegal_cc_field",
"flushw_reserved_field_non_zero",
"visop36_reserved_field_non_zero",
"sir_reserved_field_non_zero",
"cas_reserved_field_non_zero",
"misc_reserved_field_non_zero"
};
#ifdef FP_DECODE_DISABLED
#define FP_DECODE_FPU_ON_CHECK \
if (!((sparcv9_cpu_t*)(sp->specificp))->fpu_on) goto fp_disabled
#else /* FP_DECODE_DISABLED */
#define FP_DECODE_FPU_ON_CHECK
#endif /* FP_DECODE_DISABLED */
void sparcv9_decode_me(simcpu_t *sp, xicache_instn_t * xcip)
{
int rs1, rd, rs2;
void (*exec_funcp)(simcpu_t *sp, xicache_instn_t * xcip);
void (*p_exec_funcp)(simcpu_t *sp, xicache_instn_t * xcip);
sint32_t simm;
uint32_t uimm;
T0o3_code_t op0c;
T2o3_code_t op2c;
T3o3_code_t op3c;
uint64_t tmp;
bool_t on_bp;
uint32_t instn;
XIC_MISS(sp);
on_bp = false;
/*
* Very first step .... check to see if breakpoint
* reached. If true, install breakpoint catcher instead
* of a decoded instruction ....
* ... if there is a match, we still decode the instruction,
* but replace the actual instruction operation with a trampoline
* the instruction operation is then encoded into the
* breakpoint itself.
*
* FIXME : for the time being because of the hassles of flushing the
* x-cache, we dont install a trampoline .. we leave the decoded func
* as decode_me and pay the penalty .... this way we can track the
* breakpoint progress for the time being.
* Also means we don't have to have the decoded instn in the breakpoint
* either ....
*
* OK: So if we match an active breakpoint, we *must* always leave the
* decoded function as *_decode_me. Asside from this whether or
* not we execute the *real* decoded instruction depends on whether or
* not the breakpoint is being executed for the first time, or this
* is the first instruction after that breakpoint being taken !
*/
if (sp->bp_infop != NULL) {
breakpoint_t *bp;
switch (breakpoint_check(sp->bp_infop, sp->pc, DEFAULT_BP_CONTEXT /* FIXME */, &bp)) {
case ON_BREAKPOINT:
if (bp == NULL /* "next" breakpoint */
|| bp->first_strike == false) {
/* just stop if we really want to break */
if (bp != NULL)
bp->first_strike = true;
simcore_stop();
return;
} else {
/* if not, continue the decode, but don't install the function */
bp->first_strike = false;
on_bp = true;
}
break;
case NOTHING:
break;
}
}
/*
* For sparcv9, to save us time an undecoded instruction is
* saved as a bit pattern in the xicache ...
* ... saves us a second v-to-p conversion so we can read memory
*/
instn = xcip->rawi;
/*
* Decoder is designed for a big endian instn encoding.
* So to make life simpler on a little endian host, reverse the byte order
* and then treat as big endian.
*/
instn = FE_INSTN(instn);
/*
* Now go about the legitimate instruction decoding
*/
switch ((ty_code_t)X_OP(instn)) {
case Ty_0:
op0c = (T0o3_code_t)X_OP2(instn);
switch (op0c) {
sint32_t br_offset;
bool_t annul_bit;
case T0o3_Bicc:
/* Deprecated integer condition code branches */
br_offset = X_FMT2_DISP22(instn);
br_offset = ((br_offset << 10) >> 8); /* sign extend to 32bits */
annul_bit = X_ANNUL_BIT(instn);
bpcc_entry:;
SET_OP_BROFF32(br_offset);
switch ((bcc_type_t)X_COND(instn)) {
case Bcc_a:
bicc_ba:;
if (annul_bit) {
SET_OPv9(bralways_ds_annul);
} else {
SET_OPv9(bralways_ds);
}
goto all_done;
case Bcc_n:
bicc_bn:;
if (!annul_bit) goto do_noop;
SET_OPv9(brnever_ds_annul);
goto all_done;
#define BR_DECODE(_cc, _type) \
case Bcc_##_type: \
if (annul_bit) { \
SET_OPv9(b##_type##_##_cc##_an); \
} else { \
SET_OPv9(b##_type##_##_cc); \
} \
break
BR_DECODE(icc, ne);
BR_DECODE(icc, e);
BR_DECODE(icc, g);
BR_DECODE(icc, le);
BR_DECODE(icc, ge);
BR_DECODE(icc, l);
BR_DECODE(icc, gu);
BR_DECODE(icc, leu);
BR_DECODE(icc, cc);
BR_DECODE(icc, cs);
BR_DECODE(icc, pos);
BR_DECODE(icc, neg);
BR_DECODE(icc, vc);
BR_DECODE(icc, vs);
}
goto all_done;
case T0o3_BPcc:
br_offset = X_FMT2_DISP19(instn);
br_offset = ((br_offset << 13) >> 11); /* sign extend */
annul_bit = X_ANNUL_BIT(instn);
/* v9 Predicted integer condition code branches */
switch( (cc2bit_t)X_FMT2_CC(instn)) {
case CC2bit_icc:
goto bpcc_entry;
case CC2bit_xcc:
break;
default:
/* defined as illegal - rather than unknown */
SET_OP_ILL_REASON(bpcc_illegal_cc_specifier);
goto illegal_instruction;
}
/* Only xcc bpcc forms here ... */
SET_OP_BROFF32(br_offset);
switch ((bcc_type_t)X_COND(instn)) {
case Bcc_a: goto bicc_ba;
case Bcc_n: goto bicc_bn;
BR_DECODE(xcc, ne);
BR_DECODE(xcc, e);
BR_DECODE(xcc, g);
BR_DECODE(xcc, le);
BR_DECODE(xcc, ge);
BR_DECODE(xcc, l);
BR_DECODE(xcc, gu);
BR_DECODE(xcc, leu);
BR_DECODE(xcc, cc);
BR_DECODE(xcc, cs);
BR_DECODE(xcc, pos);
BR_DECODE(xcc, neg);
BR_DECODE(xcc, vc);
BR_DECODE(xcc, vs);
}
goto all_done;
case T0o3_SetHi:
rd = X_RD(instn);
if (rd == 0) goto do_noop;
uimm = (instn & 0x3FFFFF) << 10;
SET_OP( move_uimm );
SET_OP_RD(rd);
SET_OP_UIMM32(uimm);
goto all_done;
case T0o3_Illtrap:
if (!CHECK_RESERVED_ZERO(instn, 29, 25)) {
SET_OP_ILL_REASON(illtrap_reserved_field_non_zero);
goto illegal_instruction;
}
SET_OPv9(illtrap);
/* capture const22 */
SET_OP_UIMM32((instn & 0x3FFFFF));
goto all_done;
case T0o3_BPr:
rs1 = X_RS1(instn);
br_offset = X_FMT2_DISP16(instn);
br_offset = ((br_offset << 16) >> 14); /* sign extend to 32bits & scale by 4*/
annul_bit = X_ANNUL_BIT(instn);
SET_OP_BREGOFF32(br_offset);
SET_OP_RS1(rs1);
#define BREG_DECODE(_type, _an) \
case RCond_##_type: \
SET_OPv9(br##_type##_an); \
goto all_done
if (annul_bit) {
switch ((rcond_type_t)X_RCOND(instn)) {
BREG_DECODE(z,_an);
BREG_DECODE(lez,_an);
BREG_DECODE(lz,_an);
BREG_DECODE(nz,_an);
BREG_DECODE(gz,_an);
BREG_DECODE(gez,_an);
default:
break;
}
SET_OP_ILL_REASON(bpr_illegal_cc_specifier);
goto illegal_instruction;
}
switch ((rcond_type_t)X_RCOND(instn)) {
BREG_DECODE(z,);
BREG_DECODE(lez,);
BREG_DECODE(lz,);
BREG_DECODE(nz,);
BREG_DECODE(gz,);
BREG_DECODE(gez,);
default:
break;
}
SET_OP_ILL_REASON(bpr_illegal_cc_specifier);
goto illegal_instruction;
#undef BREG_DECODE
case T0o3_FBfcc:
FP_DECODE_FPU_ON_CHECK;
/* Deprecated floating condition code branches */
br_offset = X_FMT2_DISP22(instn);
br_offset = ((br_offset << 10) >> 8); /* sign extend to 32bits */
annul_bit = X_ANNUL_BIT(instn);
SET_OP_BR_FCC(0);
fbpcc_entry:;
SET_OP_BROFF32(br_offset);
switch ((bcc_type_t)X_COND(instn)) {
case FBcc_a:
fbicc_ba:;
if (annul_bit) {
SET_OPv9(bralways_ds_annul);
} else {
SET_OPv9(bralways_ds);
}
goto all_done;
case FBcc_n:
fbicc_bn:;
if (!annul_bit) goto do_noop;
SET_OPv9(brnever_ds_annul);
goto all_done;
#define FBR_DECODE(_cc, _type) \
case FBcc_##_type: \
if (annul_bit) { \
SET_OPv9(fb##_type##_##_cc##_an); \
} else { \
SET_OPv9(fb##_type##_##_cc); \
} \
break
FBR_DECODE(fcc0, e);
FBR_DECODE(fcc0, ne);
FBR_DECODE(fcc0, ue);
FBR_DECODE(fcc0, lg);
FBR_DECODE(fcc0, ge);
FBR_DECODE(fcc0, ul);
FBR_DECODE(fcc0, uge);
FBR_DECODE(fcc0, l);
FBR_DECODE(fcc0, le);
FBR_DECODE(fcc0, ug);
FBR_DECODE(fcc0, ule);
FBR_DECODE(fcc0, g);
FBR_DECODE(fcc0, o);
FBR_DECODE(fcc0, u);
}
goto all_done;
case T0o3_FBPfcc:
FP_DECODE_FPU_ON_CHECK;
br_offset = X_FMT2_DISP19(instn);
br_offset = ((br_offset << 13) >> 11); /* sign extend */
annul_bit = X_ANNUL_BIT(instn);
/* v9 Predicted floating condition code branches */
SET_OP_BR_FCC(X_FMT2_CC(instn));
switch( (fcc2bit_t)X_FMT2_CC(instn)) {
case FCC2bit_fcc0:
goto fbpcc_entry;
}
/* Only fcc1-3 bpcc forms here ... */
SET_OP_BROFF32(br_offset);
switch ((bcc_type_t)X_COND(instn)) {
case FBcc_a: goto fbicc_ba;
case FBcc_n: goto fbicc_bn;
FBR_DECODE(fccN, e);
FBR_DECODE(fccN, ne);
FBR_DECODE(fccN, ue);
FBR_DECODE(fccN, lg);
FBR_DECODE(fccN, ge);
FBR_DECODE(fccN, ul);
FBR_DECODE(fccN, uge);
FBR_DECODE(fccN, l);
FBR_DECODE(fccN, le);
FBR_DECODE(fccN, ug);
FBR_DECODE(fccN, ule);
FBR_DECODE(fccN, g);
FBR_DECODE(fccN, o);
FBR_DECODE(fccN, u);
}
goto all_done;
default:
break;
}
goto unknown_decode;
case Ty_1: /* Call instruction only */
{
sint32_t offset;
offset = X_FMT1_DISP30(instn) << 2; /* shift to be address relative */
SET_OP_SIMM32( offset );
SET_OPv9(call);
goto all_done;
}
case Ty_2:
rs1 = X_RS1(instn);
rd = X_RD(instn);
op2c = (T2o3_code_t)X_OP3(instn);
if (X_I(instn)) {
simm = X_SIMM13(instn);
/* register x immediate -> register forms */
switch ( op2c ) {
/*
* Arithmetic instructions first
*/
case T2o3_add :
if (rd == 0) goto do_noop;
if (simm == 0) {
if (rs1 == 0) goto do_zero_reg;
goto do_move_reg;
}
if (rs1 == 0) goto do_move_simm;
SET_OP( add_imm );
goto do_imm;
case T2o3_addc :
if (rd == 0) goto do_noop;
SET_OPv9( add_ci_imm );
goto do_imm;
case T2o3_addcc :
if (rd == 0) {
SET_OPv9( add_co_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( add_co_imm );
}
goto do_imm;
case T2o3_addccc :
if (rd == 0 ) {
SET_OPv9( add_cico_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( add_cico_imm );
}
goto do_imm;
case T2o3_sub :
if (rd == 0) goto do_noop;
if (simm == 0 && rs1 == 0) goto do_zero_reg;
if (simm == 0) goto do_move_reg;
simm = -simm;
if (rs1 == 0) goto do_move_simm;
SET_OP( add_imm );
goto do_imm;
case T2o3_subc :
if (rd == 0) goto do_noop;
SET_OPv9( sub_ci_imm );
goto do_imm;
case T2o3_subcc :
if (rd == 0) {
SET_OPv9( sub_co_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( sub_co_imm );
}
goto do_imm;
case T2o3_subccc :
if (rd == 0) {
SET_OPv9( sub_cico_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( sub_cico_imm );
}
goto do_imm;
case T2o3_andn :
simm = ~simm; /* fall thru*/
case T2o3_and :
if (rd == 0) goto do_noop;
if (simm == 0 || rs1==0) goto do_zero_reg;
if (simm == -1) goto do_move_reg;
SET_OP( and_imm );
goto do_imm;
case T2o3_orn:
simm = ~simm; /* fall thru*/
case T2o3_or :
if (rd == 0) goto do_noop;
if (simm == 0 && rs1==0) goto do_zero_reg;
if (simm == 0) goto do_move_reg;
if (rs1 == 0) goto do_move_simm;
SET_OP( or_imm );
goto do_imm;
case T2o3_xnor :
simm = ~simm; /* fall thru*/
case T2o3_xor :
if (rd == 0) goto do_noop;
if (simm == 0 && rs1 == 0) goto do_zero_reg;
if (simm == 0) goto do_move_reg;
if (rs1 == 0) goto do_move_simm;
SET_OP( xor_imm );
goto do_imm;
/* cond code out - forms */
case T2o3_andncc :
simm = ~simm; /* fall thru*/
case T2o3_andcc :
if (rd == 0) {
SET_OPv9( and_cc_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( and_cc_imm );
}
goto do_imm;
case T2o3_orncc :
simm = ~simm; /* fall thru*/
case T2o3_orcc :
if (rd == 0) {
SET_OPv9( or_cc_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( or_cc_imm );
}
goto do_imm;
case T2o3_xnorcc :
simm = ~simm; /* fall thru*/
case T2o3_xorcc :
if (rd == 0) {
SET_OPv9( xor_cc_imm_rd0 ); /* rd==0 */
} else {
SET_OPv9( xor_cc_imm );
}
goto do_imm;
/*
** Shift operations
*/
case T2o3_sll :
if (!(X_SHIFT_SIZE_BIT(instn) ?
CHECK_RESERVED_ZERO(instn, 11, 6) :
CHECK_RESERVED_ZERO(instn, 11, 5))) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (rs1 == 0) goto do_zero_reg;
simm = (X_SHIFT_SIZE_BIT(instn)) ? X_SHIFT_IMM64(instn) : X_SHIFT_IMM32(instn);
SET_OP(sll_imm);
goto do_imm;
case T2o3_srl :
if (!(X_SHIFT_SIZE_BIT(instn) ?
CHECK_RESERVED_ZERO(instn, 11, 6) :
CHECK_RESERVED_ZERO(instn, 11, 5))) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (rs1 == 0) goto do_zero_reg;
if (X_SHIFT_SIZE_BIT(instn)) {
simm = X_SHIFT_IMM64(instn);
SET_OP( srl64_imm );
} else {
simm = X_SHIFT_IMM32(instn);
SET_OP( srl32_imm );
}
goto do_imm;
case T2o3_sra :
if (!(X_SHIFT_SIZE_BIT(instn) ?
CHECK_RESERVED_ZERO(instn, 11, 6) :
CHECK_RESERVED_ZERO(instn, 11, 5))) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (rs1 == 0) goto do_zero_reg;
if (X_SHIFT_SIZE_BIT(instn)) {
simm = X_SHIFT_IMM64(instn);
SET_OP( sra64_imm );
} else {
simm = X_SHIFT_IMM32(instn);
SET_OP( sra32_imm );
}
goto do_imm;
case T2o3_jmpl :
if (rd == 0) {
SET_OPv9(jmpl_imm_rd0);
} else {
SET_OPv9(jmpl_imm);
}
goto do_imm;
case T2o3_tcc :
if (!CHECK_RESERVED_ZERO(instn, 10, 8)) {
SET_OP_ILL_REASON(tcc_reserved_field_non_zero);
goto illegal_instruction;
}
switch( (cc4bit_t)X_FMT4_CC(instn) ) {
case CC4bit_icc: SET_OP_TRAP_CC(0); break;
case CC4bit_xcc: SET_OP_TRAP_CC(1); break;
default:
SET_OP_ILL_REASON(tcc_illegal_cc_field);
goto illegal_instruction;
}
/* truncate simm - as only an 8 bit
* immediate in tcc instructions, not the
* 13 bit field we extracted above
*/
simm = simm & 0xff;
if (X_COND(instn) == cond_n) goto do_noop;
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
SET_OP_TRAP_COND(X_COND(instn));
/* We attempt to fast path ta ... */
if (X_COND(instn) == cond_a && rs1==0)
SET_OPv9(trap_imm_fast);
else
SET_OPv9(trapcc_imm);
goto all_done;
case T2o3_saved:
saved_instn:;
/* Niagara2 and Rock support additional functions. */
goto unknown_decode;
case T2o3_retry :
done_retry_instn:;
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_save :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_restore :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_smul :
/* can't check for rd = 0 because side-effect is write to Y reg */
SET_OPv9(smul_imm);
goto do_imm;
case T2o3_umul :
/* can't check for rd = 0 because side-effect is write to Y reg */
SET_OPv9(umul_imm);
goto do_imm;
case T2o3_mulx :
if (rd==0) goto do_noop;
SET_OP(mul_imm);
goto do_imm;
case T2o3_rdasr :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_wrasr :
if (rd == 0xf) {
/* sir shares this opcode */
if (!CHECK_RESERVED_ZERO(instn, 18, 14)) {
SET_OP_ILL_REASON(sir_reserved_field_non_zero);
goto illegal_instruction;
}
SET_OPv9( sir );
SET_OP_SIMM16(simm);
goto all_done;
}
SET_OPv9( write_state_reg_imm );
goto do_imm;
case T2o3_rdpr :
SET_OPv9( read_priv_reg );
simm = rs1; /* duplicate the reg code into simm */
goto do_imm;
case T2o3_rdhpr :
SET_OPv9( read_hyper_priv_reg );
simm = rs1; /* duplicate the reg code into simm */
goto do_imm;
case T2o3_wrpr :
SET_OPv9( write_priv_reg_imm );
goto do_imm;
case T2o3_wrhpr :
SET_OPv9( write_hyper_priv_reg_imm );
goto do_imm;
case T2o3_return :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_udivx :
/* cant optimise for rd=0 because */
/* need to test for /0 */
SET_OPv9(udiv64_imm);
goto do_imm;
case T2o3_udiv :
SET_OPv9(udiv_imm);
goto do_imm;
case T2o3_sdiv :
SET_OPv9(sdiv_imm);
goto do_imm;
case T2o3_umulcc :
SET_OPv9(umul_cc_imm);
goto do_imm;
case T2o3_smulcc :
SET_OPv9(smul_cc_imm);
goto do_imm;
case T2o3_udivcc :
SET_OPv9(udiv_cc_imm);
goto do_imm;
case T2o3_sdivcc :
SET_OPv9(sdiv_cc_imm);
goto do_imm;
case T2o3_taddcc :
SET_OPv9(tadd_co_imm);
goto do_imm;
case T2o3_tsubcc :
SET_OPv9(tsub_co_imm);
goto do_imm;
case T2o3_taddcctv :
SET_OPv9(tadd_co_tv_imm);
goto do_imm;
case T2o3_tsubcctv :
SET_OPv9(tsub_co_tv_imm);
goto do_imm;
case T2o3_mulscc :
goto unknown_decode;
case T2o3_flushw :
SET_OP_ILL_REASON(flushw_reserved_field_non_zero);
goto illegal_instruction;
case T2o3_movcc :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_sdivx :
SET_OPv9(sdiv64_imm);
goto do_imm;
case T2o3_popc :
goto unknown_decode;
case T2o3_movr :
if (rd == 0) goto do_noop;
simm = X_SIMM10(instn);
SET_OP_SIMM16(simm);
SET_OP_RS1(rs1);
SET_OP_RD(rd);
switch ((rcond_type_t)X_MOVRCOND(instn)) {
case RCond_z:
SET_OPv9(movr_imm_z);
break;
case RCond_lez:
SET_OPv9(movr_imm_lez);
break;
case RCond_lz:
SET_OPv9(movr_imm_lz);
break;
case RCond_nz:
SET_OPv9(movr_imm_nz);
break;
case RCond_gz:
SET_OPv9(movr_imm_gz);
break;
case RCond_gez:
SET_OPv9(movr_imm_gez);
break;
default:
SET_OP_ILL_REASON(movr_illegal_cc_field);
goto illegal_instruction;
}
goto all_done;
case T2o3_fpop_0x34 :
/* jumping out of _imm to _rrr forms */
rs2 = X_RS2(instn);
goto handle_fpop_0x34;
case T2o3_fpop_0x35 :
/* jumping out of _imm to _rrr forms */
rs2 = X_RS2(instn);
goto handle_fpop_0x35;
case T2o3_gop :
/* jumping out of _imm to _rrr forms */
rs2 = X_RS2(instn);
goto handle_gop;
case T2o3_flush :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_unknown_0x19 :
case T2o3_unknown_0x1d :
case T2o3_unknown_0x37 :
case T2o3_unknown_0x3f :
break;
}
goto unknown_decode;
} else {
rs2 = X_RS2(instn);
/* register x register -> register forms */
switch ( op2c ) {
case T2o3_add :
if (rd == 0) goto do_noop;
if (rs2 == 0) {
if (rs1 == 0) goto do_zero_reg;
goto do_move_reg;
}
if (rs1 == 0) {
rs1 = rs2;
goto do_move_reg;
}
SET_OP( add_rrr );
goto do_rrr;
case T2o3_addc :
if (rd == 0) goto do_noop;
SET_OPv9( add_ci_rrr );
goto do_rrr;
case T2o3_addcc :
if (rd == 0) {
SET_OPv9( add_co_rrr_rd0 );
} else {
SET_OPv9( add_co_rrr );
}
goto do_rrr;
case T2o3_addccc :
if (rd == 0) {
SET_OPv9( add_cico_rrr_rd0 );
} else {
SET_OPv9( add_cico_rrr );
}
goto do_rrr;
case T2o3_sub :
if (rd==0) goto do_noop;
if (rs2==0 && rs1==0) goto do_zero_reg;
if (rs2==0) goto do_move_reg;
SET_OP( sub_rrr );
goto do_rrr;
case T2o3_subc :
if (rd == 0) goto do_noop;
SET_OPv9( sub_ci_rrr );
goto do_rrr;
case T2o3_subcc :
if (rd == 0) {
SET_OPv9( sub_co_rrr_rd0 );
} else {
SET_OPv9( sub_co_rrr );
}
goto do_rrr;
case T2o3_subccc :
if (rd == 0) {
SET_OPv9( sub_cico_rrr_rd0 );
} else {
SET_OPv9( sub_cico_rrr );
}
goto do_rrr;
/*
* Logic RRR forms
*/
case T2o3_and :
if (rd == 0) goto do_noop;
if (rs2 == 0 || rs1==0) goto do_zero_reg;
SET_OP( and_rrr );
goto do_rrr;
case T2o3_or :
if (rd == 0) goto do_noop;
if (rs2 == 0 && rs1==0) goto do_zero_reg;
if (rs2 == 0) goto do_move_reg;
if (rs1 == 0) {
rs1 = rs2;
goto do_move_reg;
}
SET_OP( or_rrr );
goto do_rrr;
case T2o3_xor:
if (rd == 0) goto do_noop;
if (rs2 == 0 && rs1==0) goto do_zero_reg;
if (rs2 == 0) goto do_move_reg;
if (rs1 == 0) {
rs1 = rs2;
goto do_move_reg;
}
SET_OP( xor_rrr );
goto do_rrr;
case T2o3_andn :
if (rd==0) goto do_noop;
if (rs1==0) goto do_zero_reg;
if (rs2==0) goto do_move_reg;
SET_OP( andn_rrr );
goto do_rrr;
case T2o3_orn :
if (rd==0) goto do_noop;
/* more optmisiing here - FIXME */
SET_OP( orn_rrr );
goto do_rrr;
case T2o3_xnor :
if (rd == 0) goto do_noop;
SET_OP( xnor_rrr );
goto do_rrr;
/* condition code forms */
case T2o3_andcc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( and_cc_rrr_rd0 );
} else {
SET_OPv9( and_cc_rrr );
}
goto do_rrr;
case T2o3_andncc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( andn_cc_rrr_rd0 );
} else {
SET_OPv9( andn_cc_rrr );
}
goto do_rrr;
case T2o3_orcc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( or_cc_rrr_rd0 );
} else {
SET_OPv9( or_cc_rrr );
}
goto do_rrr;
case T2o3_orncc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( orn_cc_rrr_rd0 );
} else {
SET_OPv9( orn_cc_rrr );
}
goto do_rrr;
case T2o3_xorcc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( xor_cc_rrr_rd0 );
} else {
SET_OPv9( xor_cc_rrr );
}
goto do_rrr;
case T2o3_xnorcc :
if (rd == 0) { /* RD0DECODE */
SET_OPv9( xnor_cc_rrr_rd0 );
} else {
SET_OPv9( xnor_cc_rrr );
}
goto do_rrr;
/*
** Shift operations
*/
case T2o3_sll :
if (!CHECK_RESERVED_ZERO(instn, 11, 5)) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (X_SHIFT_SIZE_BIT(instn)) {
SET_OP(sll64_rrr);
} else {
SET_OP(sll32_rrr);
}
goto do_rrr;
case T2o3_srl :
if (!CHECK_RESERVED_ZERO(instn, 11, 5)) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (X_SHIFT_SIZE_BIT(instn)) {
SET_OP(srl64_rrr);
} else {
SET_OP(srl32_rrr);
}
goto do_rrr;
case T2o3_sra :
if (!CHECK_RESERVED_ZERO(instn, 11, 5)) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) goto do_noop;
if (X_SHIFT_SIZE_BIT(instn)) {
SET_OP(sra64_rrr);
} else {
SET_OP(sra32_rrr);
}
goto do_rrr;
case T2o3_jmpl :
if (!CHECK_RESERVED_ZERO(instn, 12, 5)) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
if (rd == 0) {
SET_OPv9(jmpl_rrr_rd0);
} else {
SET_OPv9(jmpl_rrr);
}
goto do_rrr;
case T2o3_saved:
goto saved_instn;
case T2o3_retry :
goto done_retry_instn;
case T2o3_smul :
/* can't check for rd = 0 because side-effect is write to Y reg */
SET_OPv9(smul_rrr);
goto do_rrr;
case T2o3_umul :
/* can't check for rd = 0 because side-effect is write to Y reg */
SET_OPv9(umul_rrr);
goto do_rrr;
case T2o3_mulx :
if (rd==0) goto do_noop;
SET_OP(mul_rrr);
goto do_rrr;
case T2o3_rdasr :
/* Here I = 0 */
if (rd == 0 && rs1==15) {
if (!CHECK_RESERVED_ZERO(instn, 12, 0)) {
SET_OP_ILL_REASON(misc_reserved_field_non_zero);
goto illegal_instruction;
}
SET_OPv9( stbar );
goto all_done; /* no further args */
}
SET_OPv9( read_state_reg );
simm = 0; /* unused */
goto do_imm;
case T2o3_rdpr :
SET_OPv9( read_priv_reg );
simm = rs1; /* duplicate the reg code into simm */
goto do_imm;
case T2o3_rdhpr :
SET_OPv9( read_hyper_priv_reg );
simm = rs1; /* duplicate the reg code into simm */
goto do_imm;
case T2o3_wrpr :
SET_OPv9( write_priv_reg_rrr );
goto do_rrr;
case T2o3_wrhpr :
SET_OPv9( write_hyper_priv_reg_rrr );
goto do_rrr;
case T2o3_wrasr :
SET_OPv9( write_state_reg_rrr );
goto do_rrr;
/* save and restore ! */
case T2o3_save :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_restore :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_return :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_tcc :
if (!CHECK_RESERVED_ZERO(instn, 10, 5)) {
SET_OP_ILL_REASON(tcc_reserved_field_non_zero);
goto illegal_instruction;
}
switch( (cc4bit_t)X_FMT4_CC(instn) ) {
case CC4bit_icc: SET_OP_TRAP_CC(0); break;
case CC4bit_xcc: SET_OP_TRAP_CC(1); break;
default:
SET_OP_ILL_REASON(tcc_illegal_cc_field);
goto illegal_instruction;
}
if (X_COND(instn) == cond_n) goto do_noop;
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
SET_OP_TRAP_COND(X_COND(instn));
SET_OPv9(trapcc_rr);
goto all_done;
case T2o3_udivx :
/* cant optimise for rd=0 because */
/* need to test for /0 */
SET_OPv9(udiv64_rrr);
goto do_rrr;
case T2o3_udiv :
SET_OPv9(udiv_rrr);
goto do_rrr;
case T2o3_sdiv :
SET_OPv9(sdiv_rrr);
goto do_rrr;
case T2o3_umulcc :
SET_OPv9(umul_cc_rrr);
goto do_rrr;
case T2o3_smulcc :
SET_OPv9(smul_cc_rrr);
goto do_rrr;
case T2o3_udivcc :
SET_OPv9(udiv_cc_rrr);
goto do_rrr;
case T2o3_sdivcc :
SET_OPv9(sdiv_cc_rrr);
goto do_rrr;
case T2o3_taddcc :
SET_OPv9(tadd_co_rrr);
goto do_rrr;
case T2o3_tsubcc :
SET_OPv9(tsub_co_rrr);
goto do_rrr;
case T2o3_taddcctv :
SET_OPv9(tadd_co_tv_rrr);
goto do_rrr;
case T2o3_tsubcctv :
SET_OPv9(tsub_co_tv_rrr);
goto do_rrr;
case T2o3_mulscc :
goto unknown_decode;
case T2o3_flushw :
{
int fcn = X_FMT2_FCN(instn);
if (!fcn && (!CHECK_RESERVED_ZERO(instn, 18, 0))) {
SET_OP_ILL_REASON(flushw_reserved_field_non_zero);
goto illegal_instruction;
}
SET_OPv9(flushw);
goto all_done;
}
case T2o3_movcc :
if (!CHECK_RESERVED_ZERO(instn, 10, 5)) {
SET_OP_ILL_REASON(movcc_reserved_field_non_zero);
goto illegal_instruction;
}
if (!X_FMT4_CC2(instn)) {
FP_DECODE_FPU_ON_CHECK;
if (rd == 0) goto do_noop;
/* We attempt to fast path movfcc_a ... */
if (X_FMT4_COND(instn) == cond_n) goto do_noop;
if (X_FMT4_COND(instn) == cond_a) {
rs1 = rs2;
goto do_move_reg;
}
SET_OP_MOVCC_CC(X_FMT4_CC(instn));
SET_OP_RD(rd);
SET_OP_RS2(rs2);
SET_OP_MOVCC_COND(X_FMT4_COND(instn));
SET_OPv9(movfcc_rr);
goto all_done;
}
if (rd == 0) goto do_noop;
switch( (cc4bit_t)X_FMT4_CC(instn) ) {
case CC4bit_icc: SET_OP_MOVCC_CC(0); break;
case CC4bit_xcc: SET_OP_MOVCC_CC(1); break;
default:
SET_OP_ILL_REASON(movcc_illegal_cc_field);
goto illegal_instruction;
}
/* We attempt to fast path movcc_a ... */
if (X_FMT4_COND(instn) == cond_n) goto do_noop;
if (X_FMT4_COND(instn) == cond_a) {
rs1 = rs2;
goto do_move_reg;
}
SET_OP_RD(rd);
SET_OP_RS2(rs2);
SET_OP_MOVCC_COND(X_FMT4_COND(instn));
SET_OPv9(movcc_rr);
goto all_done;
case T2o3_sdivx :
SET_OPv9(sdiv64_rrr);
goto do_rrr;
case T2o3_popc :
goto unknown_decode;
case T2o3_movr :
if (rd == 0) goto do_noop;
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
SET_OP_RD(rd);
switch ((rcond_type_t)X_MOVRCOND(instn)) {
case RCond_z:
SET_OPv9(movr_rr_z);
break;
case RCond_lez:
SET_OPv9(movr_rr_lez);
break;
case RCond_lz:
SET_OPv9(movr_rr_lz);
break;
case RCond_nz:
SET_OPv9(movr_rr_nz);
break;
case RCond_gz:
SET_OPv9(movr_rr_gz);
break;
case RCond_gez:
SET_OPv9(movr_rr_gez);
break;
default:
SET_OP_ILL_REASON(movr_illegal_cc_field);
goto illegal_instruction;
}
goto all_done;
case T2o3_fpop_0x34 :
handle_fpop_0x34:;
FP_DECODE_FPU_ON_CHECK;
switch ((T3o3_fp34_opf_t)X_FP_OPF(instn)) {
case FPop34_fmovs: SET_OPv9(fmovs); goto do_fp_s2s_ds;
case FPop34_fmovd: SET_OPv9(fmovd); goto do_fp_s2d_dd;
case FPop34_fmovq: goto unimplemented_fpop;
case FPop34_fnegs: SET_OPv9(fnegs); goto do_fp_s2s_ds;
case FPop34_fnegd: SET_OPv9(fnegd); goto do_fp_s2d_dd;
case FPop34_fnegq: goto unimplemented_fpop;
case FPop34_fabss: SET_OPv9(fabss); goto do_fp_s2s_ds;
case FPop34_fabsd: SET_OPv9(fabsd); goto do_fp_s2d_dd;
case FPop34_fabsq: goto unimplemented_fpop;
/*
* Niagara 1 doesn't have fsqrt[sd], but this
* is dealt with in the fpsim_bw support.
*/
case FPop34_fsqrts: SET_OPv9(fsqrts); goto do_fp_s2s_ds;
case FPop34_fsqrtd: SET_OPv9(fsqrtd); goto do_fp_s2d_dd;
case FPop34_fsqrtq: goto unimplemented_fpop;
case FPop34_fadds: SET_OPv9(fadds); goto do_fp_s1s_s2s_ds;
case FPop34_faddd: SET_OPv9(faddd); goto do_fp_s1d_s2d_dd;
case FPop34_faddq: goto unimplemented_fpop;
case FPop34_fsubs: SET_OPv9(fsubs); goto do_fp_s1s_s2s_ds;
case FPop34_fsubd: SET_OPv9(fsubd); goto do_fp_s1d_s2d_dd;
case FPop34_fsubq: goto unimplemented_fpop;
case FPop34_fmuls: SET_OPv9(fmuls); goto do_fp_s1s_s2s_ds;
case FPop34_fmuld: SET_OPv9(fmuld); goto do_fp_s1d_s2d_dd;
case FPop34_fmulq: goto unimplemented_fpop;
case FPop34_fdivs: SET_OPv9(fdivs); goto do_fp_s1s_s2s_ds;
case FPop34_fdivd: SET_OPv9(fdivd); goto do_fp_s1d_s2d_dd;
case FPop34_fdivq: goto unimplemented_fpop;
case FPop34_fsmuld: SET_OPv9(fsmuld); goto do_fp_s1s_s2s_dd;
case FPop34_fdmulq: goto unimplemented_fpop;
case FPop34_fstox: SET_OPv9(fstox); goto do_fp_s2s_dd;
case FPop34_fdtox: SET_OPv9(fdtox); goto do_fp_s2d_dd;
case FPop34_fqtox: goto unimplemented_fpop;
case FPop34_fxtos: SET_OPv9(fxtos); goto do_fp_s2d_ds;
case FPop34_fxtod: SET_OPv9(fxtod); goto do_fp_s2d_dd;
case FPop34_fxtoq: goto unimplemented_fpop;
case FPop34_fitos: SET_OPv9(fitos); goto do_fp_s2s_ds;
case FPop34_fdtos: SET_OPv9(fdtos); goto do_fp_s2d_ds;
case FPop34_fqtos: goto unimplemented_fpop;
case FPop34_fitod: SET_OPv9(fitod); goto do_fp_s2s_dd;
case FPop34_fstod: SET_OPv9(fstod); goto do_fp_s2s_dd;
case FPop34_fqtod: goto unimplemented_fpop;
case FPop34_fitoq: goto unimplemented_fpop;
case FPop34_fstoq: goto unimplemented_fpop;
case FPop34_fdtoq: goto unimplemented_fpop;
case FPop34_fstoi: SET_OPv9(fstoi); goto do_fp_s2s_ds;
case FPop34_fdtoi: SET_OPv9(fdtoi); goto do_fp_s2d_ds;
case FPop34_fqtoi: goto unimplemented_fpop;
default:
goto unknown_fp_decode;
}
case T2o3_fpop_0x35 :
handle_fpop_0x35:
FP_DECODE_FPU_ON_CHECK;
switch ((T3o3_fp35_opf_t)X_FP_OPF(instn)) {
case FPop35_fcmps:
switch( (fcc2bit_t)X_FCOND(instn)) {
case FCC2bit_fcc0:
SET_OPv9(fcmps_fcc0); break;
case FCC2bit_fcc1:
SET_OPv9(fcmps_fcc1); break;
case FCC2bit_fcc2:
SET_OPv9(fcmps_fcc2); break;
case FCC2bit_fcc3:
SET_OPv9(fcmps_fcc3); break;
}
goto do_fp_s1s_s2s_cmp;
case FPop35_fcmpd:
switch( (fcc2bit_t)X_FCOND(instn)) {
case FCC2bit_fcc0:
SET_OPv9(fcmpd_fcc0); break;
case FCC2bit_fcc1:
SET_OPv9(fcmpd_fcc1); break;
case FCC2bit_fcc2:
SET_OPv9(fcmpd_fcc2); break;
case FCC2bit_fcc3:
SET_OPv9(fcmpd_fcc3); break;
}
goto do_fp_s1d_s2d_cmp;
case FPop35_fcmpq: goto unimplemented_fpop;
case FPop35_fcmpes:
switch( (fcc2bit_t)X_FCOND(instn)) {
case FCC2bit_fcc0:
SET_OPv9(fcmpes_fcc0); break;
case FCC2bit_fcc1:
SET_OPv9(fcmpes_fcc1); break;
case FCC2bit_fcc2:
SET_OPv9(fcmpes_fcc2); break;
case FCC2bit_fcc3:
SET_OPv9(fcmpes_fcc3); break;
}
goto do_fp_s1s_s2s_cmp;
case FPop35_fcmped:
switch( (fcc2bit_t)X_FCOND(instn)) {
case FCC2bit_fcc0:
SET_OPv9(fcmped_fcc0); break;
case FCC2bit_fcc1:
SET_OPv9(fcmped_fcc1); break;
case FCC2bit_fcc2:
SET_OPv9(fcmped_fcc2); break;
case FCC2bit_fcc3:
SET_OPv9(fcmped_fcc3); break;
}
goto do_fp_s1d_s2d_cmp;
case FPop35_fcmpeq: goto unimplemented_fpop;
case FPop35_fmovs_fcc0:
case FPop35_fmovs_fcc1:
case FPop35_fmovs_fcc2:
case FPop35_fmovs_fcc3:
case FPop35_fmovs_icc:
case FPop35_fmovs_xcc:
if (!CHECK_RESERVED_ZERO(instn, 18, 18)) {
SET_OP_ILL_REASON(fmovcc_reserved_field_non_zero);
goto illegal_instruction;
}
if (X_FMT4_COND(instn) == cond_n)
goto do_noop;
if (X_FMT4_COND(instn) == cond_a) {
SET_OPv9(fmovs);
goto do_fp_s2s_ds;
}
if (X_FMT4_CC2a(instn)) {
switch( (cc4bit_t)X_FMT4_CC(instn) ) {
case CC4bit_icc: SET_OP_MOVCC_CC(0); break;
case CC4bit_xcc: SET_OP_MOVCC_CC(1); break;
default:
SET_OP_ILL_REASON(fmovcc_illegal_cc_field);
goto illegal_instruction;
}
SET_OPv9(fmovscc);
} else {
SET_OP_MOVCC_CC(X_FMT4_CC(instn));
SET_OPv9(fmovsfcc);
}
SET_OP_MOVCC_COND(X_FMT4_COND(instn));
goto do_fp_s2s_ds;
case FPop35_fmovd_fcc0:
case FPop35_fmovd_fcc1:
case FPop35_fmovd_fcc2:
case FPop35_fmovd_fcc3:
case FPop35_fmovd_icc:
case FPop35_fmovd_xcc:
if (!CHECK_RESERVED_ZERO(instn, 18, 18)) {
SET_OP_ILL_REASON(fmovcc_reserved_field_non_zero);
goto illegal_instruction;
}
if (X_FMT4_COND(instn) == cond_n)
goto do_noop;
if (X_FMT4_COND(instn) == cond_a) {
SET_OPv9(fmovd);
goto do_fp_s2d_dd;
}
if (X_FMT4_CC2a(instn)) {
switch( (cc4bit_t)X_FMT4_CC(instn) ) {
case CC4bit_icc: SET_OP_MOVCC_CC(0); break;
case CC4bit_xcc: SET_OP_MOVCC_CC(1); break;
default:
SET_OP_ILL_REASON(fmovcc_illegal_cc_field);
goto illegal_instruction;
}
SET_OPv9(fmovdcc);
} else {
SET_OP_MOVCC_CC(X_FMT4_CC(instn));
SET_OPv9(fmovdfcc);
}
SET_OP_MOVCC_COND(X_FMT4_COND(instn));
goto do_fp_s2d_dd;
case FPop35_fmovrsz:
SET_OPv9(fmovrs_z);
goto fmovrs_common;
case FPop35_fmovrslez:
SET_OPv9(fmovrs_lez);
goto fmovrs_common;
case FPop35_fmovrslz:
SET_OPv9(fmovrs_lz);
goto fmovrs_common;
case FPop35_fmovrsnz:
SET_OPv9(fmovrs_nz);
goto fmovrs_common;
case FPop35_fmovrsgz:
SET_OPv9(fmovrs_gz);
goto fmovrs_common;
case FPop35_fmovrsgez:
SET_OPv9(fmovrs_gez);
fmovrs_common:
SET_OP_RS1(rs1);
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS2( rs2 );
rd = FP_32_INDX(rd);
SET_OP_FPRD( rd );
goto all_done;
case FPop35_fmovrdz:
SET_OPv9(fmovrd_z);
goto fmovrd_common;
case FPop35_fmovrdlez:
SET_OPv9(fmovrd_lez);
goto fmovrd_common;
case FPop35_fmovrdlz:
SET_OPv9(fmovrd_lz);
goto fmovrd_common;
case FPop35_fmovrdnz:
SET_OPv9(fmovrd_nz);
goto fmovrd_common;
case FPop35_fmovrdgz:
SET_OPv9(fmovrd_gz);
goto fmovrd_common;
case FPop35_fmovrdgez:
SET_OPv9(fmovrd_gez);
fmovrd_common:
SET_OP_RS1(rs1);
RESCALEFPREG(rs2);
SET_OP_FPRS2( rs2 );
RESCALEFPREG(rd);
SET_OP_FPRD( rd );
goto all_done;
default:
goto unimplemented_fpop;
}
case T2o3_gop :
handle_gop:;
/*
* strange but true ... if fp disabled, VIS
* instructions fail because they can't access
* the FP registers ... except the ones that
* don't use them.
* ... otherwise unknown VIS instructions
* fail as illegal instructions.
*/
switch ((T3o3_fp36_opf_t)X_FP_OPF(instn)) {
case VISop36_alignaddr:
FP_DECODE_FPU_ON_CHECK;
SET_OPv9(alignaddr);
goto do_rrr;
case VISop36_alignaddrl:
FP_DECODE_FPU_ON_CHECK;
SET_OPv9(alignaddrl);
goto do_rrr;
case VISop36_faligndata:
SET_OPv9(faligndata);
goto do_fp_s1d_s2d_dd;
case VISop36_fzerod:
SET_OPv9(fzerod);
goto do_fp_s1d;
case VISop36_fzeros:
SET_OPv9(fzeros);
goto do_fp_s1s;
case VISop36_foned:
SET_OPv9(foned);
goto do_fp_s1d;
case VISop36_fones:
SET_OPv9(fones);
goto do_fp_s1s;
case VISop36_fandd:
SET_OPv9(fandd);
goto do_fp_s1d_s2d_dd;
case VISop36_fandnot1d:
SET_OPv9(fandnot1d);
goto do_fp_s1d_s2d_dd;
case VISop36_fandnot1s:
SET_OPv9(fandnot1s);
goto do_fp_s1s_s2s_ds;
case VISop36_fandnot2d:
SET_OPv9(fandnot2d);
goto do_fp_s1d_s2d_dd;
case VISop36_fandnot2s:
SET_OPv9(fandnot2s);
goto do_fp_s1s_s2s_ds;
case VISop36_fands:
SET_OPv9(fands);
goto do_fp_s1s_s2s_ds;
case VISop36_fnandd:
SET_OPv9(fnandd);
goto do_fp_s1d_s2d_dd;
case VISop36_fnands:
SET_OPv9(fnands);
goto do_fp_s1s_s2s_ds;
case VISop36_fnord:
SET_OPv9(fnord);
goto do_fp_s1d_s2d_dd;
case VISop36_fnors:
SET_OPv9(fnors);
goto do_fp_s1s_s2s_ds;
case VISop36_fnot1d:
SET_OPv9(fnotXd);
goto do_fp_s1d_dd;
case VISop36_fnot1s:
SET_OPv9(fnotXs);
goto do_fp_s1s_ds;
case VISop36_fnot2d:
SET_OPv9(fnotXd);
goto do_fp_s2d_dd;
case VISop36_fnot2s:
SET_OPv9(fnotXs);
goto do_fp_s2s_ds;
case VISop36_ford:
SET_OPv9(ford);
goto do_fp_s1d_s2d_dd;
case VISop36_fornot1d:
SET_OPv9(fornot1d);
goto do_fp_s1d_s2d_dd;
case VISop36_fornot1s:
SET_OPv9(fornot1s);
goto do_fp_s1s_s2s_ds;
case VISop36_fornot2d:
SET_OPv9(fornot2d);
goto do_fp_s1d_s2d_dd;
case VISop36_fornot2s:
SET_OPv9(fornot2s);
goto do_fp_s1s_s2s_ds;
case VISop36_fors:
SET_OPv9(fors);
goto do_fp_s1s_s2s_ds;
case VISop36_fsrc1d:
SET_OPv9(fsrcXd);
goto do_fp_s1d_dd;
case VISop36_fsrc1s:
SET_OPv9(fsrcXs);
goto do_fp_s1s_ds;
case VISop36_fsrc2d:
SET_OPv9(fsrcXd);
goto do_fp_s2d_dd;
case VISop36_fsrc2s:
SET_OPv9(fsrcXs);
goto do_fp_s2s_ds;
case VISop36_fxnord:
SET_OPv9(fxnord);
goto do_fp_s1d_s2d_dd;
case VISop36_fxnors:
SET_OPv9(fxnors);
goto do_fp_s1s_s2s_ds;
case VISop36_fxord:
SET_OPv9(fxord);
goto do_fp_s1d_s2d_dd;
case VISop36_fxors:
SET_OPv9(fxors);
goto do_fp_s1s_s2s_ds;
case VISop36_fpadd16:
SET_OPv9(fpadd16);
goto do_fp_s1d_s2d_dd;
case VISop36_fpadd16s:
SET_OPv9(fpadd16s);
goto do_fp_s1s_s2s_ds;
case VISop36_fpadd32:
SET_OPv9(fpadd32);
goto do_fp_s1d_s2d_dd;
case VISop36_fpadd32s:
SET_OPv9(fpadd32s);
goto do_fp_s1s_s2s_ds;
case VISop36_fpsub16:
SET_OPv9(fpsub16);
goto do_fp_s1d_s2d_dd;
case VISop36_fpsub16s:
SET_OPv9(fpsub16s);
goto do_fp_s1s_s2s_ds;
case VISop36_fpsub32:
SET_OPv9(fpsub32);
goto do_fp_s1d_s2d_dd;
case VISop36_fpsub32s:
SET_OPv9(fpsub32s);
goto do_fp_s1s_s2s_ds;
case VISop36_siam:
if (!CHECK_RESERVED_ZERO3(instn, 29, 25, 18, 14, 4, 3)) {
SET_OP_ILL_REASON(visop36_reserved_field_non_zero);
goto illegal_instruction;
}
FP_DECODE_FPU_ON_CHECK;
/* extract mode field */
SET_OP_SIMM16((instn & 7));
SET_OPv9(siam);
goto all_done;
default:
break;
}
goto unimplemented_visop;
case T2o3_flush :
/* This instruction is handled differently wrt niagara and rock.
* Therefore it is moved to cpu_decode_me() functions in rock.c
* and niagara?.c
*/
goto unknown_decode;
case T2o3_unknown_0x19 :
case T2o3_unknown_0x1d :
case T2o3_unknown_0x37 :
case T2o3_unknown_0x3f :
goto unknown_decode;
}
goto unknown_decode;
}
/*
* Principally load/store operation decoding
*/
case Ty_3:
rs1 = X_RS1(instn);
rd = X_RD(instn);
op3c = (T3o3_code_t)X_OP3(instn);
if (X_I(instn)) {
simm = X_SIMM13(instn);
/* register x immediate -> register forms */
switch ( op3c ) {
case T3o3_lduw:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu32);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( ldu32_imm );
goto do_imm;
case T3o3_ldub:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu8);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( ldu8_imm );
goto do_imm;
case T3o3_lduh:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu16);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( ldu16_imm );
goto do_imm;
case T3o3_ldd:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_ldd);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_lddu64);
SET_OPv9(memop_imm);
goto do_memop_imm;
case T3o3_stw:
SET_OP( st32_imm );
goto do_imm;
case T3o3_stb:
SET_OP( st8_imm );
goto do_imm;
case T3o3_sth:
SET_OP( st16_imm );
goto do_imm;
case T3o3_std:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_std);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_stdu64);
SET_OPv9(memop_imm);
goto do_memop_imm;
case T3o3_ldsw:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds32);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( lds32_imm );
goto do_imm;
case T3o3_ldsb:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds8);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( lds8_imm );
goto do_imm;
case T3o3_ldsh:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds16);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( lds16_imm );
goto do_imm;
case T3o3_ldx:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu64);
SET_OPv9(memop_imm);
goto do_memop_imm;
}
SET_OP( ld64_imm );
goto do_imm;
case T3o3_ldstub1:
SET_OP_ASI_OP(MA_ldstub);
SET_OPv9(memop_imm);
goto do_memop_imm;
case T3o3_swapd:
SET_OP_ASI_OP(MA_swap);
SET_OPv9(memop_imm);
goto do_memop_imm;
case T3o3_stx:
SET_OP( st64_imm );
goto do_imm;
case T3o3_lduwa:
SET_OP_ASI_OP(MA_ldu32);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_lduba:
SET_OP_ASI_OP(MA_ldu8);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_lduha:
SET_OP_ASI_OP(MA_ldu16);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldxa:
SET_OP_ASI_OP(MA_ldu64);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldstuba:
SET_OP_ASI_OP(MA_ldstub);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_stwa:
SET_OP_ASI_OP(MA_st32);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_stba:
SET_OP_ASI_OP(MA_st8);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_stha:
SET_OP_ASI_OP(MA_st16);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_stxa:
SET_OP_ASI_OP(MA_st64);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldda:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_ldd);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_lddu64);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_stda:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_std);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_stdu64);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldswa:
SET_OP_ASI_OP(MA_lds32);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldsba:
SET_OP_ASI_OP(MA_lds8);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_ldsha:
SET_OP_ASI_OP(MA_lds16);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
case T3o3_casa:
SET_OP_ASI_OP(MA_cas32);
goto do_cas_imm;
case T3o3_casxa:
SET_OP_ASI_OP(MA_cas64);
do_cas_imm:
if (!CHECK_RESERVED_ZERO(instn, 12, 5)) {
SET_OP_ILL_REASON(cas_reserved_field_non_zero);
goto illegal_instruction;
}
SET_OPv9(asi_reg);
SET_OP_RS1( rs1 );
SET_OP_RS2( X_RS2(instn) );
SET_OP_ASI_RD( rd );
goto all_done;
case T3o3_ldf:
rd = FP_32_INDX(rd);
SET_OP( ldfp32_imm );
goto do_fp_ldst_imm;
case T3o3_lddf:
RESCALEFPREG(rd);
SET_OP( ldfp64_imm );
goto do_fp_ldst_imm;
case T3o3_ldqf:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_stf:
rd = FP_32_INDX(rd);
SET_OP( stfp32_imm );
goto do_fp_ldst_imm;
case T3o3_stdf:
RESCALEFPREG(rd);
SET_OP( stfp64_imm );
goto do_fp_ldst_imm;
case T3o3_stqf:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_ldfsr:
switch (rd) {
case 0:
SET_OPv9( ldfsr_imm );
break;
case 1:
SET_OPv9( ldxfsr_imm );
break;
default:
SET_OP_ILL_REASON(illegal_fsr_specifier);
goto illegal_instruction;
}
goto do_fp_fsr_imm;
case T3o3_stfsr:
switch (rd) {
case 0:
SET_OPv9( stfsr_imm );
break;
case 1:
SET_OPv9( stxfsr_imm );
break;
default:
SET_OP_ILL_REASON(illegal_fsr_specifier);
goto illegal_instruction;
}
goto do_fp_fsr_imm;
case T3o3_ldfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_ldfp32);
SET_OPv9(fp64asi_imm);
goto do_asi_imm;
case T3o3_stfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_stfp32);
SET_OPv9(fp64asi_imm);
goto do_asi_imm;
case T3o3_ldqfa:
case T3o3_stqfa:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_lddfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_ldfp64);
SET_OPv9(fp64asi_imm);
goto do_fp_asi_imm;
case T3o3_stdfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_stfp64);
SET_OPv9(fp64asi_imm);
goto do_fp_asi_imm;
case T3o3_prefetch:
case T3o3_prefetcha:
goto do_noop;
case T3o3_swapa:
SET_OP_ASI_OP(MA_swap);
SET_OPv9(asi_reg_imm);
goto do_asi_imm;
default:
goto unknown_decode;
}
} else {
rs2 = X_RS2(instn);
switch ( op3c ) {
case T3o3_lduw:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu32);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(ldu32_rrr);
goto do_rrr;
case T3o3_ldub:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu8);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(ldu8_rrr);
goto do_rrr;
case T3o3_lduh:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu16);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(ldu16_rrr);
goto do_rrr;
case T3o3_ldd:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_ldd);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_lddu64);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
case T3o3_stw:
SET_OP(st32_rrr);
goto do_rrr;
case T3o3_stb:
SET_OP(st8_rrr);
goto do_rrr;
case T3o3_sth:
SET_OP(st16_rrr);
goto do_rrr;
case T3o3_std:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_std);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_stdu64);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
case T3o3_ldsw:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds32);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(lds32_rrr);
goto do_rrr;
case T3o3_ldsb:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds8);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(lds8_rrr);
goto do_rrr;
case T3o3_ldsh:
if (rd == 0) {
SET_OP_ASI_OP(MA_lds16);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(lds16_rrr);
goto do_rrr;
case T3o3_ldx:
if (rd == 0) {
SET_OP_ASI_OP(MA_ldu64);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
}
SET_OP(ld64_rrr);
goto do_rrr;
case T3o3_ldstub1:
SET_OP_ASI_OP(MA_ldstub);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
case T3o3_swapd:
SET_OP_ASI_OP(MA_swap);
SET_OPv9(memop_rrr);
goto do_memop_rrr;
case T3o3_stx:
SET_OP(st64_rrr);
goto do_rrr;
case T3o3_lduwa:
SET_OP_ASI_OP(MA_ldu32);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_lduba:
SET_OP_ASI_OP(MA_ldu8);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_lduha:
SET_OP_ASI_OP(MA_ldu16);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldstuba:
SET_OP_ASI_OP(MA_ldstub);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldxa:
SET_OP_ASI_OP(MA_ldu64);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_stwa:
SET_OP_ASI_OP(MA_st32);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_stba:
SET_OP_ASI_OP(MA_st8);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_stha:
SET_OP_ASI_OP(MA_st16);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_stxa:
SET_OP_ASI_OP(MA_st64);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldda:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_ldd);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_lddu64);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_stda:
if (rd & 1) {
SET_OP_ILL_REASON(odd_rd_for_std);
goto illegal_instruction;
}
SET_OP_ASI_OP(MA_stdu64);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldswa:
SET_OP_ASI_OP(MA_lds32);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldsba:
SET_OP_ASI_OP(MA_lds8);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_ldsha:
SET_OP_ASI_OP(MA_lds16);
SET_OPv9(asi_num);
goto do_asi_rrr;
case T3o3_casa:
SET_OP_ASI_OP(MA_cas32);
goto do_cas_notimm;
case T3o3_casxa:
SET_OP_ASI_OP(MA_cas64);
do_cas_notimm:
SET_OPv9(asi_num);
SET_OP_RS1( rs1 );
SET_OP_RS2( rs2 );
SET_OP_ASI_RD( rd );
SET_OP_ASI_NUM( X_ASI(instn) );
goto all_done;
case T3o3_ldf:
rd = FP_32_INDX(rd);
SET_OP( ldfp32_rrr );
goto do_fp_ldst_rrr;
case T3o3_lddf:
RESCALEFPREG(rd);
SET_OP( ldfp64_rrr );
goto do_fp_ldst_rrr;
case T3o3_ldqf:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_stf:
rd = FP_32_INDX(rd);
SET_OP( stfp32_rrr );
goto do_fp_ldst_rrr;
case T3o3_stdf:
RESCALEFPREG(rd);
SET_OP( stfp64_rrr );
goto do_fp_ldst_rrr;
case T3o3_stqf:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_ldfsr:
switch (rd) {
case 0:
SET_OPv9( ldfsr_rr );
break;
case 1:
SET_OPv9( ldxfsr_rr );
break;
default:
SET_OP_ILL_REASON(illegal_fsr_specifier);
goto illegal_instruction;
}
goto do_fp_fsr_rr;
case T3o3_stfsr:
switch (rd) {
case 0:
SET_OPv9( stfsr_rr );
break;
case 1:
SET_OPv9( stxfsr_rr );
break;
default:
SET_OP_ILL_REASON(illegal_fsr_specifier);
goto illegal_instruction;
}
goto do_fp_fsr_rr;
case T3o3_ldfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_ldfp32);
SET_OPv9(fp64asi_rrr);
goto do_asi_rrr;
case T3o3_stfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_stfp32);
SET_OPv9(fp64asi_rrr);
goto do_asi_rrr;
case T3o3_ldqfa:
case T3o3_stqfa:
SET_OP_ILL_REASON(illegal_instruction);
goto illegal_instruction;
case T3o3_lddfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_ldfp64);
SET_OPv9(fp64asi_rrr);
goto do_fp_asi_rrr;
case T3o3_stdfa:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_OP(MA_stfp64);
SET_OPv9(fp64asi_rrr);
goto do_fp_asi_rrr;
case T3o3_prefetch:
case T3o3_prefetcha:
goto do_noop;
case T3o3_swapa:
SET_OP_ASI_OP(MA_swap);
SET_OPv9(asi_num);
goto do_asi_rrr;
default:
goto unknown_decode; /* FIXME */
}
}
}
goto unknown_decode; /* Could be CPU specific instruction. */
unknown_decode:; /* We can reach here if either the decoder screwed up (Even illegal */
/* instructions should have a proper decode case) or we encountered */
/* a CPU specific instruction which the SparcV9 decoder doesn't */
/* know about. We check to see which of those two cases happened in */
/* the illegal instruction handling code below. */
SET_OP_ILL_REASON(unknown_instruction);
goto illegal_instruction;
/*
* Sparc allows us to not decode FP ops when there is no floating point
* unit. So in this case we deliver a fp_disabled trap ...
*/
#ifdef FP_DECODE_DISABLED
fp_disabled:;
#endif /* FP_DECODE_DISABLED */
unimplemented_fpop:;
SET_OPv9(fp_unimplemented_instruction);
goto all_done;
/* FP version of unknown_decode. */
unknown_fp_decode:;
SET_OP_ILL_REASON(unknown_fp_instruction);
SET_OPv9(fp_unimplemented_instruction);
goto try_proc_specific;
#ifdef PROCESSOR_SUPPORTS_QUADFP
invalid_fp_register:
SET_OPv9(fp_invalidreg_instruction);
goto all_done;
#endif
unimplemented_visop:
SET_OP_ILL_REASON(unimplemented_visop);
goto illegal_instruction;
illegal_instruction:; /* we reach here if the decoder detected an illegal instruction*/
/* for example - a bpcc instrn with cc0=0 & cc1=1 */
/* Or if we have run into a CPU specific instruction which the */
/* SparcV9 decoder doesn't know about. */
SET_OPv9(illegal_instruction);
try_proc_specific:;
/*
* Before declaring the instruction illegal or unknown, we check the CPU
* specific instruction decoder.
* Since some FP instructions want to return 'unimplemented'
* instead of 'illegal', preserve whatever has been set until
* we get a positive decode from the proc-specific decode.
*/
p_exec_funcp = sp->config_procp->proc_typep->cpu_decode_me(sp, xcip, instn);
if (p_exec_funcp != NULL) {
/*
* CPU specific instruction decoder was successful.
*/
exec_funcp = p_exec_funcp;
goto all_done;
}
DBGILLINST( lprintf(sp->gid, "decoded illegal instruction 0x%x "
"(@PC = 0x%llx) : %s\n", instn, sp->pc,
v9_illegal_reason_str[(int)xcip->di.ill_reason]););
DBGDECODE(
if (xcip->di.ill_reason == unknown_instruction) {
fprintf(stderr, "Error! : unable to decode instruction "
"(PC = 0x%llx in mode %s) 0x%x\n", sp->pc,
sparcv9_state_name[((sparcv9_cpu_t *)
(sp->specificp))->state], instn);
abort(); /* shouldnt get here*/
}
);
goto all_done;
/*
* Setup and tests for decoded floating point instructions
*/
do_fp_s1d:
FP_DECODE_FPU_ON_CHECK;
RESCALEFPREG(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s1s:
FP_DECODE_FPU_ON_CHECK;
rd = FP_32_INDX(rd);
SET_OP_FPRD( rd );
goto all_done;
#ifdef PROCESSOR_SUPPORTS_QUADFP
do_fp_s1q_s2q_dq:
FP_DECODE_FPU_ON_CHECK;
if (rs1 & 0x2) goto invalid_fp_register;
do_fp_s2q_dq:
FP_DECODE_FPU_ON_CHECK;
if (rs2 & 0x2) goto invalid_fp_register;
do_fp_s1d_s2d_dq:
FP_DECODE_FPU_ON_CHECK;
if (rd & 0x2) goto invalid_fp_register;
/* Quad not supported yet - FIXME */
goto unimplemented_fpop;
#endif
do_fp_s1d_s2d_dd:
FP_DECODE_FPU_ON_CHECK;
RESCALEFPREG(rs1);
RESCALEFPREG(rs2);
RESCALEFPREG(rd);
SET_OP_FPRS1( rs1 );
SET_OP_FPRS2( rs2 );
SET_OP_FPRD( rd );
goto all_done;
do_fp_s1s_s2s_dd:
FP_DECODE_FPU_ON_CHECK;
rs1 = FP_32_INDX(rs1);
SET_OP_FPRS1( rs1 );
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS2( rs2 );
RESCALEFPREG(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s1s_s2s_ds:
FP_DECODE_FPU_ON_CHECK;
rs1 = FP_32_INDX(rs1);
SET_OP_FPRS1( rs1 );
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS2( rs2 );
rd = FP_32_INDX(rd);
SET_OP_FPRD( rd );
goto all_done;
/*
* For FP ops with a single operand (e.g. abs) SPARC encodes into rs2
* I move it into rs1 for my pre-decoded form.
*/
do_fp_s1d_dd:
rs2 = rs1;
do_fp_s2d_dd:
FP_DECODE_FPU_ON_CHECK;
RESCALEFPREG(rs2);
SET_OP_FPRS1( rs2 );
RESCALEFPREG(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s2d_ds:
FP_DECODE_FPU_ON_CHECK;
RESCALEFPREG(rs2);
SET_OP_FPRS1( rs2 );
rd = FP_32_INDX(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s1s_ds:
rs2 = rs1;
do_fp_s2s_ds:
FP_DECODE_FPU_ON_CHECK;
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS1( rs2 );
rd = FP_32_INDX(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s2s_dd:
FP_DECODE_FPU_ON_CHECK;
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS1( rs2 );
RESCALEFPREG(rd);
SET_OP_FPRD( rd );
goto all_done;
do_fp_s1d_s2d_cmp:
FP_DECODE_FPU_ON_CHECK;
RESCALEFPREG(rs1);
SET_OP_FPRS1( rs1 );
RESCALEFPREG(rs2);
SET_OP_FPRS2( rs2 );
goto all_done;
do_fp_s1s_s2s_cmp:
FP_DECODE_FPU_ON_CHECK;
rs1 = FP_32_INDX(rs1);
SET_OP_FPRS1( rs1 );
rs2 = FP_32_INDX(rs2);
SET_OP_FPRS2( rs2 );
goto all_done;
do_fp_ldst_imm:
FP_DECODE_FPU_ON_CHECK;
SET_OP_FPRD(rd);
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
goto all_done;
do_fp_fsr_imm:
FP_DECODE_FPU_ON_CHECK;
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
goto all_done;
do_fp_ldst_rrr:
SET_OP_FPRD(rd);
do_fp_fsr_rr:
FP_DECODE_FPU_ON_CHECK;
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
goto all_done;
do_fp_asi_imm:
FP_DECODE_FPU_ON_CHECK;
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
RESCALEFPREG(rd);
SET_OP_ASI_FPRD(rd);
goto all_done;
do_fp_asi_rrr:
FP_DECODE_FPU_ON_CHECK;
SET_OP_ASI_NUM(X_ASI(instn));
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
RESCALEFPREG(rd);
SET_OP_ASI_FPRD(rd);
goto all_done;
/*
* Setup for decoded instructions
*/
do_asi_rrr:
SET_OP_ASI_NUM(X_ASI(instn));
do_memop_rrr:
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
SET_OP_ASI_RD(rd);
goto all_done;
do_memop_imm:
do_asi_imm:
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
SET_OP_ASI_RD(rd);
goto all_done;
do_rrr:
SET_OP_RD(rd);
SET_OP_RS1(rs1);
SET_OP_RS2(rs2);
goto all_done;
do_imm:
SET_OP_RD(rd);
SET_OP_RS1(rs1);
SET_OP_SIMM16(simm);
goto all_done;
do_move_simm:
SET_OP( move_simm );
SET_OP_RD(rd);
SET_OP_SIMM32(simm);
goto all_done;
do_move_reg:
SET_OP( move_reg );
SET_OP_RD(rd);
SET_OP_RS1(rs1);
goto all_done;
do_zero_reg:
SET_OP( zero_reg );
SET_OP_RD(rd);
goto all_done;
do_noop:
SET_OP( noop );
goto all_done;
all_done:
/*
* FIXME: This ugly hook is so that we can instruction trace for
* debugging without penalising the main execution loop.
* Basically, if debugging is turned on we leverage the same
* behaviour as for breakpoint support and after dumping the
* pre-execution state, prevent installation of the exec_func.
*
* Why is this a fixme ? This will ultimately done by a trampoline
* for each instruction we wish to trace .. and will be done on a per
* simcpu basis rather than globally. Until then we are left with this.
*/
DBGELMIN(
sparcv9_trace_output(sp, instn);
on_bp = true;
);
/*
* prevent installation of any instruction
* that matched a live instruction
*/
if (on_bp) {
xcip->exec_funcp = sp->decodemep;
} else {
/* cache for next time around */
xcip->exec_funcp = exec_funcp;
}
/* execute the instruction on behalf of the x-cache */
exec_funcp(sp, xcip);
}