int32_t instr_group_5_ff_inc(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /0 * Increment r/m word by 1 * INC r/m16 */ uint16_t dst; MEM_WORD_READ(c, i->modrm.ea, &dst); INSTR_CALC_AND_SET_FLAGS(16, c, dst) MEM_WORD_WRITE(c, i->modrm.ea, dst); } else { /* FF /0 * Increment r/m doubleword by 1 * INC r/m32 */ uint32_t dst; MEM_DWORD_READ(c, i->modrm.ea, &dst); INSTR_CALC_AND_SET_FLAGS(32, c, dst) MEM_DWORD_WRITE(c, i->modrm.ea, dst); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /0 * Increment r/m word by 1 * INC r/m16 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm]) } else { /* FF /0 * Increment r/m doubleword by 1 * INC r/m32 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm]) } } return 0; }
int32_t instr_group_5_ff_push(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /6 * Push r/m16 * PUSH r/m16 */ uint16_t m16; MEM_WORD_READ(c,i->modrm.ea,&m16); PUSH_WORD(c, m16); } else { /* FF /6 * Push r/m32 * PUSH r/m32 */ uint32_t m32; MEM_DWORD_READ(c,i->modrm.ea,&m32); enum emu_segment oldseg = emu_memory_segment_get(c->mem); emu_memory_segment_select(c->mem, s_ss); PUSH_DWORD(c, m32); emu_memory_segment_select(c->mem, oldseg); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* FF /6 * Push r/m16 * PUSH r/m16 */ PUSH_WORD(c, *c->reg16[i->modrm.rm]); } else { /* FF /6 * Push r/m32 * PUSH r/m32 */ PUSH_DWORD(c, c->reg[i->modrm.rm]); } } return 0; }
int32_t instr_mov_8b(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->prefixes & PREFIX_OPSIZE ) { /* 8B /r * Move r/m16 to r16 * MOV r16,r/m16 */ if( i->modrm.mod != 3 ) { MEM_WORD_READ(c, i->modrm.ea, c->reg16[i->modrm.opc]); //TRACK_INIT_REG16(c->instr, i->modrm.opc); } else { *c->reg16[i->modrm.opc] = *c->reg16[i->modrm.rm]; } } else { /* 8B /r * Move r/m32 to r32 * MOV r32,r/m32 */ if( i->modrm.mod != 3 ) { MEM_DWORD_READ(c, i->modrm.ea, &c->reg[i->modrm.opc]); //TRACK_INIT_REG32(c->instr, i->modrm.opc); } else { c->reg[i->modrm.opc] = c->reg[i->modrm.rm]; //TRACK_INIT_REG32(c->instr, i->modrm.opc); /*if ( c->tracking != NULL ) { c->tracking->track.reg[i->modrm.opc] = c->tracking->track.reg[i->modrm.rm]; }*/ } } return 0; }
//dzzie 5.19.11 - http://pdos.csail.mit.edu/6.828/2004/readings/i386/MOVS.htm int32_t instr_movs_a5(struct emu_cpu *c, struct emu_cpu_instruction *i) { if (i->prefixes & PREFIX_ADSIZE ) { UNIMPLEMENTED(c, SST); return 0; } uint8_t incSize = 0; if ( i->prefixes & PREFIX_OPSIZE ) //16bit { uint16_t tmp; MEM_WORD_READ(c, c->reg[esi], &tmp); MEM_WORD_WRITE(c, c->reg[edi], tmp); incSize = 2; } else{ //32bit uint32_t tmp2; MEM_DWORD_READ(c, c->reg[esi], &tmp2); MEM_DWORD_WRITE(c, c->reg[edi], tmp2); incSize = 4; } if (i->prefixes & PREFIX_F3) /* rep prefix - Copy ECX bytes from DS:[ESI] to ES:[EDI] */ { c->repeat_current_instr = false; if (c->reg[ecx] > 0 ){ c->reg[ecx]--; c->repeat_current_instr = true; }else{ return 0; //rep operation complete..do not adjust registers any more } } if ( !CPU_FLAG_ISSET(c,f_df) ){ /* increment */ c->reg[edi] += incSize; c->reg[esi] += incSize; } else{ /* decrement */ c->reg[edi] -= incSize; c->reg[esi] -= incSize; } return 0; }
int32_t instr_mov_a1(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->prefixes & PREFIX_OPSIZE ) { /* A1 * Move word at (seg:offset) to AX * MOV AX,moffs16* */ MEM_WORD_READ(c, i->disp, c->reg16[ax]); } else { /* A1 * Move doubleword at (seg:offset) to EAX * MOV EAX,moffs32* */ MEM_DWORD_READ(c, i->disp, &c->reg[eax]); //TRACK_INIT_REG32(c->instr, eax); } return 0; }
int32_t instr_imul_0f_af(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 0F AF /r * word register <- word register * r/m word * IMUL r16,r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, *c->reg16[i->modrm.opc], m16) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 0F AF /r * doubleword register <- doubleword register * r/m doubleword * IMUL r32,r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, c->reg[i->modrm.opc], m32) c->reg[i->modrm.opc] = operation_result; uint16_t high; DWORD_UPPER_TO_WORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 0F AF /r * word register <- word register * r/m word * IMUL r16,r/m16 */ INSTR_CALC(16, 32, c, *c->reg16[i->modrm.opc], *c->reg16[i->modrm.rm]) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 0F AF /r * doubleword register <- doubleword register * r/m doubleword * IMUL r32,r/m32 */ INSTR_CALC(32, 64, c, c->reg[i->modrm.opc], c->reg[i->modrm.rm]) c->reg[i->modrm.opc] = operation_result; uint16_t high; DWORD_UPPER_TO_WORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t instr_group_2_d3_shr(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /5 * Unsigned divide r/m16 by 2, CL times * SHR r/m16,CL */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *c->reg8[cl]); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D3 /5 * Unsigned divide r/m32 by 2, CL times * SHR r/m32,CL */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *c->reg8[cl]); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /5 * Unsigned divide r/m16 by 2, CL times * SHR r/m16,CL */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *c->reg8[cl]); } else { /* D3 /5 * Unsigned divide r/m32 by 2, CL times * SHR r/m32,CL */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *c->reg8[cl]); } } return 0; }
int32_t instr_group_3_f7_not(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /2 * Reverse each bit of r/m16 * NOT r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16) MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* F7 /2 * Reverse each bit of r/m32 * NOT r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32) MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /2 * Reverse each bit of r/m16 * NOT r/m16 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm]) } else { /* F7 /2 * Reverse each bit of r/m32 * NOT r/m32 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm]) } } return 0; }
int32_t instr_group_2_d3_rcl(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /2 * Rotate 17 bits (CF,r/m16) left CL times * RCL r/m16,CL */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *c->reg8[cl]); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D3 /2 * Rotate 33 bits (CF,r/m32) left CL times * RCL r/m32,CL */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *c->reg8[cl]); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D3 /2 * Rotate 17 bits (CF,r/m16) left CL times * RCL r/m16,CL */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *c->reg8[cl]); } else { /* D3 /2 * Rotate 33 bits (CF,r/m32) left CL times * RCL r/m32,CL */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *c->reg8[cl]); } } return 0; }
int32_t instr_group_5_ff_call(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->modrm.opc == 2 ) { PUSH_DWORD(c, c->eip); if( i->modrm.mod != 3 ) { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /2 * CALL r/m16 * Call near, absolute indirect, address given in r/m16 */ uint16_t disp; MEM_WORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } else { /* FF /2 * CALL r/m32 * Call near, absolute indirect, address given in r/m32 */ uint32_t disp; MEM_DWORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } } else { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /2 * CALL r/m16 * Call near, absolute indirect, address given in r/m16 */ c->eip = *c->reg16[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); TRACK_NEED_REG16(c->instr, i->modrm.rm); } else { /* FF /2 * CALL r/m32 * Call near, absolute indirect, address given in r/m32 */ c->eip = c->reg[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); TRACK_NEED_REG32(c->instr, i->modrm.rm); } } } else { /* FF /3 * CALL m16:16 * Call far, absolute indirect, address given in m16:16 */ /* FF /3 * CALL m16:32 * Call far, absolute indirect, address given in m16:32 */ UNIMPLEMENTED(c, SST); } return 0; }
int32_t instr_group_2_d1_sal(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /4 * Multiply r/m16 by 2, once * SAL r/m16,1 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, 1); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D1 /4 * Multiply r/m32 by 2, once * SAL r/m32,1 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, 1); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /4 * Multiply r/m16 by 2, once * SAL r/m16,1 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], 1); } else { /* D1 /4 * Multiply r/m32 by 2, once * SAL r/m32,1 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], 1); } } return 0; }
int32_t instr_imul_69(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 69 /r iw * word register <- r/m16 * immediate word * IMUL r16,imm16 * * word register <- r/m16 * immediate word * IMUL r16,r/m16,imm16 */ #if BYTE_ORDER == BIG_ENDIAN int16_t sexd; bcopy(i->imm16, &sexd, 2); #else int16_t sexd = (int16_t)*i->imm16; #endif uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, m16, sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 69 /r id * doubleword register <- r/m32 * immediate doubleword * IMUL r32,imm32 * * doubleword register <- r/m32 * immediate doubleword * IMUL r32,r/m32,imm32 */ int32_t sexd = (int32_t)i->imm; uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, m32, sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 69 /r iw * word register <- r/m16 * immediate word * IMUL r16,imm16 * * word register <- r/m16 * immediate word * IMUL r16,r/m16,imm16 */ #if BYTE_ORDER == BIG_ENDIAN int16_t sexd; bcopy(i->imm16, &sexd, 2); #else int16_t sexd = (int16_t)*i->imm16; #endif INSTR_CALC(16, 32, c, *c->reg16[i->modrm.rm], sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 69 /r id * doubleword register <- r/m32 * immediate doubleword * IMUL r32,imm32 * * doubleword register <- r/m32 * immediate doubleword * IMUL r32,r/m32,imm32 */ int32_t sexd = (int32_t)i->imm; INSTR_CALC(32, 64, c, c->reg[i->modrm.rm], sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t instr_group_3_f7_imul(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /5 * DX:AX <- AX * r/m word * IMUL r/m16 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, *c->reg16[al], m16) DWORD_UPPER_TO_WORD(*c->reg16[dx],operation_result); DWORD_LOWER_TO_WORD(*c->reg16[ax],operation_result); INSTR_SET_FLAGS(c,*c->reg16[dx]); } else { /* F7 /5 * EDX:EAX <- EAX * r/m doubleword * IMUL r/m32 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, c->reg[eax], m32) QWORD_UPPER_TO_DWORD(c->reg[edx],operation_result); QWORD_LOWER_TO_DWORD(c->reg[eax],operation_result); INSTR_SET_FLAGS(c,c->reg[edx]); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* F7 /5 * DX:AX <- AX * r/m word * IMUL r/m16 */ INSTR_CALC(16, 32, c, *c->reg16[al], *c->reg16[i->modrm.rm]) DWORD_UPPER_TO_WORD(*c->reg16[dx],operation_result); DWORD_LOWER_TO_WORD(*c->reg16[ax],operation_result); INSTR_SET_FLAGS(c,*c->reg16[dx]); } else { /* F7 /5 * EDX:EAX <- EAX * r/m doubleword * IMUL r/m32 */ INSTR_CALC(32, 64, c, c->reg[eax], c->reg[i->modrm.rm]) QWORD_UPPER_TO_DWORD(c->reg[edx],operation_result); QWORD_LOWER_TO_DWORD(c->reg[eax],operation_result); INSTR_SET_FLAGS(c,c->reg[edx]); } } return 0; }
int32_t instr_imul_6b(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* 6B /r ib * word register <- m16 * sign-extended immediate byte * IMUL r16,m16,imm8 */ int16_t sexd = (int8_t)*i->imm8; uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC(16, 32, c, m16, sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 6B /r ib * word register <- m16 * sign-extended immediate byte * IMUL r16,m16,imm8 */ int32_t sexd = (int8_t)*i->imm8; uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC(32, 64, c, m32, sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* 6B /r ib * word register <- r16 * sign-extended immediate byte * IMUL r16,r16,imm8 * * word register <- word register * sign-extended immediate byte * IMUL r16,imm8 */ int16_t sexd = (int8_t)*i->imm8; INSTR_CALC(16, 32, c, *c->reg16[i->modrm.rm], sexd) *c->reg16[i->modrm.opc] = operation_result; uint8_t high; WORD_UPPER_TO_BYTE(high,operation_result); INSTR_SET_FLAGS(c,high); } else { /* 6B /r ib * doubleword register <- r32 * sign-extended immediate byte * IMUL r32,r32,imm8 * * doubleword register <- doubleword register * sign-extended immediate byte * IMUL r32,imm8 */ int32_t sexd = (int8_t)*i->imm8; INSTR_CALC(32, 64, c, c->reg[i->modrm.rm], sexd) c->reg[i->modrm.opc] = operation_result; uint32_t high; QWORD_UPPER_TO_DWORD(high,operation_result); INSTR_SET_FLAGS(c,high); } } return 0; }
int32_t instr_group_2_c1_sar(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* C1 /7 ib * Signed divide* r/m16 by 2, imm8 times * SAR r/m16,imm8 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, *i->imm8); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* C1 /7 ib * Signed divide* r/m32 by 2, imm8 times * SAR r/m32,imm8 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, *i->imm8); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* C1 /7 ib * Signed divide* r/m16 by 2, imm8 times * SAR r/m16,imm8 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], *i->imm8); } else { /* C1 /7 ib * Signed divide* r/m32 by 2, imm8 times * SAR r/m32,imm8 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], *i->imm8); } } return 0; }
int32_t instr_group_5_ff_jmp(struct emu_cpu *c, struct emu_cpu_instruction *i) { if( i->modrm.opc == 4 ) { if( i->modrm.mod != 3 ) { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /4 * Jump near, absolute indirect, address given in r/m16 * JMP r/m16 */ uint16_t disp; MEM_WORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } else { /* FF /4 * Jump near, absolute indirect, address given in r/m32 * JMP r/m32 */ uint32_t disp; MEM_DWORD_READ(c, i->modrm.ea, &disp); c->eip = disp; SOURCE_NORM_POS(c->instr, c->eip); } } else { if( i->prefixes & PREFIX_OPSIZE ) { /* FF /4 * Jump near, absolute indirect, address given in r/m16 * JMP r/m16 */ c->eip = *c->reg16[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); //TRACK_NEED_REG16(c->instr, i->modrm.rm); } else { /* FF /4 * Jump near, absolute indirect, address given in r/m32 * JMP r/m32 */ c->eip = c->reg[i->modrm.rm]; SOURCE_NORM_POS(c->instr, c->eip); //TRACK_NEED_REG32(c->instr, i->modrm.rm); } } } else /* /5 */ { /* unneeded */ /* FF /5 * Jump far, absolute indirect, address given in m16:16 * JMP m16:16 */ /* FF /5 * Jump far, absolute indirect, address given in m16:32 * JMP m16:32 */ UNIMPLEMENTED(c, SST); } return 0; }
int32_t instr_group_2_d1_rcr(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->modrm.mod != 3 ) { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /3 * Rotate 17 bits (CF,r/m16) right once * RCR r/m16,1 */ uint16_t m16; MEM_WORD_READ(c, i->modrm.ea, &m16); INSTR_CALC_AND_SET_FLAGS(16, c, m16, 1); MEM_WORD_WRITE(c, i->modrm.ea, m16); } else { /* D1 /3 * Rotate 33 bits (CF,r/m32) right once * RCR r/m32,1 */ uint32_t m32; MEM_DWORD_READ(c, i->modrm.ea, &m32); INSTR_CALC_AND_SET_FLAGS(32, c, m32, 1); MEM_DWORD_WRITE(c, i->modrm.ea, m32); } } else { if ( i->prefixes & PREFIX_OPSIZE ) { /* D1 /3 * Rotate 17 bits (CF,r/m16) right once * RCR r/m16,1 */ INSTR_CALC_AND_SET_FLAGS(16, c, *c->reg16[i->modrm.rm], 1); } else { /* D1 /3 * Rotate 33 bits (CF,r/m32) right once * RCR r/m32,1 */ INSTR_CALC_AND_SET_FLAGS(32, c, c->reg[i->modrm.rm], 1); } } return 0; }
int32_t instr_lods_ad(struct emu_cpu *c, struct emu_cpu_instruction *i) { if ( i->prefixes & PREFIX_OPSIZE ) { /* AD * Load word at address DS:(E)SI into AX * LODS m16 */ /* AD * Load word at address DS:(E)SI into AX * LODSW */ if ( i->prefixes & PREFIX_ADSIZE ) { // MEM_WORD_READ(c, c->reg16[si], c->reg16[ax]); UNIMPLEMENTED(c, SST); } else { MEM_WORD_READ(c, c->reg[esi], c->reg16[ax]); if (CPU_FLAG_ISSET(c,f_df)) { /* decrement */ c->reg[esi] -= 2; }else { /* increment */ c->reg[esi] += 2; } } } else { /* AD * Load doubleword at address DS:(E)SI into EAX * LODS m32 */ /* AD * Load doubleword at address DS:(E)SI into EAX * LODSD */ if ( i->prefixes & PREFIX_ADSIZE ) { // MEM_DWORD_READ(c, c->reg16[si], &c->reg[eax]); UNIMPLEMENTED(c, SST); } else { MEM_DWORD_READ(c, c->reg[esi], &c->reg[eax]); if (CPU_FLAG_ISSET(c,f_df)) { /* decrement */ c->reg[esi] -= 4; }else { /* increment */ c->reg[esi] += 4; } //TRACK_INIT_REG32(c->instr, eax); } } return 0; }