Esempio n. 1
0
void tlcs870_device::do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    CLR g.b           1110 1ggg           0100 1bbb                        Z  *  -  -    3
	*/
	m_cycles = 3;

	uint8_t val = get_reg8(opbyte0 & 0x7);
	const uint8_t bitpos = opbyte1 & 0x7;

	const int bitused = (1 << bitpos);

	if (val & bitused) // Zero flag gets set based on original value of bit?
	{
		clear_ZF();
		clear_JF(); // 'Z' (so copy Z flag?)
	}
	else
	{
		set_ZF();
		set_JF();  // 'Z'
	}

	val &= ~bitused;

	set_reg8(opbyte0 & 0x7, val);
}
Esempio n. 2
0
void tlcs870_device::do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    CPL g.b           1110 1ggg           1100 0bbb                        Z  *  -  -    3
	*/
	m_cycles = 3;

	uint8_t val = get_reg8(opbyte0 & 0x7);
	const uint8_t bitpos = opbyte1 & 0x7;

	const int bitused = (1 << bitpos);

	uint8_t bit = val & bitused;

	if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
	{
		clear_ZF();
		clear_JF();

		val &= ~bitused;
	}
	else  // if the bit isn't set, set the zero/jump flags and set the bit
	{
		set_ZF();
		set_JF();

		val |= bitused;
	}

	set_reg8(opbyte0 & 0x7, val);
}
Esempio n. 3
0
void tlcs870_device::do_CPL_inpp_indirectbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    CPL (DE).g        1110 1ggg           1001 0010                        Z  *  -  -    5
	    CPL (HL).g        1110 1ggg           1001 0011                        Z  *  -  -    5
	*/
	m_cycles = 5;

	const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
	const uint8_t bitused = 1 << bitpos;
	const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
	m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports
	uint8_t val = RM8(addr);

	uint8_t bit = val & bitused;

	if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
	{
		clear_ZF();
		clear_JF();

		val &= ~bitused;
	}
	else  // if the bit isn't set, set the zero/jump flags and set the bit
	{
		set_ZF();
		set_JF();

		val |= bitused;
	}

	WM8(addr, val);
}
Esempio n. 4
0
void tlcs870_device::do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    CLR (DE).g        1110 1ggg           1000 1010                        Z  *  -  -    5
	    CLR (HL).g        1110 1ggg           1000 1011                        Z  *  -  -    5
	*/
	m_cycles = 5;

	const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
	const uint8_t bitused = 1 << bitpos;
	const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
	m_read_input_port = 0; // reads output latch, not actual ports if accessing memory mapped ports
	uint8_t val = RM8(addr);

	if (val & bitused) // Zero flag gets set based on original value of bit?
	{
		clear_ZF();
		clear_JF(); // 'Z' (so copy Z flag?)
	}
	else
	{
		set_ZF();
		set_JF();  // 'Z'
	}

	val &= ~bitused;

	WM8(addr, val);
}
Esempio n. 5
0
void tlcs870_device::do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    SET (DE).g        1110 1ggg           1000 0010                        Z  *  -  -    5
	    SET (HL).g        1110 1ggg           1000 0011                        Z  *  -  -    5
	*/
	m_cycles = 5;

	const uint8_t bitpos = get_reg8(opbyte0 & 7) & 0x7;
	const uint8_t bitused = 1 << bitpos;
	const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
	uint8_t val = RM8(addr);

	if (val & bitused) // Zero flag gets set based on original value of bit?
	{
		clear_ZF();
		clear_JF(); // 'Z' (so copy Z flag?)
	}
	else
	{
		set_ZF();
		set_JF();  // 'Z'
	}

	val |= bitused;

	WM8(addr, val);
}
Esempio n. 6
0
  void
