Beispiel #1
0
void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    ORB orig_orb, orb;
    uint64_t addr;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        return;
    }
    if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
        s390_cpu_virt_mem_handle_exc(cpu, ra);
        return;
    }
    copy_orb_from_guest(&orb, &orig_orb);
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_orb_valid(&orb)) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        return;
    }
    trace_ioinst_sch_id("ssch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (!sch || !css_subch_visible(sch)) {
        setcc(cpu, 3);
        return;
    }
    setcc(cpu, css_do_ssch(sch, &orb));
}
Beispiel #2
0
/* DA E9 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOMPP(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          BX_CPU_THIS_PTR the_i387.FPU_pop();
          BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_t status =
      FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

  int rc = floatx80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(1), status);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     BX_CPU_THIS_PTR the_i387.FPU_pop();
     BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
Beispiel #3
0
static void
fptan(void)
{
    FPU_REG *st_new_ptr;
    int     q;
    char    arg_sign = FPU_st0_ptr->sign;

    if (STACK_OVERFLOW) {
        stack_overflow();
        return;
    }
    switch (FPU_st0_tag) {
    case TW_Valid:

#ifdef DENORM_OPERAND
        if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
            return;
#endif				/* DENORM_OPERAND */

        FPU_st0_ptr->sign = SIGN_POS;
        if ((q = trig_arg(FPU_st0_ptr)) != -1) {
            if (q & 1)
                reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION);

            poly_tan(FPU_st0_ptr, FPU_st0_ptr);

            FPU_st0_ptr->sign = (q & 1) ^ arg_sign;

            if (FPU_st0_ptr->exp <= EXP_UNDER)
                arith_underflow(FPU_st0_ptr);

            push();
            reg_move(&CONST_1, FPU_st0_ptr);
            setcc(0);
        } else {
            /* Operand is out of range */
            setcc(SW_C2);
            FPU_st0_ptr->sign = arg_sign;	/* restore st(0) */
            return;
        }
        break;
    case TW_Infinity:
        /* Operand is out of range */
        setcc(SW_C2);
        FPU_st0_ptr->sign = arg_sign;	/* restore st(0) */
        return;
    case TW_Zero:
        push();
        reg_move(&CONST_1, FPU_st0_ptr);
        setcc(0);
        break;
    default:
        single_arg_error();
        break;
    }
}
Beispiel #4
0
static void ftst_(void)
{
  switch (FPU_st0_tag)
    {
    case TW_Zero:
      setcc(SW_C3);
      break;
    case TW_Valid:
      if (FPU_st0_ptr->sign == SIGN_POS)
        setcc(0);
      else
        setcc(SW_C0);
      break;
    case TW_NaN:
      setcc(SW_C2);    /* Operand is not comparable */ 
      EXCEPTION(EX_Invalid);
      break;
    case TW_Infinity:
      if (FPU_st0_ptr->sign == SIGN_POS)
        setcc(0);
      else
        setcc(SW_C3);
      /*      setcc(SW_C0|SW_C2|SW_C3); */
      EXCEPTION(EX_Invalid);
      break;
    case TW_Empty:
      setcc(SW_C0|SW_C2|SW_C3);
      EXCEPTION(EX_StackUnder);
      break;
    default:
      setcc(SW_C2);    /* Operand is not comparable */ 
      EXCEPTION(EX_INTERNAL|0x14);
      break;
    }
}
static int compare_u_st_st(int nr)
{
	int f = 0, c;
	FPU_REG *st_ptr;

	if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
		setcc(SW_C3 | SW_C2 | SW_C0);
		/*             */
		EXCEPTION(EX_StackUnder);
		return !(control_word & CW_Invalid);
	}

	st_ptr = &st(nr);
	c = compare(st_ptr, FPU_gettagi(nr));
	if (c & COMP_NaN) {
		setcc(SW_C3 | SW_C2 | SW_C0);
		if (c & COMP_SNaN) {	/*                                    
                                            */
			EXCEPTION(EX_Invalid);
			return !(control_word & CW_Invalid);
		}
		return 0;
	} else
		switch (c & 7) {
		case COMP_A_lt_B:
			f = SW_C0;
			break;
		case COMP_A_eq_B:
			f = SW_C3;
			break;
		case COMP_A_gt_B:
			f = 0;
			break;
		case COMP_No_Comp:
			f = SW_C3 | SW_C2 | SW_C0;
			break;
#ifdef PARANOID
		default:
			EXCEPTION(EX_INTERNAL | 0x123);
			f = SW_C3 | SW_C2 | SW_C0;
			break;
#endif /*          */
		}
	setcc(f);
	if (c & COMP_Denormal) {
		return denormal_operand() < 0;
	}
	return 0;
}
Beispiel #6
0
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb)
{
    CRW *crw;
    uint64_t addr;
    int cc;
    hwaddr len = sizeof(*crw);
    CPUS390XState *env = &cpu->env;

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    crw = s390_cpu_physical_memory_map(env, addr, &len, 1);
    if (!crw || len != sizeof(*crw)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        goto out;
    }
    cc = css_do_stcrw(crw);
    /* 0 - crw stored, 1 - zeroes stored */
    setcc(cpu, cc);

out:
    s390_cpu_physical_memory_unmap(env, crw, len, 1);
}
Beispiel #7
0
void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
{
    CRW crw;
    uint64_t addr;
    int cc;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        return;
    }

    cc = css_do_stcrw(&crw);
    /* 0 - crw stored, 1 - zeroes stored */

    if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
        setcc(cpu, cc);
    } else {
        if (cc == 0) {
            /* Write failed: requeue CRW since STCRW is suppressing */
            css_undo_stcrw(&crw);
        }
        s390_cpu_virt_mem_handle_exc(cpu, ra);
    }
}
Beispiel #8
0
static void
fxam(void)
{
	int     c = 0;
	switch (FPU_st0_tag) {
	case TW_Empty:
		c = SW_C3 | SW_C0;
		break;
	case TW_Zero:
		c = SW_C3;
		break;
	case TW_Valid:
		/* This will need to be changed if TW_Denormal is ever used. */
		if (FPU_st0_ptr->exp <= EXP_UNDER)
			c = SW_C2 | SW_C3;	/* Denormal */
		else
			c = SW_C3;
		break;
	case TW_NaN:
		c = SW_C0;
		break;
	case TW_Infinity:
		c = SW_C2 | SW_C0;
		break;
	}
	if (FPU_st0_ptr->sign == SIGN_NEG)
		c |= SW_C1;
	setcc(c);
}
Beispiel #9
0
static void fxam(void)
{
  int c=0;
  switch (FPU_st0_tag)
    {
    case TW_Empty:
      c = SW_C3|SW_C0;
      break;
    case TW_Zero:
      c = SW_C3;
      break;
    case TW_Valid:
      if (FPU_st0_ptr->sigh & 0x80000000)
        c = SW_C2;
      else
        c = SW_C3|SW_C2;
      break;
    case TW_NaN:
      c = SW_C0;
      break;
    case TW_Infinity:
      c = SW_C2|SW_C0;
      break;
    }
  if (FPU_st0_ptr->sign == SIGN_NEG)
    c |= SW_C1;
  setcc(c);
}
Beispiel #10
0
static void fxam(FPU_REG *st0_ptr, u_char st0tag)
{
    int c = 0;
    switch (st0tag) {
    case TAG_Empty:
        c = SW_C3 | SW_C0;
        break;
    case TAG_Zero:
        c = SW_C3;
        break;
    case TAG_Valid:
        c = SW_C2;
        break;
    case TAG_Special:
        switch (FPU_Special(st0_ptr)) {
        case TW_Denormal:
            c = SW_C2 | SW_C3;	/* Denormal */
            break;
        case TW_NaN:
            /* We also use NaN for unsupported types. */
            if ((st0_ptr->sigh & 0x80000000)
                    && (exponent(st0_ptr) == EXP_OVER))
                c = SW_C0;
            break;
        case TW_Infinity:
            c = SW_C2 | SW_C0;
            break;
        }
    }
    if (getsign(st0_ptr) == SIGN_NEG)
        c |= SW_C1;
    setcc(c);
}
Beispiel #11
0
void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    int ret = -ENODEV;
    int cc;

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        program_interrupt(&cpu->env, PGM_OPERAND, 2);
        return;
    }
    trace_ioinst_sch_id("hsch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_hsch(sch);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }
    setcc(cpu, cc);
}
Beispiel #12
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_DOUBLE_REAL(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  int pop_stack = i->nnn() & 1, rc;

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
  float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i));

  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_t status =
      FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

  floatx80 a = BX_READ_FPU_REG(0);

  if (floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(load_reg)) {
    rc = float_relation_unordered;
    float_raise(status, float_flag_invalid);
  }
  else {
    rc = floatx80_compare(a, float64_to_floatx80(load_reg, status), status);
  }
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
         BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
