/* 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);
}
