mirror of
https://github.com/phabrics/Run-Sun3-SunOS-4.1.1.git
synced 2026-04-29 11:02:59 -04:00
1001 lines
38 KiB
C
1001 lines
38 KiB
C
/* automatically generated by sparc-vis-auto.sh, do not edit! */
|
|
_TME_RCSID("$Id: sparc-vis-auto.sh,v 1.4 2010/02/20 22:01:40 fredette Exp $");
|
|
|
|
/* this handles VIS instructions: */
|
|
void
|
|
tme_sparc_vis(struct tme_sparc *ic)
|
|
{
|
|
unsigned int opf;
|
|
unsigned int fpreg_rd_number_encoded;
|
|
const struct tme_float *fpreg_rs1;
|
|
const struct tme_float *fpreg_rs2;
|
|
unsigned int fpreg_rd_format;
|
|
unsigned int fpreg_rd_number;
|
|
struct tme_float fpreg_rd;
|
|
tme_uint64_t value_fpreg_rs1;
|
|
tme_uint64_t value_fpreg_rs2;
|
|
unsigned int compare_result;
|
|
unsigned int reg_rd;
|
|
unsigned int alignaddr_off;
|
|
|
|
TME_SPARC_INSN_FPU;
|
|
|
|
/* extract the opf field: */
|
|
opf = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0x1ff << 5));
|
|
|
|
/* extract the encoded rd: */
|
|
fpreg_rd_number_encoded = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
|
|
#ifdef _TME_SPARC_RECODE_VERIFY
|
|
/* clear the rd buffer: */
|
|
memset(&fpreg_rd, 0, sizeof(fpreg_rd));
|
|
#endif /* _TME_SPARC_RECODE_VERIFY */
|
|
|
|
/* dispatch on the opf field: */
|
|
switch (opf) {
|
|
#define _TME_SPARC_FPU_FORMAT_RS1(format) fpreg_rs1 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS1, (format))
|
|
#define _TME_SPARC_FPU_FORMAT_RS2(format) fpreg_rs2 = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RS2, (format))
|
|
#define _TME_SPARC_FPU_FORMAT_RD(format) do { fpreg_rd_format = (format) | TME_IEEE754_FPREG_FORMAT_BUILTIN; fpreg_rd_number = tme_sparc_fpu_fpreg_decode(ic, fpreg_rd_number_encoded, fpreg_rd_format); } while (/* CONSTCOND */ 0)
|
|
|
|
case 32: /* 000100000 FCMPLE16: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
<= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
<= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (16 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
<= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
<= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (48 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 34: /* 000100010 FCMPNE16: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
!= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
!= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (16 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
!= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
!= (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (48 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 36: /* 000100100 FCMPLE32: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
<= (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
<= (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 38: /* 000100110 FCMPNE32: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
!= (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
!= (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 40: /* 000101000 FCMPGT16: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
> (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
> (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (16 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
> (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
> (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (48 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 42: /* 000101010 FCMPEQ16: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
== (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
== (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (16 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
== (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
if (((tme_uint16_t) value_fpreg_rs1)
|
|
== (tme_uint16_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (48 / 16));
|
|
}
|
|
value_fpreg_rs1 >>= 16;
|
|
value_fpreg_rs2 >>= 16;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 44: /* 000101100 FCMPGT32: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
> (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
> (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 46: /* 000101110 FCMPEQ32: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_fpreg_rs1 = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
value_fpreg_rs2 = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
compare_result = 0;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
== (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (0 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
if (((tme_uint32_t) value_fpreg_rs1)
|
|
== (tme_uint32_t) value_fpreg_rs2) {
|
|
compare_result += (1 << (32 / 32));
|
|
}
|
|
value_fpreg_rs1 >>= 32;
|
|
value_fpreg_rs2 >>= 32;
|
|
reg_rd = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);
|
|
TME_SPARC_REG_INDEX(ic, reg_rd);
|
|
ic->tme_sparc_ireg_uint64(reg_rd) = compare_result;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
case 72: /* 001001000 FALIGNDATA: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double = fpreg_rs1->tme_float_value_ieee754_double;
|
|
alignaddr_off = TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_vis_gsr, TME_SPARC_VIS_GSR_ALIGNADDR_OFF);
|
|
if (alignaddr_off) {
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint
|
|
= ((fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint
|
|
<< (8 * alignaddr_off))
|
|
+ (fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint
|
|
>> (64 - (8 * alignaddr_off))));
|
|
}
|
|
break;
|
|
|
|
case 96: /* 001100000 (0000) FZERO: */
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = 0;
|
|
break;
|
|
|
|
case 97: /* 001100001 (0000) FZEROS: */
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = 0;
|
|
break;
|
|
|
|
case 98: /* 001100010 (0001) FNOR: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = ~(fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint | fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 99: /* 001100011 (0001) FNORS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = ~(fpreg_rs1->tme_float_value_ieee754_single | fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 100: /* 001100100 (0010) FANDNOT2: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint & ~fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 101: /* 001100101 (0010) FANDNOT2S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs1->tme_float_value_ieee754_single & ~fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 102: /* 001100110 (0011) FNOT2: */
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = ~fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
break;
|
|
|
|
case 103: /* 001100111 (0011) FNOT2S: */
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = ~fpreg_rs2->tme_float_value_ieee754_single;
|
|
break;
|
|
|
|
case 104: /* 001101000 (0100) FANDNOT1: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint & ~fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 105: /* 001101001 (0100) FANDNOT1S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs2->tme_float_value_ieee754_single & ~fpreg_rs1->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 106: /* 001101010 (0101) FNOT1: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = ~fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
break;
|
|
|
|
case 107: /* 001101011 (0101) FNOT1S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = ~fpreg_rs1->tme_float_value_ieee754_single;
|
|
break;
|
|
|
|
case 108: /* 001101100 (0110) FXOR: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint ^ fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 109: /* 001101101 (0110) FXORS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs1->tme_float_value_ieee754_single ^ fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 110: /* 001101110 (0111) FNAND: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = ~(fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint & fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 111: /* 001101111 (0111) FNANDS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = ~(fpreg_rs1->tme_float_value_ieee754_single & fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 112: /* 001110000 (1000) FAND: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint & fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 113: /* 001110001 (1000) FANDS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs1->tme_float_value_ieee754_single & fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 114: /* 001110010 (1001) FXNOR: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = ~(fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint ^ fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 115: /* 001110011 (1001) FXNORS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = ~(fpreg_rs1->tme_float_value_ieee754_single ^ fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 116: /* 001110100 (1010) FSRC1: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint;
|
|
break;
|
|
|
|
case 117: /* 001110101 (1010) FSRC1S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = fpreg_rs1->tme_float_value_ieee754_single;
|
|
break;
|
|
|
|
case 118: /* 001110110 (1011) FORNOT2: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint | ~fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 119: /* 001110111 (1011) FORNOT2S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs1->tme_float_value_ieee754_single | ~fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 120: /* 001111000 (1100) FSRC2: */
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint;
|
|
break;
|
|
|
|
case 121: /* 001111001 (1100) FSRC2S: */
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = fpreg_rs2->tme_float_value_ieee754_single;
|
|
break;
|
|
|
|
case 122: /* 001111010 (1101) FORNOT1: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint | ~fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 123: /* 001111011 (1101) FORNOT1S: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs2->tme_float_value_ieee754_single | ~fpreg_rs1->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 124: /* 001111100 (1110) FOR: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (fpreg_rs1->tme_float_value_ieee754_double.tme_value64_uint | fpreg_rs2->tme_float_value_ieee754_double.tme_value64_uint);
|
|
break;
|
|
|
|
case 125: /* 001111101 (1110) FORS: */
|
|
_TME_SPARC_FPU_FORMAT_RS1(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RS2(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (fpreg_rs1->tme_float_value_ieee754_single | fpreg_rs2->tme_float_value_ieee754_single);
|
|
break;
|
|
|
|
case 126: /* 001111110 (1111) FONE: */
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
|
|
fpreg_rd.tme_float_value_ieee754_double.tme_value64_uint = (0 - (tme_uint64_t) 1);
|
|
break;
|
|
|
|
case 127: /* 001111111 (1111) FONES: */
|
|
_TME_SPARC_FPU_FORMAT_RD(TME_IEEE754_FPREG_FORMAT_SINGLE);
|
|
_TME_SPARC_FPU_BEGIN;
|
|
fpreg_rd.tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
|
|
fpreg_rd.tme_float_value_ieee754_single = (0 - (tme_uint32_t) 1);
|
|
break;
|
|
|
|
default:
|
|
_TME_SPARC_FPU_UNIMPL;
|
|
fpreg_rd_format = TME_IEEE754_FPREG_FORMAT_NULL;
|
|
fpreg_rd_number = 0;
|
|
break;
|
|
|
|
#undef _TME_SPARC_FPU_FORMAT_RS1
|
|
#undef _TME_SPARC_FPU_FORMAT_RS2
|
|
#undef _TME_SPARC_FPU_FORMAT_RD
|
|
}
|
|
|
|
/* store any destination: */
|
|
if (fpreg_rd_format != TME_IEEE754_FPREG_FORMAT_NULL) {
|
|
tme_sparc_fpu_fpreg_format(ic, fpreg_rd_number, fpreg_rd_format);
|
|
ic->tme_sparc_fpu_fpregs[fpreg_rd_number] = fpreg_rd;
|
|
TME_SPARC_FPU_DIRTY(ic, fpreg_rd_number);
|
|
}
|
|
|
|
}
|
|
|
|
/* the sparc64 cycle handler for stdfa ASI_PST*: */
|
|
static void
|
|
_tme_sparc64_vis_ls_cycle_pstd(struct tme_sparc *ic, struct tme_sparc_ls *ls)
|
|
{
|
|
unsigned int reg_rs2;
|
|
tme_uint32_t mask_raw;
|
|
unsigned int asi;
|
|
tme_uint32_t mask_0_31;
|
|
tme_uint32_t mask_32_63;
|
|
tme_uint64_t mask;
|
|
const struct tme_float *fpreg_rd;
|
|
tme_uint64_t value_written;
|
|
const struct tme_sparc_tlb *tlb;
|
|
tme_uint64_t address;
|
|
tme_shared tme_uint8_t *emulator_off;
|
|
tme_shared tme_uint64_t *memory;
|
|
tme_uint64_t value_read;
|
|
tme_uint64_t value_cmp;
|
|
|
|
/* decode rs2: */
|
|
reg_rs2 = TME_FIELD_MASK_EXTRACTU(ic->_tme_sparc_insn, TME_SPARC_FORMAT3_MASK_RS2);
|
|
TME_SPARC_REG_INDEX(ic, reg_rs2);
|
|
|
|
/* get the raw mask: */
|
|
mask_raw = ic->tme_sparc_ireg_uint64(reg_rs2);
|
|
|
|
/* get the ASI: */
|
|
asi
|
|
= (TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)
|
|
& ~(TME_SPARC64_ASI_FLAG_SECONDARY
|
|
| TME_SPARC64_ASI_FLAG_LITTLE));
|
|
|
|
/* assume that this is ASI_PST32*: */
|
|
mask_0_31 = 0 - (mask_raw & TME_BIT(0));
|
|
mask_raw >>= 1;
|
|
mask_32_63 = 0 - (mask_raw & TME_BIT(0));
|
|
mask_raw >>= 1;
|
|
|
|
/* if this is ASI_PST16*: */
|
|
if (asi == TME_SPARC_VIS_ASI_PST16) {
|
|
|
|
/* convert the ASI_PST32* mask into bits 0..31 of the ASI_PST16* mask: */
|
|
mask_0_31
|
|
= ((mask_0_31 & (((tme_uint32_t) 0xffff) << 0))
|
|
+ (mask_32_63 & (((tme_uint32_t) 0xffff) << 16)));
|
|
|
|
/* make bits 32..63 of the ASI_PST16* mask: */
|
|
mask_32_63
|
|
= (((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xffff) << 0))
|
|
+ ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xffff) << 16)));
|
|
}
|
|
|
|
/* otherwise, if this is ASI_PST8*: */
|
|
else if (asi == TME_SPARC_VIS_ASI_PST8) {
|
|
|
|
/* convert the ASI_PST32* mask into bits 0..15 of the ASI_PST8*
|
|
mask, and make bits 16..31: */
|
|
mask_0_31
|
|
= ((mask_0_31 & (((tme_uint32_t) 0xff) << 0))
|
|
+ (mask_32_63 & (((tme_uint32_t) 0xff) << 8))
|
|
+ ((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xff) << 16))
|
|
+ ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xff) << 24)));
|
|
|
|
/* make bits 32..63 of the ASI_PST8* mask: */
|
|
mask_raw >>= 2;
|
|
mask_32_63
|
|
= (((0 - (mask_raw & TME_BIT(0))) & (((tme_uint32_t) 0xff) << 0))
|
|
+ ((0 - (mask_raw & TME_BIT(1))) & (((tme_uint32_t) 0xff) << 8))
|
|
+ ((0 - (mask_raw & TME_BIT(2))) & (((tme_uint32_t) 0xff) << 16))
|
|
+ ((0 - (mask_raw & TME_BIT(3))) & (((tme_uint32_t) 0xff) << 24)));
|
|
}
|
|
|
|
/* make the full mask: */
|
|
mask = 0;
|
|
mask |= (((tme_uint64_t) mask_32_63) << 32);
|
|
mask |= mask_0_31;
|
|
|
|
/* get the value to store from the double-precision fp register: */
|
|
fpreg_rd = tme_sparc_fpu_fpreg_read(ic, TME_SPARC_FORMAT3_MASK_RD, TME_IEEE754_FPREG_FORMAT_DOUBLE);
|
|
value_written = fpreg_rd->tme_float_value_ieee754_double.tme_value64_uint;
|
|
|
|
/* get the TLB entry: */
|
|
tlb = ls->tme_sparc_ls_tlb;
|
|
|
|
/* swap the mask and the value to store: */
|
|
if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) {
|
|
value_written = tme_htole_u64(value_written);
|
|
mask = tme_htole_u64(mask);
|
|
}
|
|
else {
|
|
value_written = tme_htobe_u64(value_written);
|
|
mask = tme_htobe_u64(mask);
|
|
}
|
|
|
|
/* get the current address: */
|
|
address = ls->tme_sparc_ls_address64;
|
|
|
|
/* if this is the first transfer, and the TLB entry allows fast
|
|
transfer of all of the addresses: */
|
|
emulator_off = tlb->tme_sparc_tlb_emulator_off_write;
|
|
if (__tme_predict_true(ls->tme_sparc_ls_state == 0
|
|
&& ((tme_bus_addr64_t) tlb->tme_sparc_tlb_addr_last) >= (address + sizeof(tme_uint64_t) - 1)
|
|
&& emulator_off != TME_EMULATOR_OFF_UNDEF
|
|
&& emulator_off == tlb->tme_sparc_tlb_emulator_off_read)) {
|
|
|
|
/* make the pointer to the memory to store: */
|
|
memory = (tme_shared tme_uint64_t *) (emulator_off + address);
|
|
|
|
/* loop until we can do the atomic partial store: */
|
|
value_read = tme_memory_bus_read64(memory,
|
|
tlb->tme_sparc_tlb_bus_rwlock,
|
|
sizeof(tme_uint64_t),
|
|
sizeof(tme_uint64_t));
|
|
do {
|
|
|
|
/* make the value to write: */
|
|
value_written
|
|
= ((value_written & mask)
|
|
+ (value_read & ~mask));
|
|
|
|
/* try an atomic compare-and-exchange: */
|
|
value_cmp = value_read;
|
|
value_read
|
|
= tme_memory_atomic_cx64(memory,
|
|
value_cmp,
|
|
value_written,
|
|
tlb->tme_sparc_tlb_bus_rwlock,
|
|
sizeof(tme_uint64_t));
|
|
|
|
/* loop while the atomic compare-and-exchange failed: */
|
|
} while (value_read != value_cmp);
|
|
|
|
/* we finished this transfer: */
|
|
ls->tme_sparc_ls_size = 0;
|
|
return;
|
|
}
|
|
|
|
/* otherwise, we have to do a slow transfer: */
|
|
ls->tme_sparc_ls_buffer_offset = 0;
|
|
/* XXX WRITEME: */
|
|
abort();
|
|
}
|
|
|
|
/* the sparc64 ASI handler for ASI_PST*: */
|
|
void
|
|
tme_sparc64_vis_ls_asi_pst(struct tme_sparc *ic, struct tme_sparc_ls *ls)
|
|
{
|
|
tme_uint32_t insn;
|
|
unsigned int reg_rs1;
|
|
tme_uint64_t address_first;
|
|
|
|
/* NB: this checks for various traps in priority order: */
|
|
|
|
/* the only faults that may have been set so far are an alignment
|
|
fault, which is probably wrong because the address checked was
|
|
(rs1 + rs2), instead of just rs1, and any ldd/std rd-odd fault.
|
|
we will override both faults: */
|
|
assert ((ls->tme_sparc_ls_faults
|
|
| TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
|
|
| TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)
|
|
== (TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
|
|
| TME_SPARC_LS_FAULT_LDD_STD_RD_ODD));
|
|
|
|
/* we need to do the complete transfer: */
|
|
ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
|
|
ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_SLOW_CYCLES;
|
|
ls->tme_sparc_ls_state = 0;
|
|
|
|
/* get the instruction: */
|
|
insn = ic->_tme_sparc_insn;
|
|
|
|
/* NB: the exception for a non-stdfa opcode appears to be explicitly
|
|
prioritized above an illegal_instruction trap for an immediate
|
|
instruction: */
|
|
|
|
/* if this is an stdfa: */
|
|
if (__tme_predict_true((insn
|
|
& (0x3f << 19))
|
|
== (0x37 << 19))) {
|
|
|
|
/* set the slow cycle function: */
|
|
assert (ls->tme_sparc_ls_size == sizeof(tme_uint64_t));
|
|
ls->tme_sparc_ls_cycle = _tme_sparc64_vis_ls_cycle_pstd;
|
|
}
|
|
|
|
/* any other instruction is illegal: */
|
|
else {
|
|
ls->tme_sparc_ls_faults = ic->tme_sparc_vis_ls_fault_illegal;
|
|
return;
|
|
}
|
|
|
|
/* immediate instruction forms are illegal: */
|
|
if (__tme_predict_false(insn & TME_BIT(13))) {
|
|
tme_sparc_tlb_unbusy(ls->tme_sparc_ls_tlb);
|
|
TME_SPARC_INSN_ILL(ic);
|
|
}
|
|
|
|
/* the stdfa instruction handler must have already checked that the
|
|
FPU is enabled: */
|
|
assert (!TME_SPARC_FPU_IS_DISABLED(ic));
|
|
|
|
/* decode rs1: */
|
|
reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1);
|
|
TME_SPARC_REG_INDEX(ic, reg_rs1);
|
|
|
|
/* get the address: */
|
|
address_first = ic->tme_sparc_ireg_uint64(reg_rs1);
|
|
ls->tme_sparc_ls_address64 = address_first;
|
|
|
|
/* the address must be aligned: */
|
|
if (__tme_predict_false((((tme_uint32_t) address_first)
|
|
& (ls->tme_sparc_ls_size - 1)) != 0)) {
|
|
ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
|
|
return;
|
|
}
|
|
|
|
/* the stdfa instruction handler must have already checked that the
|
|
FPU mode is not exception_pending: */
|
|
assert (ic->tme_sparc_fpu_mode != TME_SPARC_FPU_MODE_EXCEPTION_PENDING);
|
|
}
|
|
|
|
/* the sparc64 cycle handler for lddfa and stdfa ASI_FL*: */
|
|
static void
|
|
_tme_sparc64_vis_ls_cycle_fld(struct tme_sparc *ic, struct tme_sparc_ls *ls)
|
|
{
|
|
tme_uint64_t value;
|
|
unsigned int buffer_offset;
|
|
|
|
/* if this is an stdfa: */
|
|
if (ic->_tme_sparc_insn & (4 << 19)) {
|
|
|
|
/* the actual store cycles will be done directly: */
|
|
ls->tme_sparc_ls_cycle = tme_sparc64_store;
|
|
|
|
/* initialize the memory buffer with the value to store: */
|
|
value = *ls->tme_sparc_ls_rd64;
|
|
}
|
|
|
|
/* otherwise, this is an lddfa: */
|
|
else {
|
|
|
|
/* the actual load cycles will be done directly: */
|
|
ls->tme_sparc_ls_cycle = tme_sparc64_load;
|
|
|
|
/* initialize the memory buffer with zero: */
|
|
value = 0;
|
|
}
|
|
|
|
/* initialize the memory buffer: */
|
|
if (ls->tme_sparc_ls_lsinfo & TME_SPARC_LSINFO_ENDIAN_LITTLE) {
|
|
value = tme_htole_u64(value);
|
|
buffer_offset = 0;
|
|
}
|
|
else {
|
|
value = tme_htobe_u64(value);
|
|
buffer_offset = sizeof(value) - ls->tme_sparc_ls_size;
|
|
}
|
|
ic->tme_sparc_memory_buffer.tme_sparc_memory_buffer64s[0] = value;
|
|
ls->tme_sparc_ls_buffer_offset = buffer_offset;
|
|
|
|
/* do the (first) actual cycle: */
|
|
(*ls->tme_sparc_ls_cycle)(ic, ls);
|
|
}
|
|
|
|
/* the sparc64 ASI handler for ASI_FL*: */
|
|
void
|
|
tme_sparc64_vis_ls_asi_fl(struct tme_sparc *ic, struct tme_sparc_ls *ls)
|
|
{
|
|
tme_uint32_t insn;
|
|
|
|
/* NB: this checks for various traps in priority order: */
|
|
|
|
/* the only faults that may have been set so far are an alignment
|
|
fault, which is probably wrong because the size used for the
|
|
alignment check was wrong, and any ldd/std rd-odd fault. we will
|
|
override both faults: */
|
|
assert ((ls->tme_sparc_ls_faults
|
|
| TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
|
|
| TME_SPARC_LS_FAULT_LDD_STD_RD_ODD)
|
|
== (TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED
|
|
| TME_SPARC_LS_FAULT_LDD_STD_RD_ODD));
|
|
|
|
/* get the instruction: */
|
|
insn = ic->_tme_sparc_insn;
|
|
|
|
/* we need to do the complete transfer: */
|
|
ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_NONE;
|
|
ls->tme_sparc_ls_lsinfo |= TME_SPARC_LSINFO_SLOW_CYCLES;
|
|
ls->tme_sparc_ls_state = 0;
|
|
|
|
/* set the cycle size: */
|
|
#if (TME_SPARC_VIS_ASI_FL16 & (TME_SPARC_VIS_ASI_FL16 - 1)) != TME_SPARC_VIS_ASI_FL8
|
|
#error "TME_SPARC_VIS_ASI_FL values changed"
|
|
#endif
|
|
ls->tme_sparc_ls_size
|
|
= (sizeof(tme_uint8_t)
|
|
+ ((TME_SPARC_ASI_MASK_WHICH(ls->tme_sparc_ls_asi_mask)
|
|
/ (TME_SPARC_VIS_ASI_FL16
|
|
^ TME_SPARC_VIS_ASI_FL8))
|
|
& 1));
|
|
|
|
/* if this is an stdfa or an lddfa: */
|
|
if (__tme_predict_true((insn
|
|
& (0x3b << 19))
|
|
== (0x33 << 19))) {
|
|
|
|
/* set the slow cycle function: */
|
|
ls->tme_sparc_ls_cycle = _tme_sparc64_vis_ls_cycle_fld;
|
|
|
|
/* the stdfa or lddfa instruction handler must have already
|
|
checked that the FPU is enabled: */
|
|
assert (!TME_SPARC_FPU_IS_DISABLED(ic));
|
|
}
|
|
|
|
/* any other instruction is illegal: */
|
|
/* XXX FIXME - is this correct? the UltraSPARC User's Manual
|
|
doesn't document data_access_exception for an illegal opcode: */
|
|
else {
|
|
ls->tme_sparc_ls_faults = ic->tme_sparc_vis_ls_fault_illegal;
|
|
return;
|
|
}
|
|
|
|
/* the address must be aligned: */
|
|
if (__tme_predict_false((((tme_uint32_t) ls->tme_sparc_ls_address64)
|
|
& (ls->tme_sparc_ls_size - 1)) != 0)) {
|
|
ls->tme_sparc_ls_faults = TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED;
|
|
return;
|
|
}
|
|
|
|
/* the stdfa or lddfa instruction handler must have already checked
|
|
that the FPU mode is execute: */
|
|
assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXECUTE);
|
|
}
|
|
|
|
/* the sparc64 VIS alternate ASI misalignment function: */
|
|
tme_uint32_t
|
|
tme_sparc64_vis_ls_asi_misaligned(struct tme_sparc *ic,
|
|
tme_uint32_t misaligned)
|
|
{
|
|
tme_uint32_t insn;
|
|
tme_uint32_t asi;
|
|
tme_uint32_t asi_base;
|
|
unsigned int reg_rs1;
|
|
|
|
/* get the instruction: */
|
|
insn = TME_SPARC_INSN;
|
|
|
|
/* get the ASI, assuming that the i bit is zero: */
|
|
asi = TME_FIELD_MASK_EXTRACTU(insn, (0xff << 5));
|
|
|
|
/* if the i bit is one, use the ASI register: */
|
|
if (insn & TME_BIT(13)) {
|
|
asi = ic->tme_sparc64_ireg_asi;
|
|
}
|
|
|
|
/* make a base version of the ASI, with the secondary and
|
|
little-endian flags cleared: */
|
|
asi_base = (asi & ~(TME_SPARC64_ASI_FLAG_SECONDARY | TME_SPARC64_ASI_FLAG_LITTLE));
|
|
|
|
/* ASI_FL8* requires 8-bit alignment: */
|
|
if (asi_base == TME_SPARC_VIS_ASI_FL8) {
|
|
misaligned %= sizeof(tme_uint8_t);
|
|
}
|
|
|
|
/* ASI_FL16* requires 16-bit alignment: */
|
|
else if (asi_base == TME_SPARC_VIS_ASI_FL16) {
|
|
misaligned %= sizeof(tme_uint16_t);
|
|
}
|
|
|
|
/* if this is an ASI_PST*: */
|
|
else if (asi_base == TME_SPARC_VIS_ASI_PST8
|
|
|| asi_base == TME_SPARC_VIS_ASI_PST16
|
|
|| asi_base == TME_SPARC_VIS_ASI_PST32) {
|
|
|
|
/* decode rs1: */
|
|
reg_rs1 = TME_FIELD_MASK_EXTRACTU(insn, TME_SPARC_FORMAT3_MASK_RS1);
|
|
TME_SPARC_REG_INDEX(ic, reg_rs1);
|
|
|
|
/* if this is not a register mode stdfa: */
|
|
if (__tme_predict_false((insn
|
|
& ((0x3f << 19)
|
|
+ TME_BIT(13)))
|
|
!= (0x37 << 19))) {
|
|
|
|
/* start a slow load/store, which will call the ASI handler,
|
|
which will cause the appropriate fault: */
|
|
tme_sparc64_ls(ic,
|
|
ic->tme_sparc_ireg_uint64(reg_rs1),
|
|
(tme_uint64_t *) NULL, /* _rd */
|
|
(TME_SPARC_LSINFO_SIZE(1)
|
|
| TME_SPARC_LSINFO_ASI(asi)
|
|
| TME_SPARC_LSINFO_A));
|
|
assert(FALSE);
|
|
}
|
|
|
|
/* get the least-significant 32 bits of the address: */
|
|
misaligned = ic->tme_sparc_ireg_uint64(reg_rs1);
|
|
|
|
/* ASI_PST* require 64-bit alignment, which the stdfa instruction
|
|
handler is already checking: */
|
|
}
|
|
|
|
/* return a possibly updated misalignment: */
|
|
return (misaligned);
|
|
}
|