Beispiel #13
0
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    uint64_t addr;
    int cc;
    SCHIB schib;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        /*
         * As operand exceptions have a lower priority than access exceptions,
         * we check whether the memory area is writeable (injecting the
         * access execption if it is not) first.
         */
        if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
            program_interrupt(env, PGM_OPERAND, 2);
        }
        return;
    }
    trace_ioinst_sch_id("stsch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch) {
        if (css_subch_visible(sch)) {
            css_do_stsch(sch, &schib);
            cc = 0;
        } else {
            /* Indicate no more subchannels in this css/ss */
            cc = 3;
        }
    } else {
        if (css_schid_final(m, cssid, ssid, schid)) {
            cc = 3; /* No more subchannels in this css/ss */
        } else {
            /* Store an empty schib. */
            memset(&schib, 0, sizeof(schib));
            cc = 0;
        }
    }
    if (cc != 3) {
        if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
                                    sizeof(schib)) != 0) {
            return;
        }
    } else {
        /* Access exceptions have a higher priority than cc3 */
        if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
            return;
        }
    }
    setcc(cpu, cc);
}
Beispiel #14
0
void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        s390_program_interrupt(&cpu->env, PGM_OPERAND, 4, ra);
        return;
    }
    trace_ioinst_sch_id("hsch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (!sch || !css_subch_visible(sch)) {
        setcc(cpu, 3);
        return;
    }
    setcc(cpu, css_do_hsch(sch));
}
Beispiel #15
0
void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    ORB orig_orb, orb;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
        return;
    }
    copy_orb_from_guest(&orb, &orig_orb);
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_orb_valid(&orb)) {
        program_interrupt(env, PGM_OPERAND, 2);
        return;
    }
    trace_ioinst_sch_id("ssch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_ssch(sch, &orb);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case -EFAULT:
        /*
         * TODO:
         * I'm wondering whether there is something better
         * to do for us here (like setting some device or
         * subchannel status).
         */
        program_interrupt(env, PGM_ADDRESSING, 4);
        return;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }
    setcc(cpu, cc);
}
Beispiel #16
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FICOM_WORD_INTEGER(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);

  int pop_stack = i->nnn() & 1;

  RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
  Bit16s load_reg = (Bit16s) read_virtual_word(i->seg(), RMAddr(i));

  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_t status =
      FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

  int rc = floatx80_compare(BX_READ_FPU_REG(0),
                      int32_to_floatx80((Bit32s)(load_reg)), status);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
         BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