bx_cpu_c::CMPXCHG_EbGb(BxInstruction_t *i)
{
#if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
  Bit8u op2_8, op1_8, diff_8;


  /* op1_8 is a register or memory reference */
  if (i->mod == 0xc0) {
    op1_8 = BX_READ_8BIT_REG(i->rm);
    }
  else {
    /* pointer, segment address pair */
    read_RMW_virtual_byte(i->seg, i->rm_addr, &op1_8);
    }

  diff_8 = AL - op1_8;

  SET_FLAGS_OSZAPC_8(AL, op1_8, diff_8, BX_INSTR_CMP8);

  if (diff_8 == 0) {  // if accumulator == dest
    // ZF = 1
    set_ZF(1);
    // dest <-- src
    op2_8 = BX_READ_8BIT_REG(i->nnn);

    if (i->mod == 0xc0) {
      BX_WRITE_8BIT_REG(i->rm, op2_8);
      }
    else {
      write_RMW_virtual_byte(op2_8);
      }
    }
  else {
    // ZF = 0
    set_ZF(0);
    // accumulator <-- dest
    AL = op1_8;
    }

#else
  BX_PANIC(("CMPXCHG_EbGb:"));
#endif
}
Esempio n. 7
0
  void
bx_cpu_c::BSF_GvEv(BxInstruction_t *i)
{
#if BX_CPU_LEVEL < 3
  BX_PANIC(("BSF_GvEv(): not supported on < 386"));
#else


  if (i->os_32) { /* 32 bit operand size mode */
    /* for 32 bit operand size mode */
    Bit32u op1_32, op2_32;

    /* op2_32 is a register or memory reference */
    if (i->mod == 0xc0) {
      op2_32 = BX_READ_32BIT_REG(i->rm);
      }
    else {
      /* pointer, segment address pair */
      read_virtual_dword(i->seg, i->rm_addr, &op2_32);
      }

    if (op2_32 == 0) {
      set_ZF(1);
      /* op1_32 undefined */
      return;
      }

    op1_32 = 0;
    while ( (op2_32 & 0x01) == 0 ) {
      op1_32++;
      op2_32 >>= 1;
      }
    set_ZF(0);

    /* now write result back to destination */
    BX_WRITE_32BIT_REG(i->nnn, op1_32);
    }
Esempio n. 8
0
void tlcs870_device::do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    LD r, g           1110 1ggg           0101 1rrr                        1  Z  -  -    2
	*/
	m_cycles = 2;

	const uint8_t val = get_reg8(opbyte0 & 0x7);
	set_reg8(opbyte1 & 0x7, val);

	set_JF();

	if (val == 0x00) set_ZF();
	else clear_ZF();
}
Esempio n. 9
0
void tlcs870_device::do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
	/*
	    OP                (opbyte0) (immval0) (opbyte1) (immval1) (immval2)    JF ZF CF HF   cycles
	    XCG r, g          1110 1ggg           1010 1rrr                        1  Z  -  -    3
	*/
	m_cycles = 3;

	const uint8_t val = get_reg8(opbyte0 & 0x7);
	const uint8_t r = get_reg8(opbyte1 & 0x7);

	set_reg8(opbyte1 & 0x7, val);
	set_reg8(opbyte0 & 0x7, r);

	set_JF();

	if (val == 0x00) set_ZF();
	else clear_ZF();
}
Esempio n. 10
0
Da_emulate_result Da_emulate(Da* d, CONTEXT * ctx, MemoryCache *mem, bool emulate_FS_accesses, address FS)
{
#ifdef _WIN64
    return DA_NOT_EMULATED;
#endif        
    //bool SF=IS_SET(ctx->EFlags, FLAG_SF);
    //bool OF=IS_SET(ctx->EFlags, FLAG_OF);
    //bool ZF=IS_SET(ctx->EFlags, FLAG_ZF);
    bool CF=IS_SET(ctx->EFlags, FLAG_CF);
    bool b;

    if (x86_emu_debug)
    {
        // FIXME: write to log also?
        L ("%s() begin: [", __func__);
        Da_DumpString(&cur_fds, d);
        L ("]\n");
    };

    if ((emulate_FS_accesses==false && IS_SET(d->prefix_codes, PREFIX_FS)) ||
            (IS_SET(d->prefix_codes, PREFIX_SS) || IS_SET(d->prefix_codes, PREFIX_GS)))
    {
        if (x86_emu_debug)
            L ("%s() skipping (data selector prefix present) at 0x" PRI_ADR_HEX "\n", __func__, CONTEXT_get_PC(ctx));
        return DA_EMULATED_CANNOT_READ_MEMORY;
    };

    switch (d->ins_code)
    {
        case I_CDQ:
            {
                uint32_t a=CONTEXT_get_Accum (ctx)&0xFFFFFFFF;
                CONTEXT_set_xDX (ctx, (a&0x80000000) ? 0xFFFFFFFF : 0);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_PUSH:
            {
                address rt_adr;
                obj v;
                b=Da_op_get_value_of_op (&d->op[0], &rt_adr, ctx, mem, __FILE__, __LINE__, &v, d->prefix_codes, FS);
                if (b==false)
                {
                    if (x86_emu_debug)
                        L ("%s() I_PUSH: can't read memory\n", __func__);
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                };
                b=DO_PUSH (ctx, mem, obj_get_as_REG(&v));
                if (b==false)
                {
                    if (x86_emu_debug)
                        L ("%s() I_PUSH: can't write memory\n", __func__);
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_PUSHFD:
            if (DO_PUSH (ctx, mem, ctx->EFlags | FLAG_TF)==false)
            {
                if (x86_emu_debug)
                    L ("%s() I_PUSHFD: can't write memory\n", __func__);
                return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            goto add_to_PC_and_return_OK;
            break;

        case I_POP:
            {
                REG val;
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                obj v;
                obj_tetrabyte2 (val, &v);
                Da_op_set_value_of_op (&d->op[0], &v, ctx, mem, d->prefix_codes, FS);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_POPFD:
            {
                REG val;
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                ctx->EFlags=val;
                goto add_to_PC_and_return_OK;
            };
            break;
        
        case I_LEAVE:
            {
                //ESP <- EBP
                //POP EBP

                REG val;
                CONTEXT_set_SP(ctx, CONTEXT_get_BP(ctx));
                if (DO_POP(ctx, mem, &val)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY; // FIXME: а надо еще SP назад возвращать!
                CONTEXT_set_BP(ctx, val);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_REP_STOSB:
        case I_REP_STOSW:
        case I_REP_STOSD:
            {
                BYTE *buf;
                bool DF=IS_SET(ctx->EFlags, FLAG_DF);
                if (DF)
                    return DA_NOT_EMULATED; // not supported... bug here

                SIZE_T BUF_SIZE;

                if (d->ins_code==I_REP_STOSB)
                    BUF_SIZE=CONTEXT_get_xCX (ctx);
                else if (d->ins_code==I_REP_STOSW)
                    BUF_SIZE=CONTEXT_get_xCX (ctx)*2;
                else if (d->ins_code==I_REP_STOSD)
                    BUF_SIZE=CONTEXT_get_xCX (ctx)*4;

                buf=DMALLOC(BYTE, BUF_SIZE, "buf");

                if (d->ins_code==I_REP_STOSB)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        buf[i]=CONTEXT_get_Accum(ctx)&0xFF;
                } 
                else if (d->ins_code==I_REP_STOSW)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        ((WORD*)buf)[i]=CONTEXT_get_Accum(ctx)&0xFFFF;
                } 
                else if (d->ins_code==I_REP_STOSD)
                {
                    for (REG i=0; i<CONTEXT_get_xCX(ctx); i++) // FIXME: rewrite to my own bzero()!
                        ((DWORD*)buf)[i]=(DWORD)(CONTEXT_get_Accum(ctx)&0xFFFFFFFF);
                } 
                else
                {
                    oassert(0);
                };

                if (MC_WriteBuffer (mem, CONTEXT_get_xDI (ctx), BUF_SIZE, buf)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                DFREE(buf);
                CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) + BUF_SIZE);
                CONTEXT_set_xCX (ctx, 0);
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_REP_MOVSB:
        case I_REP_MOVSW:
        case I_REP_MOVSD:
            {
                BYTE *buf;
                bool DF=IS_SET(ctx->EFlags, FLAG_DF);
                if (DF)
                    return DA_NOT_EMULATED; // not supported... bug here

                SIZE_T BUF_SIZE;
                SIZE_T sizeof_element;

                if (d->ins_code==I_REP_MOVSB)
                    sizeof_element=1;
                else if (d->ins_code==I_REP_MOVSW)
                    sizeof_element=2;
                else if (d->ins_code==I_REP_MOVSD)
                    sizeof_element=4;
                else
                {
                    oassert(0);
                };

                BUF_SIZE=CONTEXT_get_xCX(ctx)*sizeof_element;

                //printf ("%s() BUF_SIZE=0x%x\n", __func__, BUF_SIZE);
                //printf ("%s() (before) SI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xSI(ctx));
                //printf ("%s() (before) DI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xDI(ctx));

                buf=DMALLOC(BYTE, BUF_SIZE, "buf");

                address blk_src=CONTEXT_get_xSI(ctx);
                address blk_dst=CONTEXT_get_xDI(ctx);

                if (DF)
                {
                    blk_src-=BUF_SIZE; // +sizeof_element;
                    blk_dst-=BUF_SIZE; // +sizeof_element;
                };

                if (MC_ReadBuffer (mem, blk_src, BUF_SIZE, buf)==false)
                {
                    DFREE(buf);
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                };

                if (MC_WriteBuffer (mem, blk_dst, BUF_SIZE, buf)==false)
                {
                    DFREE(buf);
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };

                DFREE(buf);
                if (DF==false)
                {
                    CONTEXT_set_xSI (ctx, CONTEXT_get_xSI (ctx) + BUF_SIZE);
                    CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) + BUF_SIZE);
                }
                else
                {
                    CONTEXT_set_xSI (ctx, CONTEXT_get_xSI (ctx) - BUF_SIZE);
                    CONTEXT_set_xDI (ctx, CONTEXT_get_xDI (ctx) - BUF_SIZE);
                };
                CONTEXT_set_xCX (ctx, 0);

                //printf ("%s() (after) SI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xSI(ctx));
                //printf ("%s() (after) DI=0x" PRI_REG_HEX "\n", __func__, CONTEXT_get_xDI(ctx));

                goto add_to_PC_and_return_OK;
            };

        case I_STD:
            SET_BIT (ctx->EFlags, FLAG_DF);
            goto add_to_PC_and_return_OK;

        case I_CLD:
            REMOVE_BIT (ctx->EFlags, FLAG_DF);
            goto add_to_PC_and_return_OK;

        case I_RETN:
            {
                WORD ret_arg=0;
                if (d->ops_total==1)
                {
                    oassert (d->op[0].type==DA_OP_TYPE_VALUE);
                    ret_arg=obj_get_as_wyde(&d->op[0].val._v); // RETN arg is 16-bit
                };

                address newPC;
                if (DO_POP(ctx, mem, &newPC)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                CONTEXT_set_SP(ctx, CONTEXT_get_SP(ctx)+ret_arg);
                CONTEXT_set_PC(ctx, newPC);
                return DA_EMULATED_OK;
            };
            break;

        case I_ADD:
        case I_ADC:
        case I_INC:
            {
                //L (__FUNCTION__ "() I_ADD/I_INC begin: [%s]\n", ToString().c_str());

                obj rt1, rt2;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                if (d->ins_code==I_ADD || d->ins_code==I_ADC)
                {
                    oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                    b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                    if (b==false)
                        return DA_EMULATED_CANNOT_READ_MEMORY;
                }
                else
                {   // INC case
                    // make second op 1
                    obj_REG2_and_set_type (rt1.t, 1, 0, &rt2);
                };

                obj res_sum;
                obj_add (&rt1, &rt2, &res_sum);
                if (d->ins_code==I_ADC && CF)
                    obj_increment(&res_sum); 

                set_PF (ctx, &res_sum);
                set_SF (ctx, &res_sum);
                set_ZF (ctx, &res_sum);
                set_AF (ctx, &rt1, &rt2, &res_sum);
                if (d->ins_code==I_ADD || d->ins_code==I_ADC)
                    set_or_clear_flag (ctx, FLAG_CF, obj_compare (&res_sum, &rt1)==-1); // res_sum < rt1

                octabyte tmp=((zero_extend_to_REG(&rt1) ^ zero_extend_to_REG(&rt2) ^ 
                            get_sign_bit (d->op[0].value_width_in_bits)) & 
                        (zero_extend_to_REG(&res_sum) ^ zero_extend_to_REG(&rt1))) 
                    & 
                    get_sign_bit (d->op[0].value_width_in_bits);
                set_or_clear_flag (ctx, FLAG_OF, tmp);

                b=Da_op_set_value_of_op (&d->op[0], &res_sum, ctx, mem, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                goto add_to_PC_and_return_OK;
            };
            break;

        case I_NOT:
            {
                obj rt1, res;
                REG rt1_adr;
                if (Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj_NOT(&rt1, &res);

                if (Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS))
                    goto add_to_PC_and_return_OK;
            };
            break;

        case I_NEG:
            {
                obj rt1, res;
                REG rt1_adr;
                if (Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj_NEG(&rt1, &res);
                set_or_clear_flag (ctx, FLAG_CF, obj_is_zero(&rt1)==false);

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                set_or_clear_flag (ctx, FLAG_AF, (0 ^ obj_get_4th_bit(&rt1)) ^ obj_get_4th_bit(&res));
                REMOVE_BIT (ctx->EFlags, FLAG_OF);
                //SET_BIT (ctx->EFlags, FLAG_AF);

                if (Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS))
                    goto add_to_PC_and_return_OK;
            };
            break;


        case I_OR:
        case I_XOR:
        case I_AND:
        case I_TEST:
            {
                oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                obj rt1, rt2, res;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                switch (d->ins_code)
                {
                    case I_OR:  
                        obj_OR(&rt1, &rt2, &res); 
                        break;
                    case I_XOR: 
                        obj_XOR(&rt1, &rt2, &res); 
                        break;
                    case I_TEST: 
                    case I_AND: 
                        obj_AND(&rt1, &rt2, &res); 
                        break;
                    default: 
                        oassert(0);
                        break;
                };

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                REMOVE_BIT (ctx->EFlags, FLAG_AF);
                REMOVE_BIT (ctx->EFlags, FLAG_CF);
                REMOVE_BIT (ctx->EFlags, FLAG_OF);

                if (d->ins_code==I_TEST)
                    b=true;
                else
                    b=Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS);

                if (b)
                    goto add_to_PC_and_return_OK;
                else
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            break;

        case I_DEC:
        case I_SUB:
        case I_SBB:
        case I_CMP:
            {
                if (d->ins_code==I_SUB || d->ins_code==I_SBB || d->ins_code==I_CMP)
                {
                    oassert (d->op[0].value_width_in_bits==d->op[1].value_width_in_bits);
                };
                obj rt1, rt2;
                REG rt1_adr, rt2_adr;
                b=Da_op_get_value_of_op (&d->op[0], &rt1_adr, ctx, mem, __FILE__, __LINE__, &rt1, d->prefix_codes, FS);
                if (b==false) 
                    return DA_EMULATED_CANNOT_READ_MEMORY;
                if (d->ins_code==I_DEC)
                {
                    // make second op 1
                    obj_REG2_and_set_type (rt1.t, 1, 0, &rt2);
                }
                else
                {
                    b=Da_op_get_value_of_op (&d->op[1], &rt2_adr, ctx, mem, __FILE__, __LINE__, &rt2, d->prefix_codes, FS);
                    if (b==false)
                        return DA_EMULATED_CANNOT_READ_MEMORY;
                };

                obj res;
                obj_subtract (&rt1, &rt2, &res);
                if (d->ins_code==I_SBB && CF)
                    obj_decrement (&res);

                set_PF (ctx, &res);
                set_SF (ctx, &res);
                set_ZF (ctx, &res);
                set_AF (ctx, &rt1, &rt2, &res);

                if (d->ins_code==I_SBB)
                {
                    int tmp=(obj_compare (&rt1, &res)==-1 /* rt1<res */) || (CF && obj_get_as_tetrabyte(&rt2)==0xffffffff);
                    set_or_clear_flag (ctx, FLAG_CF, tmp);
                }
                else
                {
                    if (d->ins_code!=I_DEC) // DEC leave CF flag unaffected
                        set_or_clear_flag (ctx, FLAG_CF, obj_compare (&rt1, &rt2)==-1); /* rt1<rt2 */
                };

                octabyte tmp=((zero_extend_to_octabyte(&rt1) ^ zero_extend_to_octabyte(&rt2)) & 
                        (zero_extend_to_octabyte(&res) ^ zero_extend_to_octabyte(&rt1))) &
                    get_sign_bit (d->op[0].value_width_in_bits);
                set_or_clear_flag (ctx, FLAG_OF, tmp);

                if (d->ins_code==I_CMP)
                    b=true;
                else
                    b=Da_op_set_value_of_op (&d->op[0], &res, ctx, mem, d->prefix_codes, FS);

                if (b)
                    goto add_to_PC_and_return_OK;
                else
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
            };
            break;

        case I_XCHG:
            {
                REG op1_adr, op2_adr;

                obj op1;
                b=Da_op_get_value_of_op(&d->op[0], &op1_adr, ctx, mem, __FILE__, __LINE__, &op1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                obj op2;
                b=Da_op_get_value_of_op(&d->op[1], &op2_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                if (Da_op_set_value_of_op (&d->op[0], &op2, ctx, mem, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;

                if (Da_op_set_value_of_op (&d->op[1], &op1, ctx, mem, d->prefix_codes, FS)==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;

                goto add_to_PC_and_return_OK;
            };
            break;

        case I_MOV:
        case I_MOVDQA:
        case I_MOVDQU:
            return Da_emulate_MOV_op1_op2(d, ctx, mem, d->prefix_codes, FS);

        case I_MOVZX:
        case I_MOVSX:
            {
                address rt_adr;
                obj op2;
                bool b=Da_op_get_value_of_op(&d->op[1], &rt_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                {
                    /*
                       if (L_verbose_level>=2)
                       {
                       printf (__FUNCTION__ "(): [");
                       Da_DumpString(d);
                       printf ("]: can't read src (2nd) operand\n");
                       };
                       */
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };

                obj to_be_stored_v;

                if (d->ins_code==I_MOVZX)
                {
                    enum obj_type op1_type_will_be=bit_width_to_obj_type (d->op[0].value_width_in_bits);
                    obj_zero_extend (&op2, op1_type_will_be, &to_be_stored_v);
                }
                else if (d->ins_code==I_MOVSX)
                {
                    enum obj_type op1_type_will_be=bit_width_to_obj_type (d->op[0].value_width_in_bits);
                    obj_sign_extend (&op2, op1_type_will_be, &to_be_stored_v);
                }
                else
                {
                    oassert (0);
                };

                b=Da_op_set_value_of_op (&d->op[0], &to_be_stored_v, ctx, mem, d->prefix_codes, FS);

                if (b==false)
                {
                    /*
                       if (L_verbose_level>=2)
                       {
                       printf(__FUNCTION__ "(): [");
                       Da_DumpString(d);
                       printf ("]: can't write dst (1st) operand\n");
                       };
                       */
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                };
                goto add_to_PC_and_return_OK;
            };

        case I_NOP:
            goto add_to_PC_and_return_OK;

        case I_LEA:
            {
                address a=(address)Da_op_calc_adr_of_op(&d->op[1], ctx, mem, d->prefix_codes, FS);
                obj val;
                obj_tetrabyte2(a, &val);
                b=Da_op_set_value_of_op (&d->op[0], &val, ctx, mem, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_WRITE_MEMORY;
                goto add_to_PC_and_return_OK;
            };

        case I_SAR:
        case I_SHR:
        case I_SHL:
            {
                // http://cs.smith.edu/~thiebaut/ArtOfAssembly/CH06/CH06-3.html

                REG op1_adr, op2_adr;

                obj op1;
                bool b=Da_op_get_value_of_op(&d->op[0], &op1_adr, ctx, mem, __FILE__, __LINE__, &op1, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;

                // should be read anyway!
                obj op2;
                b=Da_op_get_value_of_op(&d->op[1], &op2_adr, ctx, mem, __FILE__, __LINE__, &op2, d->prefix_codes, FS);
                if (b==false)
                    return DA_EMULATED_CANNOT_READ_MEMORY;
#ifdef _WIN64 
                obj_AND_with (&op2, 0x3F);
#else
                obj_AND_with (&op2, 0x1F);
#endif
                if (obj_is_zero(&op2)==false)
                {
                    unsigned new_CF;

                    if (d->ins_code==I_SHR || d->ins_code==I_SAR)
                        new_CF=(zero_extend_to_octabyte(&op1) >> (obj_get_as_byte (&op2) - 1)) & 1;
                    else // SHL
                        new_CF=(zero_extend_to_octabyte(&op1) >> (obj_width_in_bits(&op1) - obj_get_as_byte (&op2))) & 1;

                    obj new_op1;

                    if (d->ins_code==I_SHR)
                    {
                        REG new_v=zero_extend_to_REG(&op1) >> obj_get_as_byte (&op2);
                        obj_REG2_and_set_type(op1.t, new_v, 0, &new_op1);
                    }
                    else if (d->ins_code==I_SAR)