Beispiel #17
0
void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    ORB *orig_orb, orb;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    hwaddr len = sizeof(*orig_orb);
    CPUS390XState *env = &cpu->env;

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0);
    if (!orig_orb || len != sizeof(*orig_orb)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        goto out;
    }
    copy_orb_from_guest(&orb, orig_orb);
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_orb_valid(&orb)) {
        program_interrupt(env, PGM_OPERAND, 2);
        goto out;
    }
    trace_ioinst_sch_id("ssch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_ssch(sch, &orb);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }
    setcc(cpu, cc);

out:
    s390_cpu_physical_memory_unmap(env, orig_orb, len, 0);
}
Beispiel #18
0
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_STi(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  int pop_stack = i->nnn() & 1;
  // handle special case of FSTP opcode @ 0xDE 0xD0..D7
  if (i->b1() == 0xde)
    pop_stack = 1;

  clear_C1();

  if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm()))
  {
      FPU_exception(FPU_EX_Stack_Underflow);
      setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);

      if(BX_CPU_THIS_PTR the_i387.is_IA_masked())
      {
          if (pop_stack)
              BX_CPU_THIS_PTR the_i387.FPU_pop();
      }
      BX_NEXT_INSTR(i);
  }

  float_status_t status =
     FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

  int rc = floatx80_compare(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status);
  setcc(status_word_flags_fpu_compare(rc));

  if (! FPU_exception(status.float_exception_flags)) {
     if (pop_stack)
        BX_CPU_THIS_PTR the_i387.FPU_pop();
  }

  BX_NEXT_INSTR(i);
}
Beispiel #19
0
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    uint64_t addr;
    int cc;
    SCHIB *schib;
    hwaddr len = sizeof(*schib);
    CPUS390XState *env = &cpu->env;

    addr = decode_basedisp_s(env, ipb);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    schib = s390_cpu_physical_memory_map(env, addr, &len, 1);
    if (!schib || len != sizeof(*schib)) {
        program_interrupt(env, PGM_ADDRESSING, 2);
        goto out;
    }

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        program_interrupt(env, PGM_OPERAND, 2);
        goto out;
    }
    trace_ioinst_sch_id("stsch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch) {
        if (css_subch_visible(sch)) {
            css_do_stsch(sch, schib);
            cc = 0;
        } else {
            /* Indicate no more subchannels in this css/ss */
            cc = 3;
        }
    } else {
        if (css_schid_final(m, cssid, ssid, schid)) {
            cc = 3; /* No more subchannels in this css/ss */
        } else {
            /* Store an empty schib. */
            memset(schib, 0, sizeof(*schib));
            cc = 0;
        }
    }
    setcc(cpu, cc);

out:
    s390_cpu_physical_memory_unmap(env, schib, len, 1);
}
Beispiel #20
0
/* D9 E4 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FTST(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  clear_C1();

  if (IS_TAG_EMPTY(0)) {
     FPU_exception(FPU_EX_Stack_Underflow);
     setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3);
  }
  else {
     extern const floatx80 Const_Z;

     float_status_t status =
        FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word());

     int rc = floatx80_compare(BX_READ_FPU_REG(0), Const_Z, status);
     setcc(status_word_flags_fpu_compare(rc));
     FPU_exception(status.float_exception_flags);
  }

  BX_NEXT_INSTR(i);
}
Beispiel #21
0
int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
{
    CPUS390XState *env = &cpu->env;
    int cssid, ssid, schid, m;
    SubchDev *sch;
    IRB irb;
    uint64_t addr;
    int cc, irb_len;
    uint8_t ar;

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        s390_program_interrupt(env, PGM_OPERAND, 4, ra);
        return -EIO;
    }
    trace_ioinst_sch_id("tsch", cssid, ssid, schid);
    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
        return -EIO;
    }

    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
    } else {
        cc = 3;
    }
    /* 0 - status pending, 1 - not status pending, 3 - not operational */
    if (cc != 3) {
        if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
            s390_cpu_virt_mem_handle_exc(cpu, ra);
            return -EFAULT;
        }
        css_do_tsch_update_subch(sch);
    } else {
        irb_len = sizeof(irb) - sizeof(irb.emw);
        /* Access exceptions have a higher priority than cc3 */
        if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
            s390_cpu_virt_mem_handle_exc(cpu, ra);
            return -EFAULT;
        }
    }

    setcc(cpu, cc);
    return 0;
}
Beispiel #22
0
void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    SCHIB schib;
    uint64_t addr;
    int ret = -ENODEV;
    int cc;
    CPUS390XState *env = &cpu->env;
    uint8_t ar;

    addr = decode_basedisp_s(env, ipb, &ar);
    if (addr & 3) {
        program_interrupt(env, PGM_SPECIFICATION, 2);
        return;
    }
    if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
        return;
    }
    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
        !ioinst_schib_valid(&schib)) {
        program_interrupt(env, PGM_OPERAND, 2);
        return;
    }
    trace_ioinst_sch_id("msch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_msch(sch, &schib);
    }
    switch (ret) {
    case -ENODEV:
        cc = 3;
        break;
    case -EBUSY:
        cc = 2;
        break;
    case 0:
        cc = 0;
        break;
    default:
        cc = 1;
        break;
    }
    setcc(cpu, cc);
}
Beispiel #23
0
static void
ftst_(void)
{
	switch (FPU_st0_tag) {
		case TW_Zero:
		setcc(SW_C3);
		break;
	case TW_Valid:

#ifdef DENORM_OPERAND
		if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))
			return;
#endif				/* DENORM_OPERAND */

		if (FPU_st0_ptr->sign == SIGN_POS)
			setcc(0);
		else
			setcc(SW_C0);
		break;
	case TW_NaN:
		setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
		EXCEPTION(EX_Invalid);
		break;
	case TW_Infinity:
		if (FPU_st0_ptr->sign == SIGN_POS)
			setcc(0);
		else
			setcc(SW_C0);
		EXCEPTION(EX_Invalid);
		break;
	case TW_Empty:
		setcc(SW_C0 | SW_C2 | SW_C3);
		EXCEPTION(EX_StackUnder);
		break;
	default:
		setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
		EXCEPTION(EX_INTERNAL | 0x14);
		break;
	}
}
Beispiel #24
0
void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1)
{
    int cssid, ssid, schid, m;
    SubchDev *sch;
    int ret = -ENODEV;
    int cc;

    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
        program_interrupt(&cpu->env, PGM_OPERAND, 2);
        return;
    }
    trace_ioinst_sch_id("csch", cssid, ssid, schid);
    sch = css_find_subch(m, cssid, ssid, schid);
    if (sch && css_subch_visible(sch)) {
        ret = css_do_csch(sch);
    }
    if (ret == -ENODEV) {
        cc = 3;
    } else {
        cc = 0;
    }
    setcc(cpu, cc);
}
int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
{
	int f = 0, c;

	c = compare(loaded_data, loaded_tag);

	if (c & COMP_NaN) {
		EXCEPTION(EX_Invalid);
		f = SW_C3 | SW_C2 | SW_C0;
	} else
		switch (c & 7) {
		case COMP_A_lt_B:
			f = SW_C0;
			break;
		case COMP_A_eq_B:
			f = SW_C3;
			break;
		case COMP_A_gt_B:
			f = 0;
			break;
		case COMP_No_Comp:
			f = SW_C3 | SW_C2 | SW_C0;
			break;
#ifdef PARANOID
		default:
			EXCEPTION(EX_INTERNAL | 0x121);
			f = SW_C3 | SW_C2 | SW_C0;
			break;
#endif /*          */
		}
	setcc(f);
	if (c & COMP_Denormal) {
		return denormal_operand() < 0;
	}
	return 0;
}
Beispiel #26
0
rmove()
{
	register struct node *p;
	register int r;
	register  r1, flt;

	for (p=first.forw; p!=0; p = p->forw) {
	flt = 0;
	switch (p->op) {

	case MOVF:
	case MOVFO:
	case MOVOF:
		flt = NREG;

	case MOV:
		if (p->subop==BYTE)
			goto dble;
		dualop(p);
		if ((r = findrand(regs[RT1], flt)) >= 0) {
			if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR
			   && p->forw->op!=SXT
			   && p->forw->op!=CFCC) {
				p->forw->back = p->back;
				p->back->forw = p->forw;
				redunm++;
				continue;
			}
		}
		if (equstr(regs[RT1], "$0")) {
			p->op = CLR;
			strcpy(regs[RT1], regs[RT2]);
			regs[RT2][0] = 0;
			p->code = copy(1, regs[RT1]);
			goto sngl;
		}
		repladdr(p, 0, flt);
		r = isreg(regs[RT1]);
		r1 = isreg(regs[RT2]);
		dest(regs[RT2], flt);
		if (r >= 0)
			if (r1 >= 0)
				savereg(r1+flt, regs[r+flt]);
			else
				savereg(r+flt, regs[RT2]);
		else
			if (r1 >= 0)
				savereg(r1+flt, regs[RT1]);
			else
				setcon(regs[RT1], regs[RT2]);
		source(regs[RT1]);
		setcc(regs[RT2]);
		continue;

	case ADDF:
	case SUBF:
	case DIVF:
	case MULF:
		flt = NREG;
		goto dble;

	case ADD:
	case SUB:
	case BIC:
	case BIS:
	case MUL:
	case DIV:
	case ASH:
	dble:
		dualop(p);
		if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) {
			p->op = CLR;
			strcpy(regs[RT1], regs[RT2]);
			regs[RT2][0] = 0;
			p->code = copy(1, regs[RT1]);
			goto sngl;
		}
		if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) {
			if (p->forw->op!=CBR) {
				p->back->forw = p->forw;
				p->forw->back = p->back;
				continue;
			}
		}
		repladdr(p, 0, flt);
		source(regs[RT1]);
		dest(regs[RT2], flt);
		if (p->op==DIV && (r = isreg(regs[RT2])>=0))
			regs[r+1][0] = 0;
		ccloc[0] = 0;
		continue;

	case CLRF:
	case NEGF:
		flt = NREG;

	case CLR:
	case COM:
	case INC:
	case DEC:
	case NEG:
	case ASR:
	case ASL:
	case SXT:
		singop(p);
	sngl:
		dest(regs[RT1], flt);
		if (p->op==CLR && flt==0)
			if ((r = isreg(regs[RT1])) >= 0)
				savereg(r, "$0");
			else
				setcon("$0", regs[RT1]);
		ccloc[0] = 0;
		continue;

	case TSTF:
		flt = NREG;

	case TST:
		singop(p);
		repladdr(p, 0, flt);
		source(regs[RT1]);
		if (equstr(regs[RT1], ccloc)) {
			p->back->forw = p->forw;
			p->forw->back = p->back;
			p = p->back;
			nrtst++;
			nchange++;
		}
		continue;

	case CMPF:
		flt = NREG;

	case CMP:
	case BIT:
		dualop(p);
		source(regs[RT1]);
		source(regs[RT2]);
		if(p->op==BIT) {
			if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) {
				p->op = TST;
				strcpy(regs[RT1], regs[RT2]);
				regs[RT2][0] = 0;
				p->code = copy(1, regs[RT1]);
				nchange++;
				nsaddr++;
			} else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) {
				p->op = TST;
				regs[RT2][0] = 0;
				p->code = copy(1, regs[RT1]);
				nchange++;
				nsaddr++;
			}
			if (equstr(regs[RT1], "$0")) {
				p->op = TST;
				regs[RT2][0] = 0;
				p->code = copy(1, regs[RT1]);
				nchange++;
				nsaddr++;
			} else if (equstr(regs[RT2], "$0")) {
				p->op = TST;
				strcpy(regs[RT1], regs[RT2]);
				regs[RT2][0] = 0;
				p->code = copy(1, regs[RT1]);
				nchange++;
				nsaddr++;
			}
		}
		repladdr(p, 1, flt);
		ccloc[0] = 0;
		continue;

	case CBR:
		if (p->back->op==TST || p->back->op==CMP) {
			if (p->back->op==TST) {
				singop(p->back);
				savereg(RT2, "$0");
			} else
				dualop(p->back);
			r = compare(p->subop, findcon(RT1), findcon(RT2));
			if (r==0) {
				p->back->back->forw = p->forw;
				p->forw->back = p->back->back;
				decref(p->ref);
				p = p->back->back;
				nchange++;
			} else if (r>0) {
				p->op = JBR;
				p->subop = 0;
				p->back->back->forw = p;
				p->back = p->back->back;
				p = p->back;
				nchange++;
			}
		}
	case CFCC:
		ccloc[0] = 0;
		continue;

	case JBR:
		redunbr(p);

	default:
		clearreg();
	}
	}
}
Beispiel #27
0
static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
{
	FPU_REG *st_new_ptr;
	int q;
	u_char arg_sign = getsign(st0_ptr);

	
	if (st0_tag == TAG_Empty) {
		FPU_stack_underflow();	
		if (control_word & CW_Invalid) {
			st_new_ptr = &st(-1);
			push();
			FPU_stack_underflow();	
		}
		return;
	}

	if (STACK_OVERFLOW) {
		FPU_stack_overflow();
		return;
	}

	if (st0_tag == TAG_Valid) {
		if (exponent(st0_ptr) > -40) {
			if ((q = trig_arg(st0_ptr, 0)) == -1) {
				
				return;
			}

			poly_tan(st0_ptr);
			setsign(st0_ptr, (q & 1) ^ (arg_sign != 0));
			set_precision_flag_up();	
		} else {
			
			

		      denormal_arg:

			FPU_to_exp16(st0_ptr, st0_ptr);

			st0_tag =
			    FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
			FPU_settag0(st0_tag);
		}
		push();
		FPU_copy_to_reg0(&CONST_1, TAG_Valid);
		return;
	}

	if (st0_tag == TAG_Zero) {
		push();
		FPU_copy_to_reg0(&CONST_1, TAG_Valid);
		setcc(0);
		return;
	}

	if (st0_tag == TAG_Special)
		st0_tag = FPU_Special(st0_ptr);

	if (st0_tag == TW_Denormal) {
		if (denormal_operand() < 0)
			return;

		goto denormal_arg;
	}

	if (st0_tag == TW_Infinity) {
		
		if (arith_invalid(0) >= 0) {
			st_new_ptr = &st(-1);
			push();
			arith_invalid(0);
		}
		return;
	}

	single_arg_2_error(st0_ptr, st0_tag);
}
Beispiel #28
0
rmove()
{
	register struct node *p;
	register char *cp;
	register int r;
	int r1, flt;

	for (p=first.forw; p!=0; p = p->forw) {
	if (debug) {
		for (r=0; r<2*NREG; r++)
			if (regs[r][0])
				printf("%d: %s\n", r, regs[r]);
		printf("-\n");
	}
	flt = 0;
	switch (p->op) {

	case MOVF:
	case MOVFO:
	case MOVOF:
		flt = NREG;

	case MOV:
		dualop(p);
		if ((r = findrand(regs[RT1], flt)) >= 0) {
			if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR) {
				p->forw->back = p->back;
				p->back->forw = p->forw;
				redunm++;
				continue;
			}
		}
		repladdr(p, 0, flt);
		r = isreg(regs[RT1]);
		r1 = isreg(regs[RT2]);
		dest(regs[RT2], flt);
		if (r >= 0)
			if (r1 >= 0)
				savereg(r1+flt, regs[r+flt]);
			else
				savereg(r+flt, regs[RT2]);
		else
			if (r1 >= 0)
				savereg(r1+flt, regs[RT1]);
			else
				setcon(regs[RT1], regs[RT2]);
		source(regs[RT1]);
		setcc(regs[RT2]);
		continue;

	case ADDF:
	case SUBF:
	case DIVF:
	case MULF:
		flt = NREG;

	case ADD:
	case SUB:
	case BIC:
	case BIS:
	case MUL:
	case DIV:
	case ASH:
		dualop(p);
		repladdr(p, 0, flt);
		source(regs[RT1]);
		dest(regs[RT2], flt);
		if (p->op==DIV && (r = isreg(regs[RT2])>=0))
			regs[r+1][0] = 0;
		ccloc[0] = 0;
		continue;

	case CLRF:
	case NEGF:
		flt = NREG;

	case CLR:
	case COM:
	case INC:
	case DEC:
	case NEG:
	case ASR:
	case ASL:
	case SXT:
		singop(p);
		dest(regs[RT1], flt);
		if (p->op==CLR && flt==0)
			if ((r = isreg(regs[RT1])) >= 0)
				savereg(r, "$0");
			else
				setcon("$0", regs[RT1]);
		setcc(regs[RT1]);
		continue;

	case TSTF:
		flt = NREG;

	case TST:
		singop(p);
		repladdr(p, 0, flt);
		source(regs[RT1]);
		if (equstr(regs[RT1], ccloc)) {
			p->back->forw = p->forw;
			p->forw->back = p->back;
			p = p->back;
			nrtst++;
			nchange++;
		}
		continue;

	case CMPF:
		flt = NREG;

	case CMP:
	case BIT:
		dualop(p);
		source(regs[RT1]);
		source(regs[RT2]);
		repladdr(p, 1, flt);
		ccloc[0] = 0;
		continue;

	case CBR:
	case CFCC:
		ccloc[0] = 0;
		continue;

	case JBR:
		redunbr(p);

	default:
		clearreg();
	}
	}
}
Beispiel #29
0
static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
{
    switch (st0tag) {
    case TAG_Zero:
        setcc(SW_C3);
        break;
    case TAG_Valid:
        if (getsign(st0_ptr) == SIGN_POS)
            setcc(0);
        else
            setcc(SW_C0);
        break;
    case TAG_Special:
        switch (FPU_Special(st0_ptr)) {
        case TW_Denormal:
            if (getsign(st0_ptr) == SIGN_POS)
                setcc(0);
            else
                setcc(SW_C0);
            if (denormal_operand() < 0) {
#ifdef PECULIAR_486
                /* This is weird! */
                if (getsign(st0_ptr) == SIGN_POS)
                    setcc(SW_C3);
#endif /* PECULIAR_486 */
                return;
            }
            break;
        case TW_NaN:
            setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
            EXCEPTION(EX_Invalid);
            break;
        case TW_Infinity:
            if (getsign(st0_ptr) == SIGN_POS)
                setcc(0);
            else
                setcc(SW_C0);
            break;
        default:
            setcc(SW_C0 | SW_C2 | SW_C3);	/* Operand is not comparable */
            EXCEPTION(EX_INTERNAL | 0x14);
            break;
        }
        break;
    case TAG_Empty:
        setcc(SW_C0 | SW_C2 | SW_C3);
        EXCEPTION(EX_StackUnder);
        break;
    }
}
Beispiel #30
0
/* D9 E5 */
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FXAM(bxInstruction_c *i)
{
  BX_CPU_THIS_PTR prepareFPU(i);
  BX_CPU_THIS_PTR FPU_update_last_instruction(i);

  floatx80 reg = BX_READ_FPU_REG(0);
  int sign = floatx80_sign(reg);

  /*
   * Examine the contents of the ST(0) register and sets the condition
   * code flags C0, C2 and C3 in the FPU status word to indicate the
   * class of value or number in the register.
   */

  if (IS_TAG_EMPTY(0))
  {
      setcc(FPU_SW_C3|FPU_SW_C1|FPU_SW_C0);
  }
  else
  {
      float_class_t aClass = floatx80_class(reg);

      switch(aClass)
      {
        case float_zero:
           setcc(FPU_SW_C3|FPU_SW_C1);
           break;

        case float_NaN:
           // unsupported handled as NaNs
           if (floatx80_is_unsupported(reg)) {
               setcc(FPU_SW_C1);
           } else {
               setcc(FPU_SW_C1|FPU_SW_C0);
           }
           break;

        case float_negative_inf:
        case float_positive_inf:
           setcc(FPU_SW_C2|FPU_SW_C1|FPU_SW_C0);
           break;

        case float_denormal:
           setcc(FPU_SW_C3|FPU_SW_C2|FPU_SW_C1);
           break;

        case float_normalized:
           setcc(FPU_SW_C2|FPU_SW_C1);
           break;
      }
  }

  /*
   * The C1 flag is set to the sign of the value in ST(0), regardless
   * of whether the register is empty or full.
   */
  if (! sign)
    clear_C1();

  BX_NEXT_INSTR(i);
}