735
636
emit_pop_r32(dst, REG_EBX); // pop ebx
736
637
emit_ret(dst); // ret
738
/* call it to determine if we have SSE3 support */
739
drcbe->sse3 = (((*cpuid_ecx_stub)() & 1) != 0);
639
// call it to determine if we have SSE3 support
640
m_sse3 = (((*cpuid_ecx_stub)() & 1) != 0);
741
/* generate an entry point */
742
drcbe->entry = (x86_entry_point_func)*dst;
642
// generate an entry point
643
m_entry = (x86_entry_point_func)dst;
743
644
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ESP, 4)); // mov eax,[esp+4]
744
645
emit_push_r32(dst, REG_EBX); // push ebx
745
646
emit_push_r32(dst, REG_ESI); // push esi
746
647
emit_push_r32(dst, REG_EDI); // push edi
747
648
emit_push_r32(dst, REG_EBP); // push ebp
748
649
emit_sub_r32_imm(dst, REG_ESP, 24); // sub esp,24
749
emit_mov_m32_r32(dst, MABS(&drcbe->hashstacksave), REG_ESP); // mov [hashstacksave],esp
650
emit_mov_m32_r32(dst, MABS(&m_hashstacksave), REG_ESP); // mov [hashstacksave],esp
750
651
emit_sub_r32_imm(dst, REG_ESP, 4); // sub esp,4
751
emit_mov_m32_r32(dst, MABS(&drcbe->stacksave), REG_ESP); // mov [stacksave],esp
752
emit_fstcw_m16(dst, MABS(&drcbe->fpumode)); // fstcw [fpumode]
652
emit_mov_m32_r32(dst, MABS(&m_stacksave), REG_ESP); // mov [stacksave],esp
653
emit_fstcw_m16(dst, MABS(&m_fpumode)); // fstcw [fpumode]
753
654
emit_jmp_r32(dst, REG_EAX); // jmp eax
754
if (drcbe->log != NULL && !drcbe->logged_common)
755
x86log_disasm_code_range(drcbe->log, "entry_point", (x86code *)drcbe->entry, *dst);
655
if (m_log != NULL && !m_logged_common)
656
x86log_disasm_code_range(m_log, "entry_point", (x86code *)m_entry, dst);
757
/* generate an exit point */
759
emit_fldcw_m16(dst, MABS(&drcbe->fpumode)); // fldcw [fpumode]
760
emit_mov_r32_m32(dst, REG_ESP, MABS(&drcbe->hashstacksave)); // mov esp,[hashstacksave]
658
// generate an exit point
660
emit_fldcw_m16(dst, MABS(&m_fpumode)); // fldcw [fpumode]
661
emit_mov_r32_m32(dst, REG_ESP, MABS(&m_hashstacksave)); // mov esp,[hashstacksave]
761
662
emit_add_r32_imm(dst, REG_ESP, 24); // add esp,24
762
663
emit_pop_r32(dst, REG_EBP); // pop ebp
763
664
emit_pop_r32(dst, REG_EDI); // pop edi
764
665
emit_pop_r32(dst, REG_ESI); // pop esi
765
666
emit_pop_r32(dst, REG_EBX); // pop ebx
766
667
emit_ret(dst); // ret
767
if (drcbe->log != NULL && !drcbe->logged_common)
768
x86log_disasm_code_range(drcbe->log, "exit_point", drcbe->exit, *dst);
668
if (m_log != NULL && !m_logged_common)
669
x86log_disasm_code_range(m_log, "exit_point", m_exit, dst);
770
/* generate a no code point */
771
drcbe->nocode = *dst;
671
// generate a no code point
772
673
emit_ret(dst); // ret
773
if (drcbe->log != NULL && !drcbe->logged_common)
774
x86log_disasm_code_range(drcbe->log, "nocode", drcbe->nocode, *dst);
674
if (m_log != NULL && !m_logged_common)
675
x86log_disasm_code_range(m_log, "nocode", m_nocode, dst);
776
/* generate a save subroutine */
677
// generate a save subroutine
778
679
emit_pushf(dst); // pushf
779
680
emit_pop_r32(dst, REG_EAX); // pop eax
780
681
emit_and_r32_imm(dst, REG_EAX, 0x8c5); // and eax,0x8c5
781
emit_mov_r8_m8(dst, REG_AL, MBD(REG_EAX, flags_map)); // mov al,[flags_map]
682
emit_mov_r8_m8(dst, REG_AL, MABSI(flags_map, REG_EAX)); // mov al,[flags_map]
782
683
emit_mov_m8_r8(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, flags)), REG_AL); // mov state->flags,al
783
emit_mov_r8_m8(dst, REG_AL, MABS(&drcbe->state.fmod)); // mov al,[fmod]
684
emit_mov_r8_m8(dst, REG_AL, MABS(&m_state.fmod)); // mov al,[fmod]
784
685
emit_mov_m8_r8(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, fmod)), REG_AL); // mov state->fmod,al
785
emit_mov_r32_m32(dst, REG_EAX, MABS(&drcbe->state.exp)); // mov eax,[exp]
686
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
786
687
emit_mov_m32_r32(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, exp)), REG_EAX); // mov state->exp,eax
787
for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.r); regnum++)
688
for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
789
int regoffsl = (int)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
790
int regoffsh = (int)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
690
FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
691
FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
791
692
if (int_register_map[regnum] != 0)
792
693
emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), int_register_map[regnum]);
795
emit_mov_r32_m32(dst, REG_EAX, MABS(&drcbe->state.r[regnum].w.l));
696
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.r[regnum].w.l));
796
697
emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), REG_EAX);
798
emit_mov_r32_m32(dst, REG_EAX, MABS(&drcbe->state.r[regnum].w.h));
699
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.r[regnum].w.h));
799
700
emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsh), REG_EAX);
801
for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.f); regnum++)
702
for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
803
int regoffsl = (int)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
804
int regoffsh = (int)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
805
emit_mov_r32_m32(dst, REG_EAX, MABS(&drcbe->state.f[regnum].s.l));
704
FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
705
FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
706
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.f[regnum].s.l));
806
707
emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), REG_EAX);
807
emit_mov_r32_m32(dst, REG_EAX, MABS(&drcbe->state.f[regnum].s.h));
708
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.f[regnum].s.h));
808
709
emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsh), REG_EAX);
810
711
emit_ret(dst); // ret
811
if (drcbe->log != NULL && !drcbe->logged_common)
812
x86log_disasm_code_range(drcbe->log, "save", drcbe->save, *dst);
712
if (m_log != NULL && !m_logged_common)
713
x86log_disasm_code_range(m_log, "save", m_save, dst);
814
/* generate a restore subroutine */
815
drcbe->restore = *dst;
816
for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.r); regnum++)
715
// generate a restore subroutine
717
for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
818
int regoffsl = (int)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
819
int regoffsh = (int)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
719
FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
720
FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
820
721
if (int_register_map[regnum] != 0)
821
722
emit_mov_r32_m32(dst, int_register_map[regnum], MBD(REG_ECX, regoffsl));
824
725
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsl));
825
emit_mov_m32_r32(dst, MABS(&drcbe->state.r[regnum].w.l), REG_EAX);
726
emit_mov_m32_r32(dst, MABS(&m_state.r[regnum].w.l), REG_EAX);
827
728
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsh));
828
emit_mov_m32_r32(dst, MABS(&drcbe->state.r[regnum].w.h), REG_EAX);
729
emit_mov_m32_r32(dst, MABS(&m_state.r[regnum].w.h), REG_EAX);
830
for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.f); regnum++)
731
for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
832
int regoffsl = (int)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
833
int regoffsh = (int)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
733
FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
734
FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
834
735
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsl));
835
emit_mov_m32_r32(dst, MABS(&drcbe->state.f[regnum].s.l), REG_EAX);
736
emit_mov_m32_r32(dst, MABS(&m_state.f[regnum].s.l), REG_EAX);
836
737
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsh));
837
emit_mov_m32_r32(dst, MABS(&drcbe->state.f[regnum].s.h), REG_EAX);
738
emit_mov_m32_r32(dst, MABS(&m_state.f[regnum].s.h), REG_EAX);
839
740
emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, fmod)));// movzx eax,state->fmod
840
741
emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
841
emit_mov_m8_r8(dst, MABS(&drcbe->state.fmod), REG_AL); // mov [fmod],al
842
emit_fldcw_m16(dst, MISD(REG_EAX, 2, &fp_control[0])); // fldcw fp_control[eax]
742
emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
743
emit_fldcw_m16(dst, MABSI(&fp_control[0], REG_EAX, 2)); // fldcw fp_control[eax]
843
744
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, exp))); // mov eax,state->exp
844
emit_mov_m32_r32(dst, MABS(&drcbe->state.exp), REG_EAX); // mov [exp],eax
745
emit_mov_m32_r32(dst, MABS(&m_state.exp), REG_EAX); // mov [exp],eax
845
746
emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, flags)));// movzx eax,state->flags
846
emit_push_m32(dst, MISD(REG_EAX, 4, flags_unmap)); // push flags_unmap[eax*4]
747
emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
847
748
emit_popf(dst); // popf
848
749
emit_ret(dst); // ret
849
if (drcbe->log != NULL && !drcbe->logged_common)
850
x86log_disasm_code_range(drcbe->log, "restore", drcbe->restore, *dst);
852
/* finish up codegen */
853
drccache_end_codegen(drcbe->cache);
854
drcbe->logged_common = TRUE;
856
/* reset our hash tables */
857
drchash_reset(drcbe->hash);
858
drchash_set_default_codeptr(drcbe->hash, drcbe->nocode);
862
/*-------------------------------------------------
863
drcbex86_execute - execute a block of code
864
referenced by the given handle
865
-------------------------------------------------*/
867
static int drcbex86_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
869
/* call our entry point which will jump to the destination */
870
return (*drcbe->entry)((x86code *)drcuml_handle_codeptr(entry));
874
/*-------------------------------------------------
875
drcbex86_generate - generate code
876
-------------------------------------------------*/
878
static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drcuml_instruction *instlist, UINT32 numinst)
750
if (m_log != NULL && !m_logged_common)
751
x86log_disasm_code_range(m_log, "restore", m_restore, dst);
755
m_cache.end_codegen();
756
m_logged_common = true;
758
// reset our hash tables
760
m_hash.set_default_codeptr(m_nocode);
764
//-------------------------------------------------
765
// drcbex86_execute - execute a block of code
766
// referenced by the given handle
767
//-------------------------------------------------
769
int drcbe_x86::execute(code_handle &entry)
771
// call our entry point which will jump to the destination
772
return (*m_entry)((x86code *)entry.codeptr());
776
//-------------------------------------------------
777
// drcbex86_generate - generate code
778
//-------------------------------------------------
780
void drcbe_x86::generate(drcuml_block &block, const instruction *instlist, UINT32 numinst)
782
// tell all of our utility objects that a block is beginning
783
m_hash.block_begin(block, instlist, numinst);
784
m_labels.block_begin(block);
785
m_map.block_begin(block);
787
// begin codegen; fail if we can't
788
drccodeptr *cachetop = m_cache.begin_codegen(numinst * 8 * 4);
789
if (cachetop == NULL)
792
// compute the base by aligning the cache top to a cache line (assumed to be 64 bytes)
793
x86code *base = (x86code *)(((FPTR)*cachetop + 63) & ~63);
880
798
const char *blockname = NULL;
881
char blockbuffer[100];
882
drccodeptr *cachetop;
887
/* tell all of our utility objects that a block is beginning */
888
drchash_block_begin(drcbe->hash, block, instlist, numinst);
889
drclabel_block_begin(drcbe->labels, block);
890
drcmap_block_begin(drcbe->map, block);
892
/* begin codegen; fail if we can't */
893
cachetop = drccache_begin_codegen(drcbe->cache, numinst * 8 * 4);
894
if (cachetop == NULL)
895
drcuml_block_abort(block);
897
/* compute the base by aligning the cache top to a cache line (assumed to be 64 bytes) */
898
base = (x86code *)(((FPTR)*cachetop + 63) & ~63);
902
for (inum = 0; inum < numinst; inum++)
799
for (int inum = 0; inum < numinst; inum++)
904
const drcuml_instruction *inst = &instlist[inum];
905
assert(inst->opcode < ARRAY_LENGTH(opcode_table));
801
const instruction &inst = instlist[inum];
802
assert(inst.opcode() < ARRAY_LENGTH(s_opcode_table));
908
if (drcbe->log != NULL)
911
drcuml_disasm(inst, dasm, drcbe->drcuml);
912
x86log_add_comment(drcbe->log, dst, "%s", dasm);
808
inst.disasm(dasm, &m_drcuml);
809
x86log_add_comment(m_log, dst, "%s", dasm.cstr());
915
/* extract a blockname */
812
// extract a blockname
916
813
if (blockname == NULL)
918
if (inst->opcode == DRCUML_OP_HANDLE)
919
blockname = drcuml_handle_name((drcuml_codehandle *)(FPTR)inst->param[0].value);
920
else if (inst->opcode == DRCUML_OP_HASH)
922
sprintf(blockbuffer, "Code: mode=%d PC=%08X", (UINT32)inst->param[0].value, (offs_t)inst->param[1].value);
923
blockname = blockbuffer;
815
if (inst.opcode() == OP_HANDLE)
816
blockname = inst.param(0).handle().string();
817
else if (inst.opcode() == OP_HASH)
818
blockname = tempstring.format("Code: mode=%d PC=%08X", (UINT32)inst.param(0).immediate(), (offs_t)inst.param(1).immediate());
928
dst = (*opcode_table[inst->opcode])(drcbe, dst, inst);
822
(this->*s_opcode_table[inst.opcode()])(dst, inst);
931
/* complete codegen */
932
826
*cachetop = (drccodeptr)dst;
933
drccache_end_codegen(drcbe->cache);
936
if (drcbe->log != NULL)
937
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drccache_top(drcbe->cache));
939
/* tell all of our utility objects that the block is finished */
940
drchash_block_end(drcbe->hash, block);
941
drclabel_block_end(drcbe->labels, block);
942
drcmap_block_end(drcbe->map, block);
946
/*-------------------------------------------------
947
drcbex86_hash_exists - return true if the
948
given mode/pc exists in the hash table
949
-------------------------------------------------*/
951
static int drcbex86_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
953
return drchash_code_exists(drcbe->hash, mode, pc);
957
/*-------------------------------------------------
958
drcbex86_get_info - return information about
959
the back-end implementation
960
-------------------------------------------------*/
962
static void drcbex86_get_info(drcbe_state *state, drcbe_info *info)
964
for (info->direct_iregs = 0; info->direct_iregs < DRCUML_REG_I_END - DRCUML_REG_I0; info->direct_iregs++)
965
if (int_register_map[info->direct_iregs] == 0)
967
info->direct_fregs = 0;
972
/***************************************************************************
974
***************************************************************************/
976
/*-------------------------------------------------
977
param_normalize - convert a full parameter
979
-------------------------------------------------*/
981
static void param_normalize(drcbe_state *drcbe, const drcuml_parameter *src, drcuml_parameter *dest, UINT32 allowed)
987
/* immediates pass through */
988
case DRCUML_PTYPE_IMMEDIATE:
989
assert(allowed & PTYPE_I);
990
dest->type = DRCUML_PTYPE_IMMEDIATE;
991
dest->value = src->value;
994
/* memory passes through */
995
case DRCUML_PTYPE_MEMORY:
996
assert(allowed & PTYPE_M);
997
dest->type = DRCUML_PTYPE_MEMORY;
998
dest->value = src->value;
1001
/* if a register maps to a register, keep it as a register; otherwise map it to memory */
1002
case DRCUML_PTYPE_INT_REGISTER:
1003
assert(allowed & PTYPE_R);
1004
assert(allowed & PTYPE_M);
1005
regnum = int_register_map[src->value - DRCUML_REG_I0];
1008
dest->type = DRCUML_PTYPE_INT_REGISTER;
1009
dest->value = regnum;
1013
dest->type = DRCUML_PTYPE_MEMORY;
1014
dest->value = (FPTR)&drcbe->state.r[src->value - DRCUML_REG_I0];
1018
/* all floating point registers map to memory */
1019
case DRCUML_PTYPE_FLOAT_REGISTER:
1020
assert(allowed & PTYPE_F);
1021
assert(allowed & PTYPE_M);
1022
dest->type = DRCUML_PTYPE_MEMORY;
1023
dest->value = (FPTR)&drcbe->state.f[src->value - DRCUML_REG_F0];
1026
/* everything else is unexpected */
1028
fatalerror("Unexpected parameter type");
1034
/*-------------------------------------------------
1035
param_normalize_1 - normalize a single
1036
parameter instruction
1037
-------------------------------------------------*/
1039
static void param_normalize_1(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0)
1041
assert(inst->numparams == 1);
1042
param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1046
/*-------------------------------------------------
1047
param_normalize_2 - normalize a 2
1048
parameter instruction
1049
-------------------------------------------------*/
1051
static void param_normalize_2(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1)
1053
assert(inst->numparams == 2);
1054
param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1055
param_normalize(drcbe, &inst->param[1], dest1, allowed1);
1059
/*-------------------------------------------------
1060
param_normalize_2_commutative - normalize a 2
1061
parameter instruction, shuffling the
1062
parameters on the assumption that the two
1063
parameters can be swapped
1064
-------------------------------------------------*/
1066
static void param_normalize_2_commutative(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1)
1068
param_normalize_2(drcbe, inst, dest0, allowed0, dest1, allowed1);
1070
/* if the inner parameter is a memory operand, push it to the outer */
1071
if (dest0->type == DRCUML_PTYPE_MEMORY)
1073
drcuml_parameter temp = *dest0;
1078
/* if the inner parameter is an immediate, push it to the outer */
1079
if (dest0->type == DRCUML_PTYPE_IMMEDIATE)
1081
drcuml_parameter temp = *dest0;
1088
/*-------------------------------------------------
1089
param_normalize_3 - normalize a 3
1090
parameter instruction
1091
-------------------------------------------------*/
1093
static void param_normalize_3(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1, drcuml_parameter *dest2, UINT32 allowed2)
1095
assert(inst->numparams == 3);
1096
param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1097
param_normalize(drcbe, &inst->param[1], dest1, allowed1);
1098
param_normalize(drcbe, &inst->param[2], dest2, allowed2);
1102
/*-------------------------------------------------
1103
param_normalize_3_commutative - normalize a 3
1104
parameter instruction, shuffling the
1105
parameters on the assumption that the last
1107
-------------------------------------------------*/
1109
static void param_normalize_3_commutative(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1, drcuml_parameter *dest2, UINT32 allowed2)
1111
param_normalize_3(drcbe, inst, dest0, allowed0, dest1, allowed1, dest2, allowed2);
1113
/* if the inner parameter is a memory operand, push it to the outer */
1114
if (dest1->type == DRCUML_PTYPE_MEMORY)
1116
drcuml_parameter temp = *dest1;
1121
/* if the inner parameter is an immediate, push it to the outer */
1122
if (dest1->type == DRCUML_PTYPE_IMMEDIATE)
1124
drcuml_parameter temp = *dest1;
1129
/* if the destination and outer parameters are equal, move the outer to the inner */
1130
if (dest0->type == dest2->type && dest0->value == dest2->value && dest0->type != DRCUML_PTYPE_IMMEDIATE)
1132
drcuml_parameter temp = *dest1;
1139
/*-------------------------------------------------
1140
param_normalize_4 - normalize a 4
1141
parameter instruction
1142
-------------------------------------------------*/
1144
static void param_normalize_4(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1, drcuml_parameter *dest2, UINT32 allowed2, drcuml_parameter *dest3, UINT32 allowed3)
1146
assert(inst->numparams == 4);
1147
param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1148
param_normalize(drcbe, &inst->param[1], dest1, allowed1);
1149
param_normalize(drcbe, &inst->param[2], dest2, allowed2);
1150
param_normalize(drcbe, &inst->param[3], dest3, allowed3);
1154
/*-------------------------------------------------
1155
param_normalize_4_commutative - normalize a 4
1156
parameter instruction, shuffling the
1157
parameters on the assumption that the last
1159
-------------------------------------------------*/
1161
static void param_normalize_4_commutative(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1, drcuml_parameter *dest2, UINT32 allowed2, drcuml_parameter *dest3, UINT32 allowed3)
1163
param_normalize_4(drcbe, inst, dest0, allowed0, dest1, allowed1, dest2, allowed2, dest3, allowed3);
1165
/* if the inner parameter is a memory operand, push it to the outer */
1166
if (dest2->type == DRCUML_PTYPE_MEMORY)
1168
drcuml_parameter temp = *dest2;
1173
/* if the inner parameter is an immediate, push it to the outer */
1174
if (dest2->type == DRCUML_PTYPE_IMMEDIATE)
1176
drcuml_parameter temp = *dest2;
1181
/* if the destination and outer parameters are equal, move the outer to the inner */
1182
if (dest0->type == dest3->type && dest0->value == dest3->value && dest0->type != DRCUML_PTYPE_IMMEDIATE)
1184
drcuml_parameter temp = *dest2;
1192
/***************************************************************************
1193
EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
1194
***************************************************************************/
1196
/*-------------------------------------------------
1197
emit_mov_r32_p32 - move a 32-bit parameter
1199
-------------------------------------------------*/
1201
static void emit_mov_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param)
1203
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1205
if (param->value == 0)
1206
emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
1208
emit_mov_r32_imm(dst, reg, param->value); // mov reg,param
1210
else if (param->type == DRCUML_PTYPE_MEMORY)
1211
emit_mov_r32_m32(dst, reg, MABS(param->value)); // mov reg,[param]
1212
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1214
if (reg != param->value)
1215
emit_mov_r32_r32(dst, reg, param->value); // mov reg,param
1220
/*-------------------------------------------------
1221
emit_mov_r32_p32_keepflags - move a 32-bit
1222
parameter into a register without affecting
1224
-------------------------------------------------*/
1226
static void emit_mov_r32_p32_keepflags(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param)
1228
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1229
emit_mov_r32_imm(dst, reg, param->value); // mov reg,param
1230
else if (param->type == DRCUML_PTYPE_MEMORY)
1232
if (!can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reg))
1233
emit_mov_r32_m32(dst, reg, MABS(param->value)); // mov reg,[param]
1235
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1237
if (reg != param->value)
1238
emit_mov_r32_r32(dst, reg, param->value); // mov reg,param
1243
/*-------------------------------------------------
1244
emit_mov_m32_p32 - move a 32-bit parameter
1245
into a memory location
1246
-------------------------------------------------*/
1248
static void emit_mov_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param)
1250
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1251
emit_mov_m32_imm(dst, MEMPARAMS, param->value); // mov [mem],param
1252
else if (param->type == DRCUML_PTYPE_MEMORY)
1254
if (!can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), REG_EAX))
1255
emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
1256
emit_mov_m32_r32(dst, MEMPARAMS, REG_EAX); // mov [mem],eax
1258
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1259
emit_mov_m32_r32(dst, MEMPARAMS, param->value); // mov [mem],param
1263
/*-------------------------------------------------
1264
emit_mov_p32_r32 - move a register into a
1266
-------------------------------------------------*/
1268
static void emit_mov_p32_r32(drcbe_state *drcbe, x86code **dst, const drcuml_parameter *param, UINT8 reg)
1270
assert(param->type != DRCUML_PTYPE_IMMEDIATE);
1271
if (param->type == DRCUML_PTYPE_MEMORY)
1273
emit_mov_m32_r32(dst, MABS(param->value), reg); // mov [param],reg
1274
set_last_lower_reg(drcbe, *dst, param, reg);
1276
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1278
if (reg != param->value)
1279
emit_mov_r32_r32(dst, param->value, reg); // mov param,reg
1284
/*-------------------------------------------------
1285
emit_add_r32_p32 - add operation to a 32-bit
1286
register from a 32-bit parameter
1287
-------------------------------------------------*/
1289
static void emit_add_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1291
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1293
if (inst->flags != 0 || param->value != 0)
1294
emit_add_r32_imm(dst, reg, param->value); // add reg,param
1296
else if (param->type == DRCUML_PTYPE_MEMORY)
1297
emit_add_r32_m32(dst, reg, MABS(param->value)); // add reg,[param]
1298
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1299
emit_add_r32_r32(dst, reg, param->value); // add reg,param
1303
/*-------------------------------------------------
1304
emit_add_m32_p32 - add operation to a 32-bit
1305
memory location from a 32-bit parameter
1306
-------------------------------------------------*/
1308
static void emit_add_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1310
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1312
if (inst->flags != 0 || param->value != 0)
1313
emit_add_m32_imm(dst, MEMPARAMS, param->value); // add [dest],param
1317
int reg = param_select_register(REG_EAX, param, NULL);
1318
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1319
emit_add_m32_r32(dst, MEMPARAMS, reg); // add [dest],reg
1324
/*-------------------------------------------------
1325
emit_adc_r32_p32 - adc operation to a 32-bit
1326
register from a 32-bit parameter
1327
-------------------------------------------------*/
1329
static void emit_adc_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1331
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1332
emit_adc_r32_imm(dst, reg, param->value); // adc reg,param
1333
else if (param->type == DRCUML_PTYPE_MEMORY)
1334
emit_adc_r32_m32(dst, reg, MABS(param->value)); // adc reg,[param]
1335
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1336
emit_adc_r32_r32(dst, reg, param->value); // adc reg,param
1340
/*-------------------------------------------------
1341
emit_adc_m32_p32 - adc operation to a 32-bit
1342
memory location from a 32-bit parameter
1343
-------------------------------------------------*/
1345
static void emit_adc_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1347
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1348
emit_adc_m32_imm(dst, MEMPARAMS, param->value); // adc [dest],param
1351
int reg = param_select_register(REG_EAX, param, NULL);
1352
emit_mov_r32_p32_keepflags(drcbe, dst, reg, param); // mov reg,param
1353
emit_adc_m32_r32(dst, MEMPARAMS, reg); // adc [dest],reg
1358
/*-------------------------------------------------
1359
emit_sub_r32_p32 - sub operation to a 32-bit
1360
register from a 32-bit parameter
1361
-------------------------------------------------*/
1363
static void emit_sub_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1365
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1367
if (inst->flags != 0 || param->value != 0)
1368
emit_sub_r32_imm(dst, reg, param->value); // sub reg,param
1370
else if (param->type == DRCUML_PTYPE_MEMORY)
1371
emit_sub_r32_m32(dst, reg, MABS(param->value)); // sub reg,[param]
1372
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1373
emit_sub_r32_r32(dst, reg, param->value); // sub reg,param
1377
/*-------------------------------------------------
1378
emit_sub_m32_p32 - sub operation to a 32-bit
1379
memory location from a 32-bit parameter
1380
-------------------------------------------------*/
1382
static void emit_sub_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1384
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1386
if (inst->flags != 0 || param->value != 0)
1387
emit_sub_m32_imm(dst, MEMPARAMS, param->value); // sub [dest],param
1391
int reg = param_select_register(REG_EAX, param, NULL);
1392
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1393
emit_sub_m32_r32(dst, MEMPARAMS, reg); // sub [dest],reg
1398
/*-------------------------------------------------
1399
emit_sbb_r32_p32 - sbb operation to a 32-bit
1400
register from a 32-bit parameter
1401
-------------------------------------------------*/
1403
static void emit_sbb_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1405
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1406
emit_sbb_r32_imm(dst, reg, param->value); // sbb reg,param
1407
else if (param->type == DRCUML_PTYPE_MEMORY)
1408
emit_sbb_r32_m32(dst, reg, MABS(param->value)); // sbb reg,[param]
1409
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1410
emit_sbb_r32_r32(dst, reg, param->value); // sbb reg,param
1414
/*-------------------------------------------------
1415
emit_sbb_m32_p32 - sbb operation to a 32-bit
1416
memory location from a 32-bit parameter
1417
-------------------------------------------------*/
1419
static void emit_sbb_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1421
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1422
emit_sbb_m32_imm(dst, MEMPARAMS, param->value); // sbb [dest],param
1425
int reg = param_select_register(REG_EAX, param, NULL);
1426
emit_mov_r32_p32_keepflags(drcbe, dst, reg, param); // mov reg,param
1427
emit_sbb_m32_r32(dst, MEMPARAMS, reg); // sbb [dest],reg
1432
/*-------------------------------------------------
1433
emit_cmp_r32_p32 - cmp operation to a 32-bit
1434
register from a 32-bit parameter
1435
-------------------------------------------------*/
1437
static void emit_cmp_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1439
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1440
emit_cmp_r32_imm(dst, reg, param->value); // cmp reg,param
1441
else if (param->type == DRCUML_PTYPE_MEMORY)
1442
emit_cmp_r32_m32(dst, reg, MABS(param->value)); // cmp reg,[param]
1443
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1444
emit_cmp_r32_r32(dst, reg, param->value); // cmp reg,param
1448
/*-------------------------------------------------
1449
emit_cmp_m32_p32 - cmp operation to a 32-bit
1450
memory location from a 32-bit parameter
1451
-------------------------------------------------*/
1453
static void emit_cmp_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1455
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1456
emit_cmp_m32_imm(dst, MEMPARAMS, param->value); // cmp [dest],param
1459
int reg = param_select_register(REG_EAX, param, NULL);
1460
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1461
emit_cmp_m32_r32(dst, MEMPARAMS, reg); // cmp [dest],reg
1466
/*-------------------------------------------------
1467
emit_and_r32_p32 - and operation to a 32-bit
1468
register from a 32-bit parameter
1469
-------------------------------------------------*/
1471
static void emit_and_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1473
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1475
if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1477
else if (inst->flags == 0 && (UINT32)param->value == 0)
1478
emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
1480
emit_and_r32_imm(dst, reg, param->value); // and reg,param
1482
else if (param->type == DRCUML_PTYPE_MEMORY)
1483
emit_and_r32_m32(dst, reg, MABS(param->value)); // and reg,[param]
1484
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1485
emit_and_r32_r32(dst, reg, param->value); // and reg,param
1489
/*-------------------------------------------------
1490
emit_and_m32_p32 - and operation to a 32-bit
1491
memory location from a 32-bit parameter
1492
-------------------------------------------------*/
1494
static void emit_and_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1496
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1498
if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1500
else if (inst->flags == 0 && (UINT32)param->value == 0)
1501
emit_mov_m32_imm(dst, MEMPARAMS, 0); // mov [dest],0
1503
emit_and_m32_imm(dst, MEMPARAMS, param->value); // and [dest],param
1507
int reg = param_select_register(REG_EAX, param, NULL);
1508
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1509
emit_and_m32_r32(dst, MEMPARAMS, reg); // and [dest],reg
1514
/*-------------------------------------------------
1515
emit_test_r32_p32 - test operation to a 32-bit
1516
register from a 32-bit parameter
1517
-------------------------------------------------*/
1519
static void emit_test_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1521
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1522
emit_test_r32_imm(dst, reg, param->value); // test reg,param
1523
else if (param->type == DRCUML_PTYPE_MEMORY)
1524
emit_test_m32_r32(dst, MABS(param->value), reg); // test [param],reg
1525
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1526
emit_test_r32_r32(dst, reg, param->value); // test reg,param
1530
/*-------------------------------------------------
1531
emit_test_m32_p32 - test operation to a 32-bit
1532
memory location from a 32-bit parameter
1533
-------------------------------------------------*/
1535
static void emit_test_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1537
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1538
emit_test_m32_imm(dst, MEMPARAMS, param->value); // test [dest],param
1539
else if (param->type == DRCUML_PTYPE_MEMORY)
1541
emit_mov_r32_p32(drcbe, dst, REG_EAX, param); // mov reg,param
1542
emit_test_m32_r32(dst, MEMPARAMS, REG_EAX); // test [dest],reg
1544
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1545
emit_test_m32_r32(dst, MEMPARAMS, param->value); // test [dest],param
1549
/*-------------------------------------------------
1550
emit_or_r32_p32 - or operation to a 32-bit
1551
register from a 32-bit parameter
1552
-------------------------------------------------*/
1554
static void emit_or_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1556
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1558
if (inst->flags == 0 && (UINT32)param->value == 0)
1560
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
827
m_cache.end_codegen();
831
x86log_disasm_code_range(m_log, (blockname == NULL) ? "Unknown block" : blockname, base, m_cache.top());
833
// tell all of our utility objects that the block is finished
834
m_hash.block_end(block);
835
m_labels.block_end(block);
836
m_map.block_end(block);
840
//-------------------------------------------------
841
// drcbex86_hash_exists - return true if the
842
// given mode/pc exists in the hash table
843
//-------------------------------------------------
845
bool drcbe_x86::hash_exists(UINT32 mode, UINT32 pc)
847
return m_hash.code_exists(mode, pc);
851
//-------------------------------------------------
852
// drcbex86_get_info - return information about
853
// the back-end implementation
854
//-------------------------------------------------
856
void drcbe_x86::get_info(drcbe_info &info)
858
for (info.direct_iregs = 0; info.direct_iregs < REG_I_COUNT; info.direct_iregs++)
859
if (int_register_map[info.direct_iregs] == 0)
861
info.direct_fregs = 0;
866
//**************************************************************************
867
// EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
868
//**************************************************************************
870
//-------------------------------------------------
871
// emit_mov_r32_p32 - move a 32-bit parameter
873
//-------------------------------------------------
875
void drcbe_x86::emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m)
877
if (param.is_immediate())
879
if (param.immediate() == 0)
880
emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
882
emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
884
else if (param.is_memory())
885
emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
886
else if (param.is_int_register())
888
if (reg != param.ireg())
889
emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
894
//-------------------------------------------------
895
// emit_mov_r32_p32_keepflags - move a 32-bit
896
// parameter into a register without affecting
898
//-------------------------------------------------
900
void drcbe_x86::emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter ¶m)
902
if (param.is_immediate())
903
emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
904
else if (param.is_memory())
906
if (!can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reg))
907
emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
909
else if (param.is_int_register())
911
if (reg != param.ireg())
912
emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
917
//-------------------------------------------------
918
// emit_mov_m32_p32 - move a 32-bit parameter
919
// into a memory location
920
//-------------------------------------------------
922
void drcbe_x86::emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m)
924
if (param.is_immediate())
925
emit_mov_m32_imm(dst, memref, param.immediate()); // mov [mem],param
926
else if (param.is_memory())
928
if (!can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), REG_EAX))
929
emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param]
930
emit_mov_m32_r32(dst, memref, REG_EAX); // mov [mem],eax
932
else if (param.is_int_register())
933
emit_mov_m32_r32(dst, memref, param.ireg()); // mov [mem],param
937
//-------------------------------------------------
938
// emit_mov_p32_r32 - move a register into a
940
//-------------------------------------------------
942
void drcbe_x86::emit_mov_p32_r32(x86code *&dst, const be_parameter ¶m, UINT8 reg)
944
assert(!param.is_immediate());
945
if (param.is_memory())
947
emit_mov_m32_r32(dst, MABS(param.memory()), reg); // mov [param],reg
948
set_last_lower_reg(dst, param, reg);
950
else if (param.is_int_register())
952
if (reg != param.ireg())
953
emit_mov_r32_r32(dst, param.ireg(), reg); // mov param,reg
958
//-------------------------------------------------
959
// emit_add_r32_p32 - add operation to a 32-bit
960
// register from a 32-bit parameter
961
//-------------------------------------------------
963
void drcbe_x86::emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
965
if (param.is_immediate())
967
if (inst.flags() != 0 || param.immediate() != 0)
968
emit_add_r32_imm(dst, reg, param.immediate()); // add reg,param
970
else if (param.is_memory())
971
emit_add_r32_m32(dst, reg, MABS(param.memory())); // add reg,[param]
972
else if (param.is_int_register())
973
emit_add_r32_r32(dst, reg, param.ireg()); // add reg,param
977
//-------------------------------------------------
978
// emit_add_m32_p32 - add operation to a 32-bit
979
// memory location from a 32-bit parameter
980
//-------------------------------------------------
982
void drcbe_x86::emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
984
if (param.is_immediate())
986
if (inst.flags() != 0 || param.immediate() != 0)
987
emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param
991
int reg = param.select_register(REG_EAX);
992
emit_mov_r32_p32(dst, reg, param); // mov reg,param
993
emit_add_m32_r32(dst, memref, reg); // add [dest],reg
998
//-------------------------------------------------
999
// emit_adc_r32_p32 - adc operation to a 32-bit
1000
// register from a 32-bit parameter
1001
//-------------------------------------------------
1003
void drcbe_x86::emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1005
if (param.is_immediate())
1006
emit_adc_r32_imm(dst, reg, param.immediate()); // adc reg,param
1007
else if (param.is_memory())
1008
emit_adc_r32_m32(dst, reg, MABS(param.memory())); // adc reg,[param]
1009
else if (param.is_int_register())
1010
emit_adc_r32_r32(dst, reg, param.ireg()); // adc reg,param
1014
//-------------------------------------------------
1015
// emit_adc_m32_p32 - adc operation to a 32-bit
1016
// memory location from a 32-bit parameter
1017
//-------------------------------------------------
1019
void drcbe_x86::emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1021
if (param.is_immediate())
1022
emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param
1025
int reg = param.select_register(REG_EAX);
1026
emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
1027
emit_adc_m32_r32(dst, memref, reg); // adc [dest],reg
1032
//-------------------------------------------------
1033
// emit_sub_r32_p32 - sub operation to a 32-bit
1034
// register from a 32-bit parameter
1035
//-------------------------------------------------
1037
void drcbe_x86::emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1039
if (param.is_immediate())
1041
if (inst.flags() != 0 || param.immediate() != 0)
1042
emit_sub_r32_imm(dst, reg, param.immediate()); // sub reg,param
1044
else if (param.is_memory())
1045
emit_sub_r32_m32(dst, reg, MABS(param.memory())); // sub reg,[param]
1046
else if (param.is_int_register())
1047
emit_sub_r32_r32(dst, reg, param.ireg()); // sub reg,param
1051
//-------------------------------------------------
1052
// emit_sub_m32_p32 - sub operation to a 32-bit
1053
// memory location from a 32-bit parameter
1054
//-------------------------------------------------
1056
void drcbe_x86::emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1058
if (param.is_immediate())
1060
if (inst.flags() != 0 || param.immediate() != 0)
1061
emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param
1065
int reg = param.select_register(REG_EAX);
1066
emit_mov_r32_p32(dst, reg, param); // mov reg,param
1067
emit_sub_m32_r32(dst, memref, reg); // sub [dest],reg
1072
//-------------------------------------------------
1073
// emit_sbb_r32_p32 - sbb operation to a 32-bit
1074
// register from a 32-bit parameter
1075
//-------------------------------------------------
1077
void drcbe_x86::emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1079
if (param.is_immediate())
1080
emit_sbb_r32_imm(dst, reg, param.immediate()); // sbb reg,param
1081
else if (param.is_memory())
1082
emit_sbb_r32_m32(dst, reg, MABS(param.memory())); // sbb reg,[param]
1083
else if (param.is_int_register())
1084
emit_sbb_r32_r32(dst, reg, param.ireg()); // sbb reg,param
1088
//-------------------------------------------------
1089
// emit_sbb_m32_p32 - sbb operation to a 32-bit
1090
// memory location from a 32-bit parameter
1091
//-------------------------------------------------
1093
void drcbe_x86::emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1095
if (param.is_immediate())
1096
emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param
1099
int reg = param.select_register(REG_EAX);
1100
emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
1101
emit_sbb_m32_r32(dst, memref, reg); // sbb [dest],reg
1106
//-------------------------------------------------
1107
// emit_cmp_r32_p32 - cmp operation to a 32-bit
1108
// register from a 32-bit parameter
1109
//-------------------------------------------------
1111
void drcbe_x86::emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1113
if (param.is_immediate())
1114
emit_cmp_r32_imm(dst, reg, param.immediate()); // cmp reg,param
1115
else if (param.is_memory())
1116
emit_cmp_r32_m32(dst, reg, MABS(param.memory())); // cmp reg,[param]
1117
else if (param.is_int_register())
1118
emit_cmp_r32_r32(dst, reg, param.ireg()); // cmp reg,param
1122
//-------------------------------------------------
1123
// emit_cmp_m32_p32 - cmp operation to a 32-bit
1124
// memory location from a 32-bit parameter
1125
//-------------------------------------------------
1127
void drcbe_x86::emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1129
if (param.is_immediate())
1130
emit_cmp_m32_imm(dst, memref, param.immediate()); // cmp [dest],param
1133
int reg = param.select_register(REG_EAX);
1134
emit_mov_r32_p32(dst, reg, param); // mov reg,param
1135
emit_cmp_m32_r32(dst, memref, reg); // cmp [dest],reg
1140
//-------------------------------------------------
1141
// emit_and_r32_p32 - and operation to a 32-bit
1142
// register from a 32-bit parameter
1143
//-------------------------------------------------
1145
void drcbe_x86::emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1147
if (param.is_immediate())
1149
if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1151
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1152
emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
1154
emit_and_r32_imm(dst, reg, param.immediate()); // and reg,param
1156
else if (param.is_memory())
1157
emit_and_r32_m32(dst, reg, MABS(param.memory())); // and reg,[param]
1158
else if (param.is_int_register())
1159
emit_and_r32_r32(dst, reg, param.ireg()); // and reg,param
1163
//-------------------------------------------------
1164
// emit_and_m32_p32 - and operation to a 32-bit
1165
// memory location from a 32-bit parameter
1166
//-------------------------------------------------
1168
void drcbe_x86::emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1170
if (param.is_immediate())
1172
if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1174
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1175
emit_mov_m32_imm(dst, memref, 0); // mov [dest],0
1177
emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param
1181
int reg = param.select_register(REG_EAX);
1182
emit_mov_r32_p32(dst, reg, param); // mov reg,param
1183
emit_and_m32_r32(dst, memref, reg); // and [dest],reg
1188
//-------------------------------------------------
1189
// emit_test_r32_p32 - test operation to a 32-bit
1190
// register from a 32-bit parameter
1191
//-------------------------------------------------
1193
void drcbe_x86::emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1195
if (param.is_immediate())
1196
emit_test_r32_imm(dst, reg, param.immediate()); // test reg,param
1197
else if (param.is_memory())
1198
emit_test_m32_r32(dst, MABS(param.memory()), reg); // test [param],reg
1199
else if (param.is_int_register())
1200
emit_test_r32_r32(dst, reg, param.ireg()); // test reg,param
1204
//-------------------------------------------------
1205
// emit_test_m32_p32 - test operation to a 32-bit
1206
// memory location from a 32-bit parameter
1207
//-------------------------------------------------
1209
void drcbe_x86::emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1211
if (param.is_immediate())
1212
emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param
1213
else if (param.is_memory())
1215
emit_mov_r32_p32(dst, REG_EAX, param); // mov reg,param
1216
emit_test_m32_r32(dst, memref, REG_EAX); // test [dest],reg
1218
else if (param.is_int_register())
1219
emit_test_m32_r32(dst, memref, param.ireg()); // test [dest],param
1223
//-------------------------------------------------
1224
// emit_or_r32_p32 - or operation to a 32-bit
1225
// register from a 32-bit parameter
1226
//-------------------------------------------------
1228
void drcbe_x86::emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1230
if (param.is_immediate())
1232
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1234
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1561
1235
emit_mov_r32_imm(dst, reg, ~0); // mov reg,-1
1563
emit_or_r32_imm(dst, reg, param->value); // or reg,param
1237
emit_or_r32_imm(dst, reg, param.immediate()); // or reg,param
1565
else if (param->type == DRCUML_PTYPE_MEMORY)
1566
emit_or_r32_m32(dst, reg, MABS(param->value)); // or reg,[param]
1567
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1568
emit_or_r32_r32(dst, reg, param->value); // or reg,param
1239
else if (param.is_memory())
1240
emit_or_r32_m32(dst, reg, MABS(param.memory())); // or reg,[param]
1241
else if (param.is_int_register())
1242
emit_or_r32_r32(dst, reg, param.ireg()); // or reg,param
1572
/*-------------------------------------------------
1573
emit_or_m32_p32 - or operation to a 32-bit
1574
memory location from a 32-bit parameter
1575
-------------------------------------------------*/
1246
//-------------------------------------------------
1247
// emit_or_m32_p32 - or operation to a 32-bit
1248
// memory location from a 32-bit parameter
1249
//-------------------------------------------------
1577
static void emit_or_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1251
void drcbe_x86::emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1579
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1253
if (param.is_immediate())
1581
if (inst->flags == 0 && (UINT32)param->value == 0)
1583
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1584
emit_mov_m32_imm(dst, MEMPARAMS, ~0); // mov [dest],-1
1255
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1257
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1258
emit_mov_m32_imm(dst, memref, ~0); // mov [dest],-1
1586
emit_or_m32_imm(dst, MEMPARAMS, param->value); // or [dest],param
1260
emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param
1590
int reg = param_select_register(REG_EAX, param, NULL);
1591
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1592
emit_or_m32_r32(dst, MEMPARAMS, reg); // or [dest],reg
1264
int reg = param.select_register(REG_EAX);
1265
emit_mov_r32_p32(dst, reg, param); // mov reg,param
1266
emit_or_m32_r32(dst, memref, reg); // or [dest],reg
1597
/*-------------------------------------------------
1598
emit_xor_r32_p32 - xor operation to a 32-bit
1599
register from a 32-bit parameter
1600
-------------------------------------------------*/
1271
//-------------------------------------------------
1272
// emit_xor_r32_p32 - xor operation to a 32-bit
1273
// register from a 32-bit parameter
1274
//-------------------------------------------------
1602
static void emit_xor_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1276
void drcbe_x86::emit_xor_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1604
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1278
if (param.is_immediate())
1606
if (inst->flags == 0 && (UINT32)param->value == 0)
1608
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1280
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1282
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1609
1283
emit_not_r32(dst, reg); // not reg
1611
emit_xor_r32_imm(dst, reg, param->value); // xor reg,param
1613
else if (param->type == DRCUML_PTYPE_MEMORY)
1614
emit_xor_r32_m32(dst, reg, MABS(param->value)); // xor reg,[param]
1615
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1616
emit_xor_r32_r32(dst, reg, param->value); // xor reg,param
1620
/*-------------------------------------------------
1621
emit_xor_m32_p32 - xor operation to a 32-bit
1622
memory location from a 32-bit parameter
1623
-------------------------------------------------*/
1625
static void emit_xor_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1627
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1629
if (inst->flags == 0 && (UINT32)param->value == 0)
1631
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1632
emit_not_m32(dst, MEMPARAMS); // not [dest]
1634
emit_xor_m32_imm(dst, MEMPARAMS, param->value); // xor [dest],param
1638
int reg = param_select_register(REG_EAX, param, NULL);
1639
emit_mov_r32_p32(drcbe, dst, reg, param); // mov reg,param
1640
emit_xor_m32_r32(dst, MEMPARAMS, reg); // xor [dest],reg
1645
/*-------------------------------------------------
1646
emit_shl_r32_p32 - shl operation to a 32-bit
1647
register from a 32-bit parameter
1648
-------------------------------------------------*/
1650
static void emit_shl_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1652
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1654
if (inst->flags == 0 && (UINT32)param->value == 0)
1657
emit_shl_r32_imm(dst, reg, param->value); // shl reg,param
1661
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1285
emit_xor_r32_imm(dst, reg, param.immediate()); // xor reg,param
1287
else if (param.is_memory())
1288
emit_xor_r32_m32(dst, reg, MABS(param.memory())); // xor reg,[param]
1289
else if (param.is_int_register())
1290
emit_xor_r32_r32(dst, reg, param.ireg()); // xor reg,param
1294
//-------------------------------------------------
1295
// emit_xor_m32_p32 - xor operation to a 32-bit
1296
// memory location from a 32-bit parameter
1297
//-------------------------------------------------
1299
void drcbe_x86::emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1301
if (param.is_immediate())
1303
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1305
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1306
emit_not_m32(dst, memref); // not [dest]
1308
emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param
1312
int reg = param.select_register(REG_EAX);
1313
emit_mov_r32_p32(dst, reg, param); // mov reg,param
1314
emit_xor_m32_r32(dst, memref, reg); // xor [dest],reg
1319
//-------------------------------------------------
1320
// emit_shl_r32_p32 - shl operation to a 32-bit
1321
// register from a 32-bit parameter
1322
//-------------------------------------------------
1324
void drcbe_x86::emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1326
if (param.is_immediate())
1328
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1331
emit_shl_r32_imm(dst, reg, param.immediate()); // shl reg,param
1335
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1662
1336
emit_shl_r32_cl(dst, reg); // shl reg,cl
1667
/*-------------------------------------------------
1668
emit_shl_m32_p32 - shl operation to a 32-bit
1669
memory location from a 32-bit parameter
1670
-------------------------------------------------*/
1341
//-------------------------------------------------
1342
// emit_shl_m32_p32 - shl operation to a 32-bit
1343
// memory location from a 32-bit parameter
1344
//-------------------------------------------------
1672
static void emit_shl_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1346
void drcbe_x86::emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1674
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1348
if (param.is_immediate())
1676
if (inst->flags == 0 && (UINT32)param->value == 0)
1350
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1679
emit_shl_m32_imm(dst, MEMPARAMS, param->value); // shl [dest],param
1353
emit_shl_m32_imm(dst, memref, param.immediate()); // shl [dest],param
1683
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1684
emit_shl_m32_cl(dst, MEMPARAMS); // shl [dest],cl
1357
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1358
emit_shl_m32_cl(dst, memref); // shl [dest],cl
1689
/*-------------------------------------------------
1690
emit_shr_r32_p32 - shr operation to a 32-bit
1691
register from a 32-bit parameter
1692
-------------------------------------------------*/
1363
//-------------------------------------------------
1364
// emit_shr_r32_p32 - shr operation to a 32-bit
1365
// register from a 32-bit parameter
1366
//-------------------------------------------------
1694
static void emit_shr_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1368
void drcbe_x86::emit_shr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1696
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1370
if (param.is_immediate())
1698
if (inst->flags == 0 && (UINT32)param->value == 0)
1372
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1701
emit_shr_r32_imm(dst, reg, param->value); // shr reg,param
1375
emit_shr_r32_imm(dst, reg, param.immediate()); // shr reg,param
1705
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1379
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1706
1380
emit_shr_r32_cl(dst, reg); // shr reg,cl
1711
/*-------------------------------------------------
1712
emit_shr_m32_p32 - shr operation to a 32-bit
1713
memory location from a 32-bit parameter
1714
-------------------------------------------------*/
1385
//-------------------------------------------------
1386
// emit_shr_m32_p32 - shr operation to a 32-bit
1387
// memory location from a 32-bit parameter
1388
//-------------------------------------------------
1716
static void emit_shr_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1390
void drcbe_x86::emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1718
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1392
if (param.is_immediate())
1720
if (inst->flags == 0 && (UINT32)param->value == 0)
1394
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1723
emit_shr_m32_imm(dst, MEMPARAMS, param->value); // shr [dest],param
1397
emit_shr_m32_imm(dst, memref, param.immediate()); // shr [dest],param
1727
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1728
emit_shr_m32_cl(dst, MEMPARAMS); // shr [dest],cl
1401
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1402
emit_shr_m32_cl(dst, memref); // shr [dest],cl
1733
/*-------------------------------------------------
1734
emit_sar_r32_p32 - sar operation to a 32-bit
1735
register from a 32-bit parameter
1736
-------------------------------------------------*/
1407
//-------------------------------------------------
1408
// emit_sar_r32_p32 - sar operation to a 32-bit
1409
// register from a 32-bit parameter
1410
//-------------------------------------------------
1738
static void emit_sar_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1412
void drcbe_x86::emit_sar_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1740
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1414
if (param.is_immediate())
1742
if (inst->flags == 0 && (UINT32)param->value == 0)
1416
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1745
emit_sar_r32_imm(dst, reg, param->value); // sar reg,param
1419
emit_sar_r32_imm(dst, reg, param.immediate()); // sar reg,param
1749
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1423
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1750
1424
emit_sar_r32_cl(dst, reg); // sar reg,cl
1755
/*-------------------------------------------------
1756
emit_sar_m32_p32 - sar operation to a 32-bit
1757
memory location from a 32-bit parameter
1758
-------------------------------------------------*/
1429
//-------------------------------------------------
1430
// emit_sar_m32_p32 - sar operation to a 32-bit
1431
// memory location from a 32-bit parameter
1432
//-------------------------------------------------
1760
static void emit_sar_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1434
void drcbe_x86::emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1762
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1436
if (param.is_immediate())
1764
if (inst->flags == 0 && (UINT32)param->value == 0)
1438
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1767
emit_sar_m32_imm(dst, MEMPARAMS, param->value); // sar [dest],param
1441
emit_sar_m32_imm(dst, memref, param.immediate()); // sar [dest],param
1771
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1772
emit_sar_m32_cl(dst, MEMPARAMS); // sar [dest],cl
1445
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1446
emit_sar_m32_cl(dst, memref); // sar [dest],cl
1777
/*-------------------------------------------------
1778
emit_rol_r32_p32 - rol operation to a 32-bit
1779
register from a 32-bit parameter
1780
-------------------------------------------------*/
1451
//-------------------------------------------------
1452
// emit_rol_r32_p32 - rol operation to a 32-bit
1453
// register from a 32-bit parameter
1454
//-------------------------------------------------
1782
static void emit_rol_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1456
void drcbe_x86::emit_rol_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1784
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1458
if (param.is_immediate())
1786
if (inst->flags == 0 && (UINT32)param->value == 0)
1460
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1789
emit_rol_r32_imm(dst, reg, param->value); // rol reg,param
1463
emit_rol_r32_imm(dst, reg, param.immediate()); // rol reg,param
1793
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1467
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1794
1468
emit_rol_r32_cl(dst, reg); // rol reg,cl
1799
/*-------------------------------------------------
1800
emit_rol_m32_p32 - rol operation to a 32-bit
1801
memory location from a 32-bit parameter
1802
-------------------------------------------------*/
1473
//-------------------------------------------------
1474
// emit_rol_m32_p32 - rol operation to a 32-bit
1475
// memory location from a 32-bit parameter
1476
//-------------------------------------------------
1804
static void emit_rol_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1478
void drcbe_x86::emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1806
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1480
if (param.is_immediate())
1808
if (inst->flags == 0 && (UINT32)param->value == 0)
1482
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1811
emit_rol_m32_imm(dst, MEMPARAMS, param->value); // rol [dest],param
1485
emit_rol_m32_imm(dst, memref, param.immediate()); // rol [dest],param
1815
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1816
emit_rol_m32_cl(dst, MEMPARAMS); // rol [dest],cl
1489
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1490
emit_rol_m32_cl(dst, memref); // rol [dest],cl
1821
/*-------------------------------------------------
1822
emit_ror_r32_p32 - ror operation to a 32-bit
1823
register from a 32-bit parameter
1824
-------------------------------------------------*/
1495
//-------------------------------------------------
1496
// emit_ror_r32_p32 - ror operation to a 32-bit
1497
// register from a 32-bit parameter
1498
//-------------------------------------------------
1826
static void emit_ror_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1500
void drcbe_x86::emit_ror_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1828
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1502
if (param.is_immediate())
1830
if (inst->flags == 0 && (UINT32)param->value == 0)
1504
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1833
emit_ror_r32_imm(dst, reg, param->value); // ror reg,param
1507
emit_ror_r32_imm(dst, reg, param.immediate()); // ror reg,param
1837
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1511
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1838
1512
emit_ror_r32_cl(dst, reg); // ror reg,cl
1843
/*-------------------------------------------------
1844
emit_ror_m32_p32 - ror operation to a 32-bit
1845
memory location from a 32-bit parameter
1846
-------------------------------------------------*/
1517
//-------------------------------------------------
1518
// emit_ror_m32_p32 - ror operation to a 32-bit
1519
// memory location from a 32-bit parameter
1520
//-------------------------------------------------
1848
static void emit_ror_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1522
void drcbe_x86::emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1850
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1524
if (param.is_immediate())
1852
if (inst->flags == 0 && (UINT32)param->value == 0)
1526
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1855
emit_ror_m32_imm(dst, MEMPARAMS, param->value); // ror [dest],param
1529
emit_ror_m32_imm(dst, memref, param.immediate()); // ror [dest],param
1859
emit_mov_r32_p32(drcbe, dst, REG_ECX, param); // mov ecx,param
1860
emit_ror_m32_cl(dst, MEMPARAMS); // ror [dest],cl
1533
emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
1534
emit_ror_m32_cl(dst, memref); // ror [dest],cl
1865
/*-------------------------------------------------
1866
emit_rcl_r32_p32 - rcl operation to a 32-bit
1867
register from a 32-bit parameter
1868
-------------------------------------------------*/
1539
//-------------------------------------------------
1540
// emit_rcl_r32_p32 - rcl operation to a 32-bit
1541
// register from a 32-bit parameter
1542
//-------------------------------------------------
1870
static void emit_rcl_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1544
void drcbe_x86::emit_rcl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1872
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1546
if (param.is_immediate())
1874
if (inst->flags == 0 && (UINT32)param->value == 0)
1548
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1877
emit_rcl_r32_imm(dst, reg, param->value); // rcl reg,param
1551
emit_rcl_r32_imm(dst, reg, param.immediate()); // rcl reg,param
1881
emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param); // mov ecx,param
1555
emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
1882
1556
emit_rcl_r32_cl(dst, reg); // rcl reg,cl
1887
/*-------------------------------------------------
1888
emit_rcl_m32_p32 - rcl operation to a 32-bit
1889
memory location from a 32-bit parameter
1890
-------------------------------------------------*/
1561
//-------------------------------------------------
1562
// emit_rcl_m32_p32 - rcl operation to a 32-bit
1563
// memory location from a 32-bit parameter
1564
//-------------------------------------------------
1892
static void emit_rcl_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1566
void drcbe_x86::emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1894
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1568
if (param.is_immediate())
1896
if (inst->flags == 0 && (UINT32)param->value == 0)
1570
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1899
emit_rcl_m32_imm(dst, MEMPARAMS, param->value); // rcl [dest],param
1573
emit_rcl_m32_imm(dst, memref, param.immediate()); // rcl [dest],param
1903
emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param); // mov ecx,param
1904
emit_rcl_m32_cl(dst, MEMPARAMS); // rcl [dest],cl
1577
emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
1578
emit_rcl_m32_cl(dst, memref); // rcl [dest],cl
1909
/*-------------------------------------------------
1910
emit_rcr_r32_p32 - rcr operation to a 32-bit
1911
register from a 32-bit parameter
1912
-------------------------------------------------*/
1583
//-------------------------------------------------
1584
// emit_rcr_r32_p32 - rcr operation to a 32-bit
1585
// register from a 32-bit parameter
1586
//-------------------------------------------------
1914
static void emit_rcr_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1588
void drcbe_x86::emit_rcr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter ¶m, const instruction &inst)
1916
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1590
if (param.is_immediate())
1918
if (inst->flags == 0 && (UINT32)param->value == 0)
1592
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1921
emit_rcr_r32_imm(dst, reg, param->value); // rcr reg,param
1595
emit_rcr_r32_imm(dst, reg, param.immediate()); // rcr reg,param
1925
emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param); // mov ecx,param
1599
emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
1926
1600
emit_rcr_r32_cl(dst, reg); // rcr reg,cl
1931
/*-------------------------------------------------
1932
emit_rcr_m32_p32 - rcr operation to a 32-bit
1933
memory location from a 32-bit parameter
1934
-------------------------------------------------*/
1605
//-------------------------------------------------
1606
// emit_rcr_m32_p32 - rcr operation to a 32-bit
1607
// memory location from a 32-bit parameter
1608
//-------------------------------------------------
1936
static void emit_rcr_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1610
void drcbe_x86::emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1938
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1612
if (param.is_immediate())
1940
if (inst->flags == 0 && (UINT32)param->value == 0)
1614
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
1943
emit_rcr_m32_imm(dst, MEMPARAMS, param->value); // rcr [dest],param
1617
emit_rcr_m32_imm(dst, memref, param.immediate()); // rcr [dest],param
1947
emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param); // mov ecx,param
1948
emit_rcr_m32_cl(dst, MEMPARAMS); // rcr [dest],cl
1621
emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
1622
emit_rcr_m32_cl(dst, memref); // rcr [dest],cl
1954
/***************************************************************************
1955
EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS
1956
***************************************************************************/
1958
/*-------------------------------------------------
1959
emit_mov_r64_p64 - move a 64-bit parameter
1960
into a pair of registers
1961
-------------------------------------------------*/
1963
static void emit_mov_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param)
1628
//**************************************************************************
1629
// EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS
1630
//**************************************************************************
1632
//-------------------------------------------------
1633
// emit_mov_r64_p64 - move a 64-bit parameter
1634
// into a pair of registers
1635
//-------------------------------------------------
1637
void drcbe_x86::emit_mov_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m)
1965
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1639
if (param.is_immediate())
1967
1641
if (reglo == REG_NONE)
1969
else if ((UINT32)param->value == 0)
1643
else if ((UINT32)param.immediate() == 0)
1970
1644
emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
1972
emit_mov_r32_imm(dst, reglo, param->value); // mov reglo,param
1646
emit_mov_r32_imm(dst, reglo, param.immediate()); // mov reglo,param
1973
1647
if (reghi == REG_NONE)
1975
else if ((UINT32)(param->value >> 32) == 0)
1649
else if ((UINT32)(param.immediate() >> 32) == 0)
1976
1650
emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
1978
emit_mov_r32_imm(dst, reghi, param->value >> 32); // mov reghi,param >> 32
1652
emit_mov_r32_imm(dst, reghi, param.immediate() >> 32); // mov reghi,param >> 32
1980
else if (param->type == DRCUML_PTYPE_MEMORY)
1654
else if (param.is_memory())
1982
int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reglo);
1983
int skip_upper = can_skip_upper_load(drcbe, *dst, (UINT32 *)((FPTR)param->value + 4), reghi);
1656
int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reglo);
1657
int skip_upper = can_skip_upper_load(dst, (UINT32 *)((FPTR)param.memory(4)), reghi);
1984
1658
if (reglo != REG_NONE && !skip_lower)
1985
emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
1659
emit_mov_r32_m32(dst, reglo, MABS(param.memory())); // mov reglo,[param]
1986
1660
if (reghi != REG_NONE && !skip_upper)
1987
emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
1661
emit_mov_r32_m32(dst, reghi, MABS(param.memory(4))); // mov reghi,[param+4]
1989
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1663
else if (param.is_int_register())
1991
int skip_upper = can_skip_upper_load(drcbe, *dst, drcbe->reghi[param->value], reghi);
1992
if (reglo != REG_NONE && reglo != param->value)
1993
emit_mov_r32_r32(dst, reglo, param->value); // mov reglo,param
1665
int skip_upper = can_skip_upper_load(dst, m_reghi[param.ireg()], reghi);
1666
if (reglo != REG_NONE && reglo != param.ireg())
1667
emit_mov_r32_r32(dst, reglo, param.ireg()); // mov reglo,param
1994
1668
if (reghi != REG_NONE && !skip_upper)
1995
emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
1669
emit_mov_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // mov reghi,reghi[param]
2000
/*-------------------------------------------------
2001
emit_mov_r64_p64_keepflags - move a 64-bit
2002
parameter into a pair of registers without
2004
-------------------------------------------------*/
1674
//-------------------------------------------------
1675
// emit_mov_r64_p64_keepflags - move a 64-bit
1676
// parameter into a pair of registers without
1677
// affecting any flags
1678
//-------------------------------------------------
2006
static void emit_mov_r64_p64_keepflags(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param)
1680
void drcbe_x86::emit_mov_r64_p64_keepflags(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m)
2008
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1682
if (param.is_immediate())
2010
1684
if (reglo != REG_NONE)
2011
emit_mov_r32_imm(dst, reglo, param->value); // mov reglo,param
1685
emit_mov_r32_imm(dst, reglo, param.immediate()); // mov reglo,param
2012
1686
if (reghi != REG_NONE)
2013
emit_mov_r32_imm(dst, reghi, param->value >> 32); // mov reghi,param >> 32
1687
emit_mov_r32_imm(dst, reghi, param.immediate() >> 32); // mov reghi,param >> 32
2015
else if (param->type == DRCUML_PTYPE_MEMORY)
1689
else if (param.is_memory())
2017
int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), reglo);
2018
int skip_upper = can_skip_upper_load(drcbe, *dst, (UINT32 *)((FPTR)param->value + 4), reghi);
1691
int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reglo);
1692
int skip_upper = can_skip_upper_load(dst, (UINT32 *)((FPTR)param.memory(4)), reghi);
2019
1693
if (reglo != REG_NONE && !skip_lower)
2020
emit_mov_r32_m32(dst, reglo, MABS(param->value)); // mov reglo,[param]
1694
emit_mov_r32_m32(dst, reglo, MABS(param.memory())); // mov reglo,[param]
2021
1695
if (reghi != REG_NONE && !skip_upper)
2022
emit_mov_r32_m32(dst, reghi, MABS(param->value + 4)); // mov reghi,[param+4]
1696
emit_mov_r32_m32(dst, reghi, MABS(param.memory(4))); // mov reghi,[param+4]
2024
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1698
else if (param.is_int_register())
2026
int skip_upper = can_skip_upper_load(drcbe, *dst, drcbe->reghi[param->value], reghi);
2027
if (reglo != REG_NONE && reglo != param->value)
2028
emit_mov_r32_r32(dst, reglo, param->value); // mov reglo,param
1700
int skip_upper = can_skip_upper_load(dst, m_reghi[param.ireg()], reghi);
1701
if (reglo != REG_NONE && reglo != param.ireg())
1702
emit_mov_r32_r32(dst, reglo, param.ireg()); // mov reglo,param
2029
1703
if (reghi != REG_NONE && !skip_upper)
2030
emit_mov_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // mov reghi,reghi[param]
1704
emit_mov_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // mov reghi,reghi[param]
2035
/*-------------------------------------------------
2036
emit_mov_m64_p64 - move a 64-bit parameter
2037
into a memory location
2038
-------------------------------------------------*/
1709
//-------------------------------------------------
1710
// emit_mov_m64_p64 - move a 64-bit parameter
1711
// into a memory location
1712
//-------------------------------------------------
2040
static void emit_mov_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param)
1714
void drcbe_x86::emit_mov_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m)
2042
if (param->type == DRCUML_PTYPE_IMMEDIATE)
1716
if (param.is_immediate())
2044
emit_mov_m32_imm(dst, MEMPARAMS + 0, param->value); // mov [mem],param
2045
emit_mov_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // mov [mem],param >> 32
1718
emit_mov_m32_imm(dst, memref + 0, param.immediate()); // mov [mem],param
1719
emit_mov_m32_imm(dst, memref + 4, param.immediate() >> 32); // mov [mem],param >> 32
2047
else if (param->type == DRCUML_PTYPE_MEMORY)
1721
else if (param.is_memory())
2049
int skip_lower = can_skip_lower_load(drcbe, *dst, (UINT32 *)((FPTR)param->value), REG_EAX);
1723
int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), REG_EAX);
2050
1724
if (!skip_lower)
2051
emit_mov_r32_m32(dst, REG_EAX, MABS(param->value)); // mov eax,[param]
2052
emit_mov_m32_r32(dst, MEMPARAMS + 0, REG_EAX); // mov [mem],eax
2053
emit_mov_r32_m32(dst, REG_EAX, MABS(param->value + 4)); // mov eax,[param+4]
2054
emit_mov_m32_r32(dst, MEMPARAMS + 4, REG_EAX); // mov [mem+4],eax
2056
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2058
emit_mov_m32_r32(dst, MEMPARAMS + 0, param->value); // mov [mem],param
2059
emit_mov_r32_m32(dst, REG_EAX, MABS(drcbe->reghi[param->value])); // mov eax,[param.hi]
2060
emit_mov_m32_r32(dst, MEMPARAMS + 4, REG_EAX); // mov [mem+4],eax
2065
/*-------------------------------------------------
2066
emit_mov_p64_r64 - move a pair of registers
2067
into a 64-bit parameter
2068
-------------------------------------------------*/
2070
static void emit_mov_p64_r64(drcbe_state *drcbe, x86code **dst, const drcuml_parameter *param, UINT8 reglo, UINT8 reghi)
2072
assert(param->type != DRCUML_PTYPE_IMMEDIATE);
2073
if (param->type == DRCUML_PTYPE_MEMORY)
2075
emit_mov_m32_r32(dst, MABS(param->value), reglo); // mov [param],reglo
2076
emit_mov_m32_r32(dst, MABS(param->value + 4), reghi); // mov [param+4],reghi
2078
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2080
if (reglo != param->value)
2081
emit_mov_r32_r32(dst, param->value, reglo); // mov param,reglo
2082
emit_mov_m32_r32(dst, MABS(drcbe->reghi[param->value]), reghi); // mov reghi[param],reghi
2084
set_last_lower_reg(drcbe, *dst, param, reglo);
2085
set_last_upper_reg(drcbe, *dst, param, reghi);
2089
/*-------------------------------------------------
2090
emit_add_r64_p64 - add operation to a 64-bit
2091
pair of registers from a 64-bit parameter
2092
-------------------------------------------------*/
2094
static void emit_add_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2096
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2097
if (param->type == DRCUML_PTYPE_MEMORY)
2099
emit_add_r32_m32(dst, reglo, MABS(param->value)); // add reglo,[param]
2100
if (saveflags) emit_pushf(dst); // pushf
2101
emit_adc_r32_m32(dst, reghi, MABS(param->value + 4)); // adc reghi,[param]
2103
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2105
emit_add_r32_imm(dst, reglo, param->value); // add reglo,param
2106
if (saveflags) emit_pushf(dst); // pushf
2107
emit_adc_r32_imm(dst, reghi, param->value >> 32); // adc reghi,param >> 32
2109
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2111
emit_add_r32_r32(dst, reglo, param->value); // add reglo,param
2112
if (saveflags) emit_pushf(dst); // pushf
2113
emit_adc_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // adc reghi,reghi[param]
2116
emit_combine_z_flags(dst);
2120
/*-------------------------------------------------
2121
emit_add_m64_p64 - add operation to a 64-bit
2122
memory location from a 64-bit parameter
2123
-------------------------------------------------*/
2125
static void emit_add_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2127
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2128
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2130
emit_add_m32_imm(dst, MEMPARAMS, param->value); // add [dest],param
2131
if (saveflags) emit_pushf(dst); // pushf
2132
emit_adc_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // adc [dest+4],param >> 32
2136
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2137
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2138
emit_add_m32_r32(dst, MEMPARAMS, reglo); // add [dest],reglo
2139
if (saveflags) emit_pushf(dst); // pushf
2140
emit_adc_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // adc [dest+4],edx
2143
emit_combine_z_flags(dst);
2147
/*-------------------------------------------------
2148
emit_adc_r64_p64 - adc operation to a 64-bit
2149
pair of registers from a 64-bit parameter
2150
-------------------------------------------------*/
2152
static void emit_adc_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2154
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2155
if (param->type == DRCUML_PTYPE_MEMORY)
2157
emit_adc_r32_m32(dst, reglo, MABS(param->value)); // adc reglo,[param]
2158
if (saveflags) emit_pushf(dst); // pushf
2159
emit_adc_r32_m32(dst, reghi, MABS(param->value + 4)); // adc reghi,[param]
2161
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2163
emit_adc_r32_imm(dst, reglo, param->value); // adc reglo,param
2164
if (saveflags) emit_pushf(dst); // pushf
2165
emit_adc_r32_imm(dst, reghi, param->value >> 32); // adc reghi,param >> 32
2167
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2169
emit_adc_r32_r32(dst, reglo, param->value); // adc reglo,param
2170
if (saveflags) emit_pushf(dst); // pushf
2171
emit_adc_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // adc reghi,reghi[param]
2174
emit_combine_z_flags(dst);
2178
/*-------------------------------------------------
2179
emit_adc_m64_p64 - adc operation to a 64-bit
2180
memory location from a 64-bit parameter
2181
-------------------------------------------------*/
2183
static void emit_adc_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2185
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2186
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2188
emit_adc_m32_imm(dst, MEMPARAMS, param->value); // adc [dest],param
2189
if (saveflags) emit_pushf(dst); // pushf
2190
emit_adc_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // adc [dest+4],param >> 32
2194
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2195
emit_mov_r64_p64_keepflags(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2196
emit_adc_m32_r32(dst, MEMPARAMS, reglo); // adc [dest],reglo
2197
if (saveflags) emit_pushf(dst); // pushf
2198
emit_adc_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // adc [dest+4],edx
2201
emit_combine_z_flags(dst);
2205
/*-------------------------------------------------
2206
emit_sub_r64_p64 - sub operation to a 64-bit
2207
pair of registers from a 64-bit parameter
2208
-------------------------------------------------*/
2210
static void emit_sub_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2212
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2213
if (param->type == DRCUML_PTYPE_MEMORY)
2215
emit_sub_r32_m32(dst, reglo, MABS(param->value)); // sub reglo,[param]
2216
if (saveflags) emit_pushf(dst); // pushf
2217
emit_sbb_r32_m32(dst, reghi, MABS(param->value + 4)); // sbb reghi,[param]
2219
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2221
emit_sub_r32_imm(dst, reglo, param->value); // sub reglo,param
2222
if (saveflags) emit_pushf(dst); // pushf
2223
emit_sbb_r32_imm(dst, reghi, param->value >> 32); // sbb reghi,param >> 32
2225
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2227
emit_sub_r32_r32(dst, reglo, param->value); // sub reglo,param
2228
if (saveflags) emit_pushf(dst); // pushf
2229
emit_sbb_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // sbb reghi,reghi[param]
2232
emit_combine_z_flags(dst);
2236
/*-------------------------------------------------
2237
emit_sub_m64_p64 - sub operation to a 64-bit
2238
memory location from a 64-bit parameter
2239
-------------------------------------------------*/
2241
static void emit_sub_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2243
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2244
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2246
emit_sub_m32_imm(dst, MEMPARAMS, param->value); // sub [dest],param
2247
if (saveflags) emit_pushf(dst); // pushf
2248
emit_sbb_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // sbb [dest+4],param >> 32
2252
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2253
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2254
emit_sub_m32_r32(dst, MEMPARAMS, reglo); // sub [dest],reglo
2255
if (saveflags) emit_pushf(dst); // pushf
2256
emit_sbb_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // sbb [dest+4],edx
2259
emit_combine_z_flags(dst);
2263
/*-------------------------------------------------
2264
emit_sbb_r64_p64 - sbb operation to a 64-bit
2265
pair of registers from a 64-bit parameter
2266
-------------------------------------------------*/
2268
static void emit_sbb_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2270
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2271
if (param->type == DRCUML_PTYPE_MEMORY)
2273
emit_sbb_r32_m32(dst, reglo, MABS(param->value)); // sbb reglo,[param]
2274
if (saveflags) emit_pushf(dst); // pushf
2275
emit_sbb_r32_m32(dst, reghi, MABS(param->value + 4)); // sbb reghi,[param]
2277
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2279
emit_sbb_r32_imm(dst, reglo, param->value); // sbb reglo,param
2280
if (saveflags) emit_pushf(dst); // pushf
2281
emit_sbb_r32_imm(dst, reghi, param->value >> 32); // sbb reghi,param >> 32
2283
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2285
emit_sbb_r32_r32(dst, reglo, param->value); // sbb reglo,param
2286
if (saveflags) emit_pushf(dst); // pushf
2287
emit_sbb_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // sbb reghi,reghi[param]
2290
emit_combine_z_flags(dst);
2294
/*-------------------------------------------------
2295
emit_sbb_m64_p64 - sbb operation to a 64-bit
2296
memory location from a 64-bit parameter
2297
-------------------------------------------------*/
2299
static void emit_sbb_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2301
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2302
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2304
emit_sbb_m32_imm(dst, MEMPARAMS, param->value); // sbb [dest],param
2305
if (saveflags) emit_pushf(dst); // pushf
2306
emit_sbb_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // sbb [dest+4],param >> 32
2310
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2311
emit_mov_r64_p64_keepflags(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2312
emit_sbb_m32_r32(dst, MEMPARAMS, reglo); // sbb [dest],reglo
2313
if (saveflags) emit_pushf(dst); // pushf
2314
emit_sbb_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // sbb [dest+4],edx
2317
emit_combine_z_flags(dst);
2321
/*-------------------------------------------------
2322
emit_cmp_r64_p64 - sub operation to a 64-bit
2323
pair of registers from a 64-bit parameter
2324
-------------------------------------------------*/
2326
static void emit_cmp_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2328
int saveflags = (inst->flags != DRCUML_FLAG_Z && (inst->flags & DRCUML_FLAG_Z) != 0);
2329
if (param->type == DRCUML_PTYPE_MEMORY)
2331
emit_sub_r32_m32(dst, reglo, MABS(param->value)); // sub reglo,[param]
2332
if (saveflags) emit_pushf(dst); // pushf
2333
emit_sbb_r32_m32(dst, reghi, MABS(param->value + 4)); // sbb reghi,[param]
2335
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2337
emit_sub_r32_imm(dst, reglo, param->value); // sub reglo,param
2338
if (saveflags) emit_pushf(dst); // pushf
2339
emit_sbb_r32_imm(dst, reghi, param->value >> 32); // sbb reghi,param >> 32
2341
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2343
emit_sub_r32_r32(dst, reglo, param->value); // sub reglo,param
2344
if (saveflags) emit_pushf(dst); // pushf
2345
emit_sbb_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // sbb reghi,reghi[param]
2347
if (inst->flags == DRCUML_FLAG_Z)
1725
emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param]
1726
emit_mov_m32_r32(dst, memref + 0, REG_EAX); // mov [mem],eax
1727
emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory(4))); // mov eax,[param+4]
1728
emit_mov_m32_r32(dst, memref + 4, REG_EAX); // mov [mem+4],eax
1730
else if (param.is_int_register())
1732
emit_mov_m32_r32(dst, memref + 0, param.ireg()); // mov [mem],param
1733
emit_mov_r32_m32(dst, REG_EAX, MABS(m_reghi[param.ireg()])); // mov eax,[param.hi]
1734
emit_mov_m32_r32(dst, memref + 4, REG_EAX); // mov [mem+4],eax
1739
//-------------------------------------------------
1740
// emit_mov_p64_r64 - move a pair of registers
1741
// into a 64-bit parameter
1742
//-------------------------------------------------
1744
void drcbe_x86::emit_mov_p64_r64(x86code *&dst, const be_parameter ¶m, UINT8 reglo, UINT8 reghi)
1746
assert(!param.is_immediate());
1747
if (param.is_memory())
1749
emit_mov_m32_r32(dst, MABS(param.memory()), reglo); // mov [param],reglo
1750
emit_mov_m32_r32(dst, MABS(param.memory(4)), reghi); // mov [param+4],reghi
1752
else if (param.is_int_register())
1754
if (reglo != param.ireg())
1755
emit_mov_r32_r32(dst, param.ireg(), reglo); // mov param,reglo
1756
emit_mov_m32_r32(dst, MABS(m_reghi[param.ireg()]), reghi); // mov reghi[param],reghi
1758
set_last_lower_reg(dst, param, reglo);
1759
set_last_upper_reg(dst, param, reghi);
1763
//-------------------------------------------------
1764
// emit_add_r64_p64 - add operation to a 64-bit
1765
// pair of registers from a 64-bit parameter
1766
//-------------------------------------------------
1768
void drcbe_x86::emit_add_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
1770
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1771
if (param.is_memory())
1773
emit_add_r32_m32(dst, reglo, MABS(param.memory())); // add reglo,[param]
1774
if (saveflags) emit_pushf(dst); // pushf
1775
emit_adc_r32_m32(dst, reghi, MABS(param.memory(4))); // adc reghi,[param]
1777
else if (param.is_immediate())
1779
emit_add_r32_imm(dst, reglo, param.immediate()); // add reglo,param
1780
if (saveflags) emit_pushf(dst); // pushf
1781
emit_adc_r32_imm(dst, reghi, param.immediate() >> 32); // adc reghi,param >> 32
1783
else if (param.is_int_register())
1785
emit_add_r32_r32(dst, reglo, param.ireg()); // add reglo,param
1786
if (saveflags) emit_pushf(dst); // pushf
1787
emit_adc_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // adc reghi,reghi[param]
1790
emit_combine_z_flags(dst);
1794
//-------------------------------------------------
1795
// emit_add_m64_p64 - add operation to a 64-bit
1796
// memory location from a 64-bit parameter
1797
//-------------------------------------------------
1799
void drcbe_x86::emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1801
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1802
if (param.is_immediate())
1804
emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param
1805
if (saveflags) emit_pushf(dst); // pushf
1806
emit_adc_m32_imm(dst, memref + 4, param.immediate() >> 32); // adc [dest+4],param >> 32
1810
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
1811
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
1812
emit_add_m32_r32(dst, memref, reglo); // add [dest],reglo
1813
if (saveflags) emit_pushf(dst); // pushf
1814
emit_adc_m32_r32(dst, memref + 4, REG_EDX); // adc [dest+4],edx
1817
emit_combine_z_flags(dst);
1821
//-------------------------------------------------
1822
// emit_adc_r64_p64 - adc operation to a 64-bit
1823
// pair of registers from a 64-bit parameter
1824
//-------------------------------------------------
1826
void drcbe_x86::emit_adc_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
1828
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1829
if (param.is_memory())
1831
emit_adc_r32_m32(dst, reglo, MABS(param.memory())); // adc reglo,[param]
1832
if (saveflags) emit_pushf(dst); // pushf
1833
emit_adc_r32_m32(dst, reghi, MABS(param.memory(4))); // adc reghi,[param]
1835
else if (param.is_immediate())
1837
emit_adc_r32_imm(dst, reglo, param.immediate()); // adc reglo,param
1838
if (saveflags) emit_pushf(dst); // pushf
1839
emit_adc_r32_imm(dst, reghi, param.immediate() >> 32); // adc reghi,param >> 32
1841
else if (param.is_int_register())
1843
emit_adc_r32_r32(dst, reglo, param.ireg()); // adc reglo,param
1844
if (saveflags) emit_pushf(dst); // pushf
1845
emit_adc_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // adc reghi,reghi[param]
1848
emit_combine_z_flags(dst);
1852
//-------------------------------------------------
1853
// emit_adc_m64_p64 - adc operation to a 64-bit
1854
// memory location from a 64-bit parameter
1855
//-------------------------------------------------
1857
void drcbe_x86::emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1859
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1860
if (param.is_immediate())
1862
emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param
1863
if (saveflags) emit_pushf(dst); // pushf
1864
emit_adc_m32_imm(dst, memref + 4, param.immediate() >> 32); // adc [dest+4],param >> 32
1868
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
1869
emit_mov_r64_p64_keepflags(dst, reglo, REG_EDX, param); // mov edx:reglo,param
1870
emit_adc_m32_r32(dst, memref, reglo); // adc [dest],reglo
1871
if (saveflags) emit_pushf(dst); // pushf
1872
emit_adc_m32_r32(dst, memref + 4, REG_EDX); // adc [dest+4],edx
1875
emit_combine_z_flags(dst);
1879
//-------------------------------------------------
1880
// emit_sub_r64_p64 - sub operation to a 64-bit
1881
// pair of registers from a 64-bit parameter
1882
//-------------------------------------------------
1884
void drcbe_x86::emit_sub_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
1886
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1887
if (param.is_memory())
1889
emit_sub_r32_m32(dst, reglo, MABS(param.memory())); // sub reglo,[param]
1890
if (saveflags) emit_pushf(dst); // pushf
1891
emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
1893
else if (param.is_immediate())
1895
emit_sub_r32_imm(dst, reglo, param.immediate()); // sub reglo,param
1896
if (saveflags) emit_pushf(dst); // pushf
1897
emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
1899
else if (param.is_int_register())
1901
emit_sub_r32_r32(dst, reglo, param.ireg()); // sub reglo,param
1902
if (saveflags) emit_pushf(dst); // pushf
1903
emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
1906
emit_combine_z_flags(dst);
1910
//-------------------------------------------------
1911
// emit_sub_m64_p64 - sub operation to a 64-bit
1912
// memory location from a 64-bit parameter
1913
//-------------------------------------------------
1915
void drcbe_x86::emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1917
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1918
if (param.is_immediate())
1920
emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param
1921
if (saveflags) emit_pushf(dst); // pushf
1922
emit_sbb_m32_imm(dst, memref + 4, param.immediate() >> 32); // sbb [dest+4],param >> 32
1926
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
1927
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
1928
emit_sub_m32_r32(dst, memref, reglo); // sub [dest],reglo
1929
if (saveflags) emit_pushf(dst); // pushf
1930
emit_sbb_m32_r32(dst, memref + 4, REG_EDX); // sbb [dest+4],edx
1933
emit_combine_z_flags(dst);
1937
//-------------------------------------------------
1938
// emit_sbb_r64_p64 - sbb operation to a 64-bit
1939
// pair of registers from a 64-bit parameter
1940
//-------------------------------------------------
1942
void drcbe_x86::emit_sbb_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
1944
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1945
if (param.is_memory())
1947
emit_sbb_r32_m32(dst, reglo, MABS(param.memory())); // sbb reglo,[param]
1948
if (saveflags) emit_pushf(dst); // pushf
1949
emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
1951
else if (param.is_immediate())
1953
emit_sbb_r32_imm(dst, reglo, param.immediate()); // sbb reglo,param
1954
if (saveflags) emit_pushf(dst); // pushf
1955
emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
1957
else if (param.is_int_register())
1959
emit_sbb_r32_r32(dst, reglo, param.ireg()); // sbb reglo,param
1960
if (saveflags) emit_pushf(dst); // pushf
1961
emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
1964
emit_combine_z_flags(dst);
1968
//-------------------------------------------------
1969
// emit_sbb_m64_p64 - sbb operation to a 64-bit
1970
// memory location from a 64-bit parameter
1971
//-------------------------------------------------
1973
void drcbe_x86::emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
1975
int saveflags = ((inst.flags() & FLAG_Z) != 0);
1976
if (param.is_immediate())
1978
emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param
1979
if (saveflags) emit_pushf(dst); // pushf
1980
emit_sbb_m32_imm(dst, memref + 4, param.immediate() >> 32); // sbb [dest+4],param >> 32
1984
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
1985
emit_mov_r64_p64_keepflags(dst, reglo, REG_EDX, param); // mov edx:reglo,param
1986
emit_sbb_m32_r32(dst, memref, reglo); // sbb [dest],reglo
1987
if (saveflags) emit_pushf(dst); // pushf
1988
emit_sbb_m32_r32(dst, memref + 4, REG_EDX); // sbb [dest+4],edx
1991
emit_combine_z_flags(dst);
1995
//-------------------------------------------------
1996
// emit_cmp_r64_p64 - sub operation to a 64-bit
1997
// pair of registers from a 64-bit parameter
1998
//-------------------------------------------------
2000
void drcbe_x86::emit_cmp_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2002
int saveflags = (inst.flags() != FLAG_Z && (inst.flags() & FLAG_Z) != 0);
2003
if (param.is_memory())
2005
emit_sub_r32_m32(dst, reglo, MABS(param.memory())); // sub reglo,[param]
2006
if (saveflags) emit_pushf(dst); // pushf
2007
emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
2009
else if (param.is_immediate())
2011
emit_sub_r32_imm(dst, reglo, param.immediate()); // sub reglo,param
2012
if (saveflags) emit_pushf(dst); // pushf
2013
emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
2015
else if (param.is_int_register())
2017
emit_sub_r32_r32(dst, reglo, param.ireg()); // sub reglo,param
2018
if (saveflags) emit_pushf(dst); // pushf
2019
emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
2021
if (inst.flags() == FLAG_Z)
2348
2022
emit_or_r32_r32(dst, reghi, reglo); // or reghi,reglo
2349
2023
else if (saveflags)
2350
2024
emit_combine_z_flags(dst);
2354
/*-------------------------------------------------
2355
emit_and_r64_p64 - and operation to a 64-bit
2356
pair of registers from a 64-bit parameter
2357
-------------------------------------------------*/
2028
//-------------------------------------------------
2029
// emit_and_r64_p64 - and operation to a 64-bit
2030
// pair of registers from a 64-bit parameter
2031
//-------------------------------------------------
2359
static void emit_and_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2033
void drcbe_x86::emit_and_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2361
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2362
if (param->type == DRCUML_PTYPE_MEMORY)
2035
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2036
if (param.is_memory())
2364
emit_and_r32_m32(dst, reglo, MABS(param->value)); // and reglo,[param]
2038
emit_and_r32_m32(dst, reglo, MABS(param.memory())); // and reglo,[param]
2365
2039
if (saveflags) emit_pushf(dst); // pushf
2366
emit_and_r32_m32(dst, reghi, MABS(param->value + 4)); // and reghi,[param]
2040
emit_and_r32_m32(dst, reghi, MABS(param.memory(4))); // and reghi,[param]
2368
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2042
else if (param.is_immediate())
2370
if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2372
else if (inst->flags == 0 && (UINT32)param->value == 0)
2044
if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2046
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2373
2047
emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
2375
emit_and_r32_imm(dst, reglo, param->value); // and reglo,param
2049
emit_and_r32_imm(dst, reglo, param.immediate()); // and reglo,param
2376
2050
if (saveflags) emit_pushf(dst); // pushf
2377
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2379
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2051
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2053
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2380
2054
emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
2382
emit_and_r32_imm(dst, reghi, param->value >> 32); // and reghi,param >> 32
2384
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2386
emit_and_r32_r32(dst, reglo, param->value); // and reglo,param
2387
if (saveflags) emit_pushf(dst); // pushf
2388
emit_and_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // and reghi,reghi[param]
2391
emit_combine_z_flags(dst);
2395
/*-------------------------------------------------
2396
emit_and_m64_p64 - and operation to a 64-bit
2397
memory location from a 64-bit parameter
2398
-------------------------------------------------*/
2400
static void emit_and_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2402
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2403
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2405
if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2407
else if (inst->flags == 0 && (UINT32)param->value == 0)
2408
emit_mov_m32_imm(dst, MEMPARAMS, 0); // mov [dest],0
2410
emit_and_m32_imm(dst, MEMPARAMS, param->value); // and [dest],param
2411
if (saveflags) emit_pushf(dst); // pushf
2412
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2414
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2415
emit_mov_m32_imm(dst, MEMPARAMS + 4, 0); // mov [dest+4],0
2417
emit_and_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // and [dest+4],param >> 32
2421
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2422
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2423
emit_and_m32_r32(dst, MEMPARAMS, reglo); // and [dest],reglo
2424
if (saveflags) emit_pushf(dst); // pushf
2425
emit_and_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // and [dest+4],edx
2428
emit_combine_z_flags(dst);
2432
/*-------------------------------------------------
2433
emit_test_r64_p64 - test operation to a 64-bit
2434
pair of registers from a 64-bit parameter
2435
-------------------------------------------------*/
2437
static void emit_test_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2439
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2440
if (param->type == DRCUML_PTYPE_MEMORY)
2442
emit_test_m32_r32(dst, MABS(param->value), reglo); // test [param],reglo
2443
if (saveflags) emit_pushf(dst); // pushf
2444
emit_test_m32_r32(dst, MABS(param->value + 4), reghi); // test [param],reghi
2446
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2448
emit_test_r32_imm(dst, reglo, param->value); // test reglo,param
2449
if (saveflags) emit_pushf(dst); // pushf
2450
emit_test_r32_imm(dst, reghi, param->value >> 32); // test reghi,param >> 32
2452
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2454
emit_test_r32_r32(dst, reglo, param->value); // test reglo,param
2455
if (saveflags) emit_pushf(dst); // pushf
2456
emit_test_m32_r32(dst, MABS(drcbe->reghi[param->value]), reghi); // test reghi[param],reghi
2459
emit_combine_z_flags(dst);
2463
/*-------------------------------------------------
2464
emit_test_m64_p64 - test operation to a 64-bit
2465
memory location from a 64-bit parameter
2466
-------------------------------------------------*/
2468
static void emit_test_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2470
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2471
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2473
emit_test_m32_imm(dst, MEMPARAMS, param->value); // test [dest],param
2474
if (saveflags) emit_pushf(dst); // pushf
2475
emit_test_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // test [dest+4],param >> 32
2479
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2480
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2481
emit_test_m32_r32(dst, MEMPARAMS, reglo); // test [dest],reglo
2482
if (saveflags) emit_pushf(dst); // pushf
2483
emit_test_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // test [dest+4],edx
2486
emit_combine_z_flags(dst);
2490
/*-------------------------------------------------
2491
emit_or_r64_p64 - or operation to a 64-bit
2492
pair of registers from a 64-bit parameter
2493
-------------------------------------------------*/
2495
static void emit_or_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2497
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2498
if (param->type == DRCUML_PTYPE_MEMORY)
2500
emit_or_r32_m32(dst, reglo, MABS(param->value)); // or reglo,[param]
2501
if (saveflags) emit_pushf(dst); // pushf
2502
emit_or_r32_m32(dst, reghi, MABS(param->value + 4)); // or reghi,[param]
2504
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2506
if (inst->flags == 0 && (UINT32)param->value == 0)
2508
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2056
emit_and_r32_imm(dst, reghi, param.immediate() >> 32); // and reghi,param >> 32
2058
else if (param.is_int_register())
2060
emit_and_r32_r32(dst, reglo, param.ireg()); // and reglo,param
2061
if (saveflags) emit_pushf(dst); // pushf
2062
emit_and_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // and reghi,reghi[param]
2065
emit_combine_z_flags(dst);
2069
//-------------------------------------------------
2070
// emit_and_m64_p64 - and operation to a 64-bit
2071
// memory location from a 64-bit parameter
2072
//-------------------------------------------------
2074
void drcbe_x86::emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
2076
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2077
if (param.is_immediate())
2079
if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2081
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2082
emit_mov_m32_imm(dst, memref, 0); // mov [dest],0
2084
emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param
2085
if (saveflags) emit_pushf(dst); // pushf
2086
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2088
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2089
emit_mov_m32_imm(dst, memref + 4, 0); // mov [dest+4],0
2091
emit_and_m32_imm(dst, memref + 4, param.immediate() >> 32); // and [dest+4],param >> 32
2095
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
2096
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
2097
emit_and_m32_r32(dst, memref, reglo); // and [dest],reglo
2098
if (saveflags) emit_pushf(dst); // pushf
2099
emit_and_m32_r32(dst, memref + 4, REG_EDX); // and [dest+4],edx
2102
emit_combine_z_flags(dst);
2106
//-------------------------------------------------
2107
// emit_test_r64_p64 - test operation to a 64-bit
2108
// pair of registers from a 64-bit parameter
2109
//-------------------------------------------------
2111
void drcbe_x86::emit_test_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2113
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2114
if (param.is_memory())
2116
emit_test_m32_r32(dst, MABS(param.memory()), reglo); // test [param],reglo
2117
if (saveflags) emit_pushf(dst); // pushf
2118
emit_test_m32_r32(dst, MABS(param.memory(4)), reghi); // test [param],reghi
2120
else if (param.is_immediate())
2122
emit_test_r32_imm(dst, reglo, param.immediate()); // test reglo,param
2123
if (saveflags) emit_pushf(dst); // pushf
2124
emit_test_r32_imm(dst, reghi, param.immediate() >> 32); // test reghi,param >> 32
2126
else if (param.is_int_register())
2128
emit_test_r32_r32(dst, reglo, param.ireg()); // test reglo,param
2129
if (saveflags) emit_pushf(dst); // pushf
2130
emit_test_m32_r32(dst, MABS(m_reghi[param.ireg()]), reghi); // test reghi[param],reghi
2133
emit_combine_z_flags(dst);
2137
//-------------------------------------------------
2138
// emit_test_m64_p64 - test operation to a 64-bit
2139
// memory location from a 64-bit parameter
2140
//-------------------------------------------------
2142
void drcbe_x86::emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
2144
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2145
if (param.is_immediate())
2147
emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param
2148
if (saveflags) emit_pushf(dst); // pushf
2149
emit_test_m32_imm(dst, memref + 4, param.immediate() >> 32); // test [dest+4],param >> 32
2153
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
2154
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
2155
emit_test_m32_r32(dst, memref, reglo); // test [dest],reglo
2156
if (saveflags) emit_pushf(dst); // pushf
2157
emit_test_m32_r32(dst, memref + 4, REG_EDX); // test [dest+4],edx
2160
emit_combine_z_flags(dst);
2164
//-------------------------------------------------
2165
// emit_or_r64_p64 - or operation to a 64-bit
2166
// pair of registers from a 64-bit parameter
2167
//-------------------------------------------------
2169
void drcbe_x86::emit_or_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2171
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2172
if (param.is_memory())
2174
emit_or_r32_m32(dst, reglo, MABS(param.memory())); // or reglo,[param]
2175
if (saveflags) emit_pushf(dst); // pushf
2176
emit_or_r32_m32(dst, reghi, MABS(param.memory(4))); // or reghi,[param]
2178
else if (param.is_immediate())
2180
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2182
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2509
2183
emit_mov_r32_imm(dst, reglo, ~0); // mov reglo,-1
2511
emit_or_r32_imm(dst, reglo, param->value); // or reglo,param
2185
emit_or_r32_imm(dst, reglo, param.immediate()); // or reglo,param
2512
2186
if (saveflags) emit_pushf(dst); // pushf
2513
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2515
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2187
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2189
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2516
2190
emit_mov_r32_imm(dst, reghi, ~0); // mov reghi,-1
2518
emit_or_r32_imm(dst, reghi, param->value >> 32); // or reghi,param >> 32
2192
emit_or_r32_imm(dst, reghi, param.immediate() >> 32); // or reghi,param >> 32
2520
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2194
else if (param.is_int_register())
2522
emit_or_r32_r32(dst, reglo, param->value); // or reglo,param
2196
emit_or_r32_r32(dst, reglo, param.ireg()); // or reglo,param
2523
2197
if (saveflags) emit_pushf(dst); // pushf
2524
emit_or_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // or reghi,reghi[param]
2198
emit_or_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // or reghi,reghi[param]
2527
2201
emit_combine_z_flags(dst);
2531
/*-------------------------------------------------
2532
emit_or_m64_p64 - or operation to a 64-bit
2533
memory location from a 64-bit parameter
2534
-------------------------------------------------*/
2205
//-------------------------------------------------
2206
// emit_or_m64_p64 - or operation to a 64-bit
2207
// memory location from a 64-bit parameter
2208
//-------------------------------------------------
2536
static void emit_or_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2210
void drcbe_x86::emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
2538
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2539
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2212
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2213
if (param.is_immediate())
2541
if (inst->flags == 0 && (UINT32)param->value == 0)
2543
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2544
emit_mov_m32_imm(dst, MEMPARAMS, ~0); // mov [dest],-1
2215
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2217
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2218
emit_mov_m32_imm(dst, memref, ~0); // mov [dest],-1
2546
emit_or_m32_imm(dst, MEMPARAMS, param->value); // or [dest],param
2220
emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param
2547
2221
if (saveflags) emit_pushf(dst); // pushf
2548
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2550
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2551
emit_mov_m32_imm(dst, MEMPARAMS + 4, ~0); // mov [dest+4],-1
2222
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2224
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2225
emit_mov_m32_imm(dst, memref + 4, ~0); // mov [dest+4],-1
2553
emit_or_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // or [dest+4],param >> 32
2227
emit_or_m32_imm(dst, memref + 4, param.immediate() >> 32); // or [dest+4],param >> 32
2557
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2558
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2559
emit_or_m32_r32(dst, MEMPARAMS, reglo); // or [dest],reglo
2231
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
2232
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
2233
emit_or_m32_r32(dst, memref, reglo); // or [dest],reglo
2560
2234
if (saveflags) emit_pushf(dst); // pushf
2561
emit_or_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // or [dest+4],edx
2235
emit_or_m32_r32(dst, memref + 4, REG_EDX); // or [dest+4],edx
2564
2238
emit_combine_z_flags(dst);
2568
/*-------------------------------------------------
2569
emit_xor_r64_p64 - xor operation to a 64-bit
2570
pair of registers from a 64-bit parameter
2571
-------------------------------------------------*/
2242
//-------------------------------------------------
2243
// emit_xor_r64_p64 - xor operation to a 64-bit
2244
// pair of registers from a 64-bit parameter
2245
//-------------------------------------------------
2573
static void emit_xor_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2247
void drcbe_x86::emit_xor_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2575
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2576
if (param->type == DRCUML_PTYPE_MEMORY)
2249
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2250
if (param.is_memory())
2578
emit_xor_r32_m32(dst, reglo, MABS(param->value)); // xor reglo,[param]
2252
emit_xor_r32_m32(dst, reglo, MABS(param.memory())); // xor reglo,[param]
2579
2253
if (saveflags) emit_pushf(dst); // pushf
2580
emit_xor_r32_m32(dst, reghi, MABS(param->value + 4)); // xor reghi,[param]
2254
emit_xor_r32_m32(dst, reghi, MABS(param.memory(4))); // xor reghi,[param]
2582
else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2256
else if (param.is_immediate())
2584
if (inst->flags == 0 && (UINT32)param->value == 0)
2586
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2258
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2260
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2587
2261
emit_not_r32(dst, reglo); // not reglo
2589
emit_xor_r32_imm(dst, reglo, param->value); // xor reglo,param
2263
emit_xor_r32_imm(dst, reglo, param.immediate()); // xor reglo,param
2590
2264
if (saveflags) emit_pushf(dst); // pushf
2591
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2593
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2265
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2267
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2594
2268
emit_not_r32(dst, reghi); // not reghi
2596
emit_xor_r32_imm(dst, reghi, param->value >> 32); // xor reghi,param >> 32
2270
emit_xor_r32_imm(dst, reghi, param.immediate() >> 32); // xor reghi,param >> 32
2598
else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2272
else if (param.is_int_register())
2600
emit_xor_r32_r32(dst, reglo, param->value); // xor reglo,param
2274
emit_xor_r32_r32(dst, reglo, param.ireg()); // xor reglo,param
2601
2275
if (saveflags) emit_pushf(dst); // pushf
2602
emit_xor_r32_m32(dst, reghi, MABS(drcbe->reghi[param->value])); // xor reghi,reghi[param]
2276
emit_xor_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // xor reghi,reghi[param]
2605
2279
emit_combine_z_flags(dst);
2609
/*-------------------------------------------------
2610
emit_xor_m64_p64 - xor operation to a 64-bit
2611
memory location from a 64-bit parameter
2612
-------------------------------------------------*/
2283
//-------------------------------------------------
2284
// emit_xor_m64_p64 - xor operation to a 64-bit
2285
// memory location from a 64-bit parameter
2286
//-------------------------------------------------
2614
static void emit_xor_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2288
void drcbe_x86::emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter ¶m, const instruction &inst)
2616
int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2617
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2290
int saveflags = ((inst.flags() & FLAG_Z) != 0);
2291
if (param.is_immediate())
2619
if (inst->flags == 0 && (UINT32)param->value == 0)
2621
else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2622
emit_not_m32(dst, MEMPARAMS); // not [dest]
2293
if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2295
else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2296
emit_not_m32(dst, memref); // not [dest]
2624
emit_xor_m32_imm(dst, MEMPARAMS, param->value); // xor [dest],param
2298
emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param
2625
2299
if (saveflags) emit_pushf(dst); // pushf
2626
if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2628
else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
2629
emit_not_m32(dst, MEMPARAMS + 4); // not [dest+4]
2300
if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2302
else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2303
emit_not_m32(dst, memref + 4); // not [dest+4]
2631
emit_xor_m32_imm(dst, MEMPARAMS + 4, param->value >> 32); // xor [dest+4],param >> 32
2305
emit_xor_m32_imm(dst, memref + 4, param.immediate() >> 32); // xor [dest+4],param >> 32
2635
int reglo = (param->type == DRCUML_PTYPE_INT_REGISTER) ? param->value : REG_EAX;
2636
emit_mov_r64_p64(drcbe, dst, reglo, REG_EDX, param); // mov edx:reglo,param
2637
emit_xor_m32_r32(dst, MEMPARAMS, reglo); // xor [dest],reglo
2309
int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
2310
emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
2311
emit_xor_m32_r32(dst, memref, reglo); // xor [dest],reglo
2638
2312
if (saveflags) emit_pushf(dst); // pushf
2639
emit_xor_m32_r32(dst, MEMPARAMS + 4, REG_EDX); // xor [dest+4],edx
2313
emit_xor_m32_r32(dst, memref + 4, REG_EDX); // xor [dest+4],edx
2642
2316
emit_combine_z_flags(dst);
2646
/*-------------------------------------------------
2647
emit_shl_r64_p64 - shl operation to a 64-bit
2648
pair of registers from a 64-bit parameter
2649
-------------------------------------------------*/
2320
//-------------------------------------------------
2321
// emit_shl_r64_p64 - shl operation to a 64-bit
2322
// pair of registers from a 64-bit parameter
2323
//-------------------------------------------------
2651
static void emit_shl_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2325
void drcbe_x86::emit_shl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter ¶m, const instruction &inst)
2653
int saveflags = (inst->flags != 0);
2654
if (param->type == DRCUML_PTYPE_IMMEDIATE)
2327
int saveflags = (inst.flags() != 0);
2328
if (param.is_immediate())
2656
int count = param->value & 63;
2657
if (inst->flags == 0 && count == 0)
2330
int count = param.immediate() & 63;
2331
if (inst.flags() == 0 && count == 0)
2661
2335
while (count >= 32)
2663
if (inst->flags != 0)
2337
if (inst.flags() != 0)
2665
2339
emit_shld_r32_r32_imm(dst, reghi, reglo, 31); // shld reghi,reglo,31
2666
2340
emit_shl_r32_imm(dst, reglo, 31); // shl reglo,31
3165
/*-------------------------------------------------
3166
fixup_exception - callback to perform cleanup
3167
and jump to an exception handler
3168
-------------------------------------------------*/
2839
//-------------------------------------------------
2840
// fixup_exception - callback to perform cleanup
2841
// and jump to an exception handler
2842
//-------------------------------------------------
3170
static void fixup_exception(drccodeptr *codeptr, void *param1, void *param2, void *param3)
2844
void drcbe_x86::fixup_exception(drccodeptr *codeptr, void *param1, void *param2)
3172
drcuml_parameter handp, exp;
3173
drcbe_state *drcbe = (drcbe_state *)param1;
3174
drccodeptr src = (drccodeptr)param2;
3175
const drcuml_instruction *inst = (const drcuml_instruction *)param3;
2846
drccodeptr src = (drccodeptr)param1;
2847
const instruction &inst = *(const instruction *)param2;
2849
// normalize parameters
2850
const parameter &handp = inst.param(0);
2851
assert(handp.is_code_handle());
2852
be_parameter exp(*this, inst.param(1), PTYPE_MRI);
2854
// look up the handle target
2855
drccodeptr *targetptr = handp.handle().codeptr_addr();
2857
// first fixup the jump to get us here
3176
2858
drccodeptr dst = *codeptr;
3177
drccodeptr *targetptr;
3179
/* normalize parameters */
3180
param_normalize_2(drcbe, inst, &handp, PTYPE_M, &exp, PTYPE_MRI);
3182
/* look up the handle target */
3183
targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3185
/* first fixup the jump to get us here */
3186
2859
((UINT32 *)src)[-1] = dst - src;
3188
/* then store the exception parameter */
3189
emit_mov_m32_p32(drcbe, &dst, MABS(&drcbe->state.exp), &exp); // mov [exp],exp
2861
// then store the exception parameter
2862
emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
3191
/* push the original return address on the stack */
3192
emit_push_imm(&dst, (FPTR)src); // push <return>
2864
// push the original return address on the stack
2865
emit_push_imm(dst, (FPTR)src); // push <return>
3193
2866
if (*targetptr != NULL)
3194
emit_jmp(&dst, *targetptr); // jmp *targetptr
2867
emit_jmp(dst, *targetptr); // jmp *targetptr
3196
emit_jmp_m32(&dst, MABS(targetptr)); // jmp [targetptr]
2869
emit_jmp_m32(dst, MABS(targetptr)); // jmp [targetptr]
3198
2871
*codeptr = dst;
3203
/***************************************************************************
3205
***************************************************************************/
3207
/*-------------------------------------------------
3208
debug_log_hashjmp - callback to handle
3210
-------------------------------------------------*/
3212
static void debug_log_hashjmp(int mode, offs_t pc)
2876
//**************************************************************************
2878
//**************************************************************************
2880
//-------------------------------------------------
2881
// debug_log_hashjmp - callback to handle
2882
// logging of hashjmps
2883
//-------------------------------------------------
2885
void drcbe_x86::debug_log_hashjmp(int mode, offs_t pc)
3214
2887
printf("mode=%d PC=%08X\n", mode, pc);
3219
/***************************************************************************
3220
COMPILE-TIME OPCODES
3221
***************************************************************************/
3223
/*-------------------------------------------------
3224
op_handle - process a HANDLE opcode
3225
-------------------------------------------------*/
3227
static x86code *op_handle(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
2892
//**************************************************************************
2893
// COMPILE-TIME OPCODES
2894
//**************************************************************************
2896
//-------------------------------------------------
2897
// op_handle - process a HANDLE opcode
2898
//-------------------------------------------------
2900
void drcbe_x86::op_handle(x86code *&dst, const instruction &inst)
2902
assert_no_condition(inst);
2903
assert_no_flags(inst);
2904
assert(inst.numparams() == 1);
2905
assert(inst.param(0).is_code_handle());
2907
reset_last_upper_lower_reg();
2909
// emit a jump around the stack adjust in case code falls through here
3229
2910
emit_link skip;
3231
assert_no_condition(inst);
3232
assert_no_flags(inst);
3233
assert(inst->numparams == 1);
3234
assert(inst->param[0].type == DRCUML_PTYPE_MEMORY);
3236
reset_last_upper_lower_reg(drcbe);
3238
/* emit a jump around the stack adjust in case code falls through here */
3239
emit_jmp_short_link(&dst, &skip); // jmp skip
3241
/* register the current pointer for the handle */
3242
drcuml_handle_set_codeptr((drcuml_codehandle *)(FPTR)inst->param[0].value, dst);
3244
/* by default, the handle points to prolog code that moves the stack pointer */
3245
emit_lea_r32_m32(&dst, REG_ESP, MBD(REG_ESP, -28)); // lea rsp,[rsp-28]
3246
track_resolve_link(drcbe, &dst, &skip); // skip:
3251
/*-------------------------------------------------
3252
op_hash - process a HASH opcode
3253
-------------------------------------------------*/
3255
static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3257
assert_no_condition(inst);
3258
assert_no_flags(inst);
3259
assert(inst->numparams == 2);
3260
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
3261
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
3263
/* register the current pointer for the mode/PC */
3264
drchash_set_codeptr(drcbe->hash, inst->param[0].value, inst->param[1].value, dst);
3265
reset_last_upper_lower_reg(drcbe);
3270
/*-------------------------------------------------
3271
op_label - process a LABEL opcode
3272
-------------------------------------------------*/
3274
static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3276
assert_no_condition(inst);
3277
assert_no_flags(inst);
3278
assert(inst->numparams == 1);
3279
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
3281
/* register the current pointer for the label */
3282
drclabel_set_codeptr(drcbe->labels, inst->param[0].value, dst);
3283
reset_last_upper_lower_reg(drcbe);
3288
/*-------------------------------------------------
3289
op_comment - process a COMMENT opcode
3290
-------------------------------------------------*/
3292
static x86code *op_comment(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3294
assert_no_condition(inst);
3295
assert_no_flags(inst);
3296
assert(inst->numparams == 1);
3297
assert(inst->param[0].type == DRCUML_PTYPE_MEMORY);
3304
/*-------------------------------------------------
3305
op_mapvar - process a MAPVAR opcode
3306
-------------------------------------------------*/
3308
static x86code *op_mapvar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3310
assert_no_condition(inst);
3311
assert_no_flags(inst);
3312
assert(inst->numparams == 2);
3313
assert(inst->param[0].type == DRCUML_PTYPE_MAPVAR);
3314
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
3316
/* set the value of the specified mapvar */
3317
drcmap_set_value(drcbe->map, dst, inst->param[0].value, inst->param[1].value);
3323
/***************************************************************************
3324
CONTROL FLOW OPCODES
3325
***************************************************************************/
3327
/*-------------------------------------------------
3328
op_nop - process a NOP opcode
3329
-------------------------------------------------*/
3331
static x86code *op_nop(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3338
/*-------------------------------------------------
3339
op_debug - process a DEBUG opcode
3340
-------------------------------------------------*/
3342
static x86code *op_debug(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3344
emit_link skip = { 0 };
3346
/* validate instruction */
3347
assert(inst->size == 4);
3348
assert_no_condition(inst);
3349
assert_no_flags(inst);
3351
if ((drcbe->device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0)
2911
emit_jmp_short_link(dst, skip); // jmp skip
2913
// register the current pointer for the handle
2914
inst.param(0).handle().set_codeptr(dst);
2916
// by default, the handle points to prolog code that moves the stack pointer
2917
emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, -28)); // lea rsp,[rsp-28]
2918
track_resolve_link(dst, skip); // skip:
2922
//-------------------------------------------------
2923
// op_hash - process a HASH opcode
2924
//-------------------------------------------------
2926
void drcbe_x86::op_hash(x86code *&dst, const instruction &inst)
2928
assert_no_condition(inst);
2929
assert_no_flags(inst);
2930
assert(inst.numparams() == 2);
2931
assert(inst.param(0).is_immediate());
2932
assert(inst.param(1).is_immediate());
2934
// register the current pointer for the mode/PC
2935
m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), dst);
2936
reset_last_upper_lower_reg();
2940
//-------------------------------------------------
2941
// op_label - process a LABEL opcode
2942
//-------------------------------------------------
2944
void drcbe_x86::op_label(x86code *&dst, const instruction &inst)
2946
assert_no_condition(inst);
2947
assert_no_flags(inst);
2948
assert(inst.numparams() == 1);
2949
assert(inst.param(0).is_code_label());
2951
// register the current pointer for the label
2952
m_labels.set_codeptr(inst.param(0).label(), dst);
2953
reset_last_upper_lower_reg();
2957
//-------------------------------------------------
2958
// op_comment - process a COMMENT opcode
2959
//-------------------------------------------------
2961
void drcbe_x86::op_comment(x86code *&dst, const instruction &inst)
2963
assert_no_condition(inst);
2964
assert_no_flags(inst);
2965
assert(inst.numparams() == 1);
2966
assert(inst.param(0).is_string());
2972
//-------------------------------------------------
2973
// op_mapvar - process a MAPVAR opcode
2974
//-------------------------------------------------
2976
void drcbe_x86::op_mapvar(x86code *&dst, const instruction &inst)
2978
assert_no_condition(inst);
2979
assert_no_flags(inst);
2980
assert(inst.numparams() == 2);
2981
assert(inst.param(0).is_mapvar());
2982
assert(inst.param(1).is_immediate());
2984
// set the value of the specified mapvar
2985
m_map.set_value(dst, inst.param(0).mapvar(), inst.param(1).immediate());
2990
//**************************************************************************
2991
// CONTROL FLOW OPCODES
2992
//**************************************************************************
2994
//-------------------------------------------------
2995
// op_nop - process a NOP opcode
2996
//-------------------------------------------------
2998
void drcbe_x86::op_nop(x86code *&dst, const instruction &inst)
3004
//-------------------------------------------------
3005
// op_debug - process a DEBUG opcode
3006
//-------------------------------------------------
3008
void drcbe_x86::op_debug(x86code *&dst, const instruction &inst)
3010
// validate instruction
3011
assert(inst.size() == 4);
3012
assert_no_condition(inst);
3013
assert_no_flags(inst);
3015
if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
3353
drcuml_parameter pcp;
3355
/* normalize parameters */
3356
param_normalize_1(drcbe, inst, &pcp, PTYPE_MRI);
3358
/* test and branch */
3359
emit_test_m32_imm(&dst, MABS(&drcbe->device->machine->debug_flags), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK
3360
emit_jcc_short_link(&dst, COND_Z, &skip); // jz skip
3362
/* push the parameter */
3363
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &pcp); // mov [esp+4],pcp
3364
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)drcbe->device); // mov [esp],device
3365
emit_call(&dst, (x86code *)debugger_instruction_hook); // call debug_cpu_instruction_hook
3367
track_resolve_link(drcbe, &dst, &skip); // skip:
3017
// normalize parameters
3018
be_parameter pcp(*this, inst.param(0), PTYPE_MRI);
3021
emit_test_m32_imm(dst, MABS(&m_device.machine().debug_flags), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK
3022
emit_link skip = { 0 };
3023
emit_jcc_short_link(dst, x86emit::COND_Z, skip); // jz skip
3025
// push the parameter
3026
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), pcp); // mov [esp+4],pcp
3027
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_device); // mov [esp],device
3028
emit_call(dst, (x86code *)debugger_instruction_hook); // call debug_cpu_instruction_hook
3030
track_resolve_link(dst, skip); // skip:
3374
/*-------------------------------------------------
3375
op_exit - process an EXIT opcode
3376
-------------------------------------------------*/
3035
//-------------------------------------------------
3036
// op_exit - process an EXIT opcode
3037
//-------------------------------------------------
3378
static x86code *op_exit(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3039
void drcbe_x86::op_exit(x86code *&dst, const instruction &inst)
3380
drcuml_parameter retp;
3382
/* validate instruction */
3383
assert(inst->size == 4);
3041
// validate instruction
3042
assert(inst.size() == 4);
3384
3043
assert_any_condition(inst);
3385
3044
assert_no_flags(inst);
3387
/* normalize parameters */
3388
param_normalize_1(drcbe, inst, &retp, PTYPE_MRI);
3046
// normalize parameters
3047
be_parameter retp(*this, inst.param(0), PTYPE_MRI);
3390
/* load the parameter into EAX */
3391
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &retp); // mov eax,retp
3392
if (inst->condition == DRCUML_COND_ALWAYS)
3393
emit_jmp(&dst, drcbe->exit); // jmp exit
3049
// load the parameter into EAX
3050
emit_mov_r32_p32(dst, REG_EAX, retp); // mov eax,retp
3051
if (inst.condition() == uml::COND_ALWAYS)
3052
emit_jmp(dst, m_exit); // jmp exit
3395
emit_jcc(&dst, X86_CONDITION(inst->condition), drcbe->exit); // jcc exit
3054
emit_jcc(dst, X86_CONDITION(inst.condition()), m_exit); // jcc exit
3401
/*-------------------------------------------------
3402
op_hashjmp - process a HASHJMP opcode
3403
-------------------------------------------------*/
3058
//-------------------------------------------------
3059
// op_hashjmp - process a HASHJMP opcode
3060
//-------------------------------------------------
3405
static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3062
void drcbe_x86::op_hashjmp(x86code *&dst, const instruction &inst)
3407
drcuml_parameter modep, pcp, exp;
3409
/* validate instruction */
3410
assert(inst->size == 4);
3064
// validate instruction
3065
assert(inst.size() == 4);
3411
3066
assert_no_condition(inst);
3412
3067
assert_no_flags(inst);
3414
/* normalize parameters */
3415
param_normalize_3(drcbe, inst, &modep, PTYPE_MRI, &pcp, PTYPE_MRI, &exp, PTYPE_M);
3069
// normalize parameters
3070
be_parameter modep(*this, inst.param(0), PTYPE_MRI);
3071
be_parameter pcp(*this, inst.param(1), PTYPE_MRI);
3072
const parameter &exp = inst.param(2);
3073
assert(exp.is_code_handle());
3417
3075
if (LOG_HASHJMPS)
3419
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &pcp);
3420
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 0), &modep);
3421
emit_call(&dst, (x86code *)debug_log_hashjmp);
3077
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), pcp);
3078
emit_mov_m32_p32(dst, MBD(REG_ESP, 0), modep);
3079
emit_call(dst, (x86code *)debug_log_hashjmp);
3424
/* load the stack base one word early so we end up at the right spot after our call below */
3425
emit_mov_r32_m32(&dst, REG_ESP, MABS(&drcbe->hashstacksave)); // mov esp,[hashstacksave]
3082
// load the stack base one word early so we end up at the right spot after our call below
3083
emit_mov_r32_m32(dst, REG_ESP, MABS(&m_hashstacksave)); // mov esp,[hashstacksave]
3427
/* fixed mode cases */
3428
if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->base[modep.value] != drcbe->hash->emptyl1)
3086
if (modep.is_immediate() && m_hash.is_mode_populated(modep.immediate()))
3430
/* a straight immediate jump is direct, though we need the PC in EAX in case of failure */
3431
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
3088
// a straight immediate jump is direct, though we need the PC in EAX in case of failure
3089
if (pcp.is_immediate())
3433
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
3434
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
3435
emit_call_m32(&dst, MABS(&drcbe->hash->base[modep.value][l1val][l2val])); // call hash[modep][l1val][l2val]
3091
UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
3092
UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
3093
emit_call_m32(dst, MABS(&m_hash.base()[modep.immediate()][l1val][l2val])); // call hash[modep][l1val][l2val]
3438
/* a fixed mode but variable PC */
3096
// a fixed mode but variable PC
3441
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
3442
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
3443
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
3444
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
3445
emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EDX, 4, &drcbe->hash->base[modep.value][0]));
3099
emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
3100
emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
3101
emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
3102
emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift());// and eax,l2mask << l2shift
3103
emit_mov_r32_m32(dst, REG_EDX, MABSI(&m_hash.base()[modep.immediate()][0], REG_EDX, 4));
3446
3104
// mov edx,hash[modep+edx*4]
3447
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift, 0)); // call [edx+eax*shift]
3105
emit_call_m32(dst, MBISD(REG_EDX, REG_EAX, 4 >> m_hash.l2shift(), 0));// call [edx+eax*shift]
3453
int modereg = param_select_register(REG_ECX, &modep, NULL);
3454
emit_mov_r32_p32(drcbe, &dst, modereg, &modep); // mov modereg,modep
3455
emit_mov_r32_m32(&dst, REG_ECX, MISD(modereg, 4, &drcbe->hash->base[0])); // mov ecx,hash[modereg*4]
3111
int modereg = modep.select_register(REG_ECX);
3112
emit_mov_r32_p32(dst, modereg, modep); // mov modereg,modep
3113
emit_mov_r32_m32(dst, REG_ECX, MABSI(m_hash.base(), modereg, 4)); // mov ecx,hash[modereg*4]
3458
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
3116
if (pcp.is_immediate())
3460
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
3461
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
3462
emit_mov_r32_m32(&dst, REG_EDX, MBD(REG_ECX, l1val*4)); // mov edx,[ecx+l1val*4]
3463
emit_call_m32(&dst, MBD(REG_EDX, l2val*4)); // call [l2val*4]
3118
UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
3119
UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
3120
emit_mov_r32_m32(dst, REG_EDX, MBD(REG_ECX, l1val*4)); // mov edx,[ecx+l1val*4]
3121
emit_call_m32(dst, MBD(REG_EDX, l2val*4)); // call [l2val*4]
3469
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
3470
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
3471
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
3472
emit_mov_r32_m32(&dst, REG_EDX, MBISD(REG_ECX, REG_EDX, 4, 0)); // mov edx,[ecx+edx*4]
3473
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
3474
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift, 0)); // call [edx+eax*shift]
3127
emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
3128
emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
3129
emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
3130
emit_mov_r32_m32(dst, REG_EDX, MBISD(REG_ECX, REG_EDX, 4, 0)); // mov edx,[ecx+edx*4]
3131
emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift());// and eax,l2mask << l2shift
3132
emit_call_m32(dst, MBISD(REG_EDX, REG_EAX, 4 >> m_hash.l2shift(), 0));// call [edx+eax*shift]
3478
/* in all cases, if there is no code, we return here to generate the exception */
3479
emit_mov_m32_p32(drcbe, &dst, MABS(&drcbe->state.exp), &pcp); // mov [exp],param
3480
emit_sub_r32_imm(&dst, REG_ESP, 4); // sub esp,4
3481
emit_call_m32(&dst, MABS(exp.value)); // call [exp]
3136
// in all cases, if there is no code, we return here to generate the exception
3137
emit_mov_m32_p32(dst, MABS(&m_state.exp), pcp); // mov [exp],param
3138
emit_sub_r32_imm(dst, REG_ESP, 4); // sub esp,4
3139
emit_call_m32(dst, MABS(exp.handle().codeptr_addr())); // call [exp]
3487
/*-------------------------------------------------
3488
op_jmp - process a JMP opcode
3489
-------------------------------------------------*/
3143
//-------------------------------------------------
3144
// op_jmp - process a JMP opcode
3145
//-------------------------------------------------
3491
static x86code *op_jmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3147
void drcbe_x86::op_jmp(x86code *&dst, const instruction &inst)
3493
drcuml_parameter labelp;
3496
/* validate instruction */
3497
assert(inst->size == 4);
3149
// validate instruction
3150
assert(inst.size() == 4);
3498
3151
assert_any_condition(inst);
3499
3152
assert_no_flags(inst);
3501
/* normalize parameters */
3502
param_normalize_1(drcbe, inst, &labelp, PTYPE_I);
3154
// normalize parameters
3155
const parameter &labelp = inst.param(0);
3156
assert(labelp.is_code_label());
3504
/* look up the jump target and jump there */
3505
jmptarget = (x86code *)drclabel_get_codeptr(drcbe->labels, labelp.value, fixup_label, dst);
3506
if (inst->condition == DRCUML_COND_ALWAYS)
3507
emit_jmp(&dst, jmptarget); // jmp target
3158
// look up the jump target and jump there
3159
x86code *jmptarget = (x86code *)m_labels.get_codeptr(labelp.label(), fixup_label, dst);
3160
if (inst.condition() == uml::COND_ALWAYS)
3161
emit_jmp(dst, jmptarget); // jmp target
3509
emit_jcc(&dst, X86_CONDITION(inst->condition), jmptarget); // jcc target
3163
emit_jcc(dst, X86_CONDITION(inst.condition()), jmptarget); // jcc target
3515
/*-------------------------------------------------
3516
op_exh - process an EXH opcode
3517
-------------------------------------------------*/
3167
//-------------------------------------------------
3168
// op_exh - process an EXH opcode
3169
//-------------------------------------------------
3519
static x86code *op_exh(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3171
void drcbe_x86::op_exh(x86code *&dst, const instruction &inst)
3521
drcuml_parameter handp, exp;
3522
drccodeptr *targetptr;
3524
/* validate instruction */
3525
assert(inst->size == 4);
3173
// validate instruction
3174
assert(inst.size() == 4);
3526
3175
assert_any_condition(inst);
3527
3176
assert_no_flags(inst);
3529
/* normalize parameters */
3530
param_normalize_2(drcbe, inst, &handp, PTYPE_M, &exp, PTYPE_MRI);
3532
/* look up the handle target */
3533
targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3535
/* perform the exception processing inline if unconditional */
3536
if (inst->condition == DRCUML_COND_ALWAYS)
3178
// normalize parameters
3179
const parameter &handp = inst.param(0);
3180
assert(handp.is_code_handle());
3181
be_parameter exp(*this, inst.param(1), PTYPE_MRI);
3183
// look up the handle target
3184
drccodeptr *targetptr = handp.handle().codeptr_addr();
3186
// perform the exception processing inline if unconditional
3187
if (inst.condition() == uml::COND_ALWAYS)
3538
emit_mov_m32_p32(drcbe, &dst, MABS(&drcbe->state.exp), &exp); // mov [exp],exp
3189
emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
3539
3190
if (*targetptr != NULL)
3540
emit_call(&dst, *targetptr); // call *targetptr
3191
emit_call(dst, *targetptr); // call *targetptr
3542
emit_call_m32(&dst, MABS(targetptr)); // call [targetptr]
3193
emit_call_m32(dst, MABS(targetptr)); // call [targetptr]
3545
/* otherwise, jump to an out-of-band handler */
3196
// otherwise, jump to an out-of-band handler
3548
emit_jcc(&dst, X86_CONDITION(inst->condition), 0); // jcc exception
3549
drccache_request_oob_codegen(drcbe->cache, fixup_exception, drcbe, dst, (void *)inst);
3199
emit_jcc(dst, X86_CONDITION(inst.condition()), 0); // jcc exception
3200
m_cache.request_oob_codegen(oob_func_stub<drcbe_x86, &drcbe_x86::fixup_exception>, dst, &const_cast<instruction &>(inst), this);
3555
/*-------------------------------------------------
3556
op_callh - process a CALLH opcode
3557
-------------------------------------------------*/
3205
//-------------------------------------------------
3206
// op_callh - process a CALLH opcode
3207
//-------------------------------------------------
3559
static x86code *op_callh(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3209
void drcbe_x86::op_callh(x86code *&dst, const instruction &inst)
3561
drcuml_parameter handp;
3562
drccodeptr *targetptr;
3563
emit_link skip = { 0 };
3565
/* validate instruction */
3566
assert(inst->size == 4);
3211
// validate instruction
3212
assert(inst.size() == 4);
3567
3213
assert_any_condition(inst);
3568
3214
assert_no_flags(inst);
3570
/* normalize parameters */
3571
param_normalize_1(drcbe, inst, &handp, PTYPE_M);
3573
/* look up the handle target */
3574
targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3576
/* skip if conditional */
3577
if (inst->condition != DRCUML_COND_ALWAYS)
3578
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condition), &skip); // jcc skip
3580
/* jump through the handle; directly if a normal jump */
3216
// normalize parameters
3217
const parameter &handp = inst.param(0);
3218
assert(handp.is_code_handle());
3220
// look up the handle target
3221
drccodeptr *targetptr = handp.handle().codeptr_addr();
3223
// skip if conditional
3224
emit_link skip = { 0 };
3225
if (inst.condition() != uml::COND_ALWAYS)
3226
emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
3228
// jump through the handle; directly if a normal jump
3581
3229
if (*targetptr != NULL)
3582
emit_call(&dst, *targetptr); // call *targetptr
3584
emit_call_m32(&dst, MABS(targetptr)); // call [targetptr]
3586
/* resolve the conditional link */
3587
if (inst->condition != DRCUML_COND_ALWAYS)
3588
track_resolve_link(drcbe, &dst, &skip); // skip:
3593
/*-------------------------------------------------
3594
op_ret - process a RET opcode
3595
-------------------------------------------------*/
3597
static x86code *op_ret(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3599
emit_link skip = { 0 };
3601
/* validate instruction */
3602
assert(inst->size == 4);
3603
assert_any_condition(inst);
3604
assert_no_flags(inst);
3605
assert(inst->numparams == 0);
3607
/* skip if conditional */
3608
if (inst->condition != DRCUML_COND_ALWAYS)
3609
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condition), &skip); // jcc skip
3612
emit_lea_r32_m32(&dst, REG_ESP, MBD(REG_ESP, 28)); // lea rsp,[rsp+28]
3613
emit_ret(&dst); // ret
3615
/* resolve the conditional link */
3616
if (inst->condition != DRCUML_COND_ALWAYS)
3617
track_resolve_link(drcbe, &dst, &skip); // skip:
3622
/*-------------------------------------------------
3623
op_callc - process a CALLC opcode
3624
-------------------------------------------------*/
3626
static x86code *op_callc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3628
drcuml_parameter funcp, paramp;
3629
emit_link skip = { 0 };
3631
/* validate instruction */
3632
assert(inst->size == 4);
3633
assert_any_condition(inst);
3634
assert_no_flags(inst);
3636
/* normalize parameters */
3637
param_normalize_2(drcbe, inst, &funcp, PTYPE_M, ¶mp, PTYPE_M);
3639
/* skip if conditional */
3640
if (inst->condition != DRCUML_COND_ALWAYS)
3641
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condition), &skip); // jcc skip
3643
/* perform the call */
3644
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), paramp.value); // mov [esp],paramp
3645
emit_call(&dst, (x86code *)(FPTR)funcp.value); // call funcp
3647
/* resolve the conditional link */
3648
if (inst->condition != DRCUML_COND_ALWAYS)
3649
track_resolve_link(drcbe, &dst, &skip); // skip:
3654
/*-------------------------------------------------
3655
op_recover - process a RECOVER opcode
3656
-------------------------------------------------*/
3658
static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3660
drcuml_parameter dstp;
3662
/* validate instruction */
3663
assert(inst->size == 4);
3664
assert_no_condition(inst);
3665
assert_no_flags(inst);
3667
/* normalize parameters */
3668
param_normalize(drcbe, &inst->param[0], &dstp, PTYPE_MR);
3670
/* call the recovery code */
3671
emit_mov_r32_m32(&dst, REG_EAX, MABS(&drcbe->stacksave)); // mov eax,stacksave
3672
emit_mov_r32_m32(&dst, REG_EAX, MBD(REG_EAX, -4)); // mov eax,[eax-4]
3673
emit_sub_r32_imm(&dst, REG_EAX, 1); // sub eax,1
3674
emit_mov_m32_imm(&dst, MBD(REG_ESP, 8), inst->param[1].value); // mov [esp+8],param1
3675
emit_mov_m32_r32(&dst, MBD(REG_ESP, 4), REG_EAX); // mov [esp+4],eax
3676
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)drcbe->map); // mov [esp],drcbe->map
3677
emit_call(&dst, (x86code *)drcmap_get_value); // call drcmap_get_value
3678
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
3685
/***************************************************************************
3686
INTERNAL REGISTER OPCODES
3687
***************************************************************************/
3689
/*-------------------------------------------------
3690
op_setfmod - process a SETFMOD opcode
3691
-------------------------------------------------*/
3693
static x86code *op_setfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3695
drcuml_parameter srcp;
3697
/* validate instruction */
3698
assert(inst->size == 4);
3699
assert_no_condition(inst);
3700
assert_no_flags(inst);
3702
/* normalize parameters */
3703
param_normalize_1(drcbe, inst, &srcp, PTYPE_MRI);
3705
/* immediate case */
3706
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
3709
emit_mov_m8_imm(&dst, MABS(&drcbe->state.fmod), srcp.value); // mov [fmod],srcp
3710
emit_fldcw_m16(&dst, MABS(&fp_control[srcp.value])); // fldcw fp_control[srcp]
3713
/* register/memory case */
3716
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &srcp); // mov eax,srcp
3717
emit_and_r32_imm(&dst, REG_EAX, 3); // and eax,3
3718
emit_mov_m8_r8(&dst, MABS(&drcbe->state.fmod), REG_AL); // mov [fmod],al
3719
emit_fldcw_m16(&dst, MISD(REG_EAX, 2, &fp_control[0])); // fldcw fp_control[eax]
3726
/*-------------------------------------------------
3727
op_getfmod - process a GETFMOD opcode
3728
-------------------------------------------------*/
3730
static x86code *op_getfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3732
drcuml_parameter dstp;
3734
/* validate instruction */
3735
assert(inst->size == 4);
3736
assert_no_condition(inst);
3737
assert_no_flags(inst);
3739
/* normalize parameters */
3740
param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
3742
/* fetch the current mode and store to the destination */
3743
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
3744
emit_movzx_r32_m8(&dst, dstp.value, MABS(&drcbe->state.fmod)); // movzx reg,[fmod]
3747
emit_movzx_r32_m8(&dst, REG_EAX, MABS(&drcbe->state.fmod)); // movzx eax,[fmod]
3748
emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
3755
/*-------------------------------------------------
3756
op_getexp - process a GETEXP opcode
3757
-------------------------------------------------*/
3759
static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3761
drcuml_parameter dstp;
3763
/* validate instruction */
3764
assert(inst->size == 4);
3765
assert_no_condition(inst);
3766
assert_no_flags(inst);
3768
/* normalize parameters */
3769
param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
3771
/* fetch the exception parameter and store to the destination */
3772
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
3773
emit_mov_r32_m32(&dst, dstp.value, MABS(&drcbe->state.exp)); // mov reg,[exp]
3776
emit_mov_r32_m32(&dst, REG_EAX, MABS(&drcbe->state.exp)); // mov eax,[exp]
3777
emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
3784
/*-------------------------------------------------
3785
op_getflgs - process a GETFLGS opcode
3786
-------------------------------------------------*/
3788
static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3790
drcuml_parameter dstp, maskp;
3230
emit_call(dst, *targetptr); // call *targetptr
3232
emit_call_m32(dst, MABS(targetptr)); // call [targetptr]
3234
// resolve the conditional link
3235
if (inst.condition() != uml::COND_ALWAYS)
3236
track_resolve_link(dst, skip); // skip:
3240
//-------------------------------------------------
3241
// op_ret - process a RET opcode
3242
//-------------------------------------------------
3244
void drcbe_x86::op_ret(x86code *&dst, const instruction &inst)
3246
// validate instruction
3247
assert(inst.size() == 4);
3248
assert_any_condition(inst);
3249
assert_no_flags(inst);
3250
assert(inst.numparams() == 0);
3252
// skip if conditional
3253
emit_link skip = { 0 };
3254
if (inst.condition() != uml::COND_ALWAYS)
3255
emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
3258
emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, 28)); // lea rsp,[rsp+28]
3259
emit_ret(dst); // ret
3261
// resolve the conditional link
3262
if (inst.condition() != uml::COND_ALWAYS)
3263
track_resolve_link(dst, skip); // skip:
3267
//-------------------------------------------------
3268
// op_callc - process a CALLC opcode
3269
//-------------------------------------------------
3271
void drcbe_x86::op_callc(x86code *&dst, const instruction &inst)
3273
// validate instruction
3274
assert(inst.size() == 4);
3275
assert_any_condition(inst);
3276
assert_no_flags(inst);
3278
// normalize parameters
3279
const parameter &funcp = inst.param(0);
3280
assert(funcp.is_c_function());
3281
be_parameter paramp(*this, inst.param(1), PTYPE_M);
3283
// skip if conditional
3284
emit_link skip = { 0 };
3285
if (inst.condition() != uml::COND_ALWAYS)
3286
emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
3289
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)paramp.memory()); // mov [esp],paramp
3290
emit_call(dst, (x86code *)(FPTR)funcp.cfunc()); // call funcp
3292
// resolve the conditional link
3293
if (inst.condition() != uml::COND_ALWAYS)
3294
track_resolve_link(dst, skip); // skip:
3298
//-------------------------------------------------
3299
// op_recover - process a RECOVER opcode
3300
//-------------------------------------------------
3302
void drcbe_x86::op_recover(x86code *&dst, const instruction &inst)
3304
// validate instruction
3305
assert(inst.size() == 4);
3306
assert_no_condition(inst);
3307
assert_no_flags(inst);
3309
// normalize parameters
3310
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3312
// call the recovery code
3313
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_stacksave)); // mov eax,stacksave
3314
emit_mov_r32_m32(dst, REG_EAX, MBD(REG_EAX, -4)); // mov eax,[eax-4]
3315
emit_sub_r32_imm(dst, REG_EAX, 1); // sub eax,1
3316
emit_mov_m32_imm(dst, MBD(REG_ESP, 8), inst.param(1).mapvar()); // mov [esp+8],param1
3317
emit_mov_m32_r32(dst, MBD(REG_ESP, 4), REG_EAX); // mov [esp+4],eax
3318
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_map); // mov [esp],m_map
3319
emit_call(dst, (x86code *)&drc_map_variables::static_get_value); // call drcmap_get_value
3320
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
3325
//**************************************************************************
3326
// INTERNAL REGISTER OPCODES
3327
//**************************************************************************
3329
//-------------------------------------------------
3330
// op_setfmod - process a SETFMOD opcode
3331
//-------------------------------------------------
3333
void drcbe_x86::op_setfmod(x86code *&dst, const instruction &inst)
3335
// validate instruction
3336
assert(inst.size() == 4);
3337
assert_no_condition(inst);
3338
assert_no_flags(inst);
3340
// normalize parameters
3341
be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
3344
if (srcp.is_immediate())
3346
int value = srcp.immediate() & 3;
3347
emit_mov_m8_imm(dst, MABS(&m_state.fmod), value); // mov [fmod],srcp
3348
emit_fldcw_m16(dst, MABS(&fp_control[value])); // fldcw fp_control[srcp]
3351
// register/memory case
3354
emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
3355
emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
3356
emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
3357
emit_fldcw_m16(dst, MABSI(&fp_control[0], REG_EAX, 2)); // fldcw fp_control[eax]
3362
//-------------------------------------------------
3363
// op_getfmod - process a GETFMOD opcode
3364
//-------------------------------------------------
3366
void drcbe_x86::op_getfmod(x86code *&dst, const instruction &inst)
3368
// validate instruction
3369
assert(inst.size() == 4);
3370
assert_no_condition(inst);
3371
assert_no_flags(inst);
3373
// normalize parameters
3374
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3376
// fetch the current mode and store to the destination
3377
if (dstp.is_int_register())
3378
emit_movzx_r32_m8(dst, dstp.ireg(), MABS(&m_state.fmod)); // movzx reg,[fmod]
3381
emit_movzx_r32_m8(dst, REG_EAX, MABS(&m_state.fmod)); // movzx eax,[fmod]
3382
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
3387
//-------------------------------------------------
3388
// op_getexp - process a GETEXP opcode
3389
//-------------------------------------------------
3391
void drcbe_x86::op_getexp(x86code *&dst, const instruction &inst)
3393
// validate instruction
3394
assert(inst.size() == 4);
3395
assert_no_condition(inst);
3396
assert_no_flags(inst);
3398
// normalize parameters
3399
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3401
// fetch the exception parameter and store to the destination
3402
if (dstp.is_int_register())
3403
emit_mov_r32_m32(dst, dstp.ireg(), MABS(&m_state.exp)); // mov reg,[exp]
3406
emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
3407
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
3412
//-------------------------------------------------
3413
// op_getflgs - process a GETFLGS opcode
3414
//-------------------------------------------------
3416
void drcbe_x86::op_getflgs(x86code *&dst, const instruction &inst)
3418
// validate instruction
3419
assert(inst.size() == 4);
3420
assert_no_condition(inst);
3421
assert_no_flags(inst);
3423
// normalize parameters
3424
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3425
be_parameter maskp(*this, inst.param(1), PTYPE_I);
3427
// pick a target register for the general case
3428
int dstreg = dstp.select_register(REG_EAX);
3430
// compute mask for flags
3791
3431
UINT32 flagmask = 0;
3794
/* validate instruction */
3795
assert(inst->size == 4);
3796
assert_no_condition(inst);
3797
assert_no_flags(inst);
3799
/* normalize parameters */
3800
param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &maskp, PTYPE_I);
3802
/* pick a target register for the general case */
3803
dstreg = param_select_register(REG_EAX, &dstp, NULL);
3805
/* compute mask for flags */
3806
if (maskp.value & DRCUML_FLAG_C) flagmask |= 0x001;
3807
if (maskp.value & DRCUML_FLAG_V) flagmask |= 0x800;
3808
if (maskp.value & DRCUML_FLAG_Z) flagmask |= 0x040;
3809
if (maskp.value & DRCUML_FLAG_S) flagmask |= 0x080;
3810
if (maskp.value & DRCUML_FLAG_U) flagmask |= 0x004;
3812
switch (maskp.value)
3432
if (maskp.immediate() & FLAG_C) flagmask |= 0x001;
3433
if (maskp.immediate() & FLAG_V) flagmask |= 0x800;
3434
if (maskp.immediate() & FLAG_Z) flagmask |= 0x040;
3435
if (maskp.immediate() & FLAG_S) flagmask |= 0x080;
3436
if (maskp.immediate() & FLAG_U) flagmask |= 0x004;
3438
switch (maskp.immediate())
3814
/* single flags only */
3816
emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
3817
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3821
emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
3822
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3823
emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
3827
emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
3828
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3829
emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
3833
emit_setcc_r8(&dst, COND_S, REG_AL); // sets al
3834
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3835
emit_shl_r32_imm(&dst, dstreg, 3); // shl dstreg,3
3839
emit_setcc_r8(&dst, COND_P, REG_AL); // setp al
3840
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3841
emit_shl_r32_imm(&dst, dstreg, 4); // shl dstreg,4
3844
/* carry plus another flag */
3845
case DRCUML_FLAG_C | DRCUML_FLAG_V:
3846
emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
3847
emit_setcc_r8(&dst, COND_O, REG_CL); // seto cl
3848
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3849
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3850
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3853
case DRCUML_FLAG_C | DRCUML_FLAG_Z:
3854
emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
3855
emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
3856
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3857
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3858
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
3861
case DRCUML_FLAG_C | DRCUML_FLAG_S:
3862
emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
3863
emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
3864
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3865
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3866
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
3869
/* overflow plus another flag */
3870
case DRCUML_FLAG_V | DRCUML_FLAG_Z:
3871
emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
3872
emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
3873
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3874
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3875
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3876
emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
3879
case DRCUML_FLAG_V | DRCUML_FLAG_S:
3880
emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
3881
emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
3882
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3883
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3884
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
3885
emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
3888
/* zero plus another flag */
3889
case DRCUML_FLAG_Z | DRCUML_FLAG_S:
3890
emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
3891
emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
3892
emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
3893
emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
3894
emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3895
emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
3440
// single flags only
3442
emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
3443
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
3447
emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
3448
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
3449
emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
3453
emit_setcc_r8(dst, x86emit::COND_Z, REG_AL); // setz al
3454
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
3455
emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
3459
emit_setcc_r8(dst, x86emit::COND_S, REG_AL); // sets al
3460
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
3461
emit_shl_r32_imm(dst, dstreg, 3); // shl dstreg,3
3465
emit_setcc_r8(dst, x86emit::COND_P, REG_AL); // setp al
3466
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
3467
emit_shl_r32_imm(dst, dstreg, 4); // shl dstreg,4
3470
// carry plus another flag
3471
case FLAG_C | FLAG_V:
3472
emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
3473
emit_setcc_r8(dst, x86emit::COND_O, REG_CL); // seto cl
3474
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3475
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3476
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3479
case FLAG_C | FLAG_Z:
3480
emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
3481
emit_setcc_r8(dst, x86emit::COND_Z, REG_CL); // setz cl
3482
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3483
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3484
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
3487
case FLAG_C | FLAG_S:
3488
emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
3489
emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
3490
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3491
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3492
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
3495
// overflow plus another flag
3496
case FLAG_V | FLAG_Z:
3497
emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
3498
emit_setcc_r8(dst, x86emit::COND_Z, REG_CL); // setz cl
3499
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3500
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3501
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3502
emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
3505
case FLAG_V | FLAG_S:
3506
emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
3507
emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
3508
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3509
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3510
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
3511
emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
3514
// zero plus another flag
3515
case FLAG_Z | FLAG_S:
3516
emit_setcc_r8(dst, x86emit::COND_Z, REG_AL); // setz al
3517
emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
3518
emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
3519
emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
3520
emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
3521
emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
3900
emit_pushf(&dst); // pushf
3901
emit_pop_r32(&dst, REG_EAX); // pop eax
3902
emit_and_r32_imm(&dst, REG_EAX, flagmask); // and eax,flagmask
3903
emit_movzx_r32_m8(&dst, dstreg, MBD(REG_EAX, flags_map)); // movzx dstreg,[flags_map]
3526
emit_pushf(dst); // pushf
3527
emit_pop_r32(dst, REG_EAX); // pop eax
3528
emit_and_r32_imm(dst, REG_EAX, flagmask); // and eax,flagmask
3529
emit_movzx_r32_m8(dst, dstreg, MABSI(flags_map, REG_EAX)); // movzx dstreg,[flags_map]
3907
/* store low 32 bits */
3908
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
3533
// store low 32 bits
3534
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
3910
/* 64-bit form stores upper 32 bits */
3911
if (inst->size == 8)
3536
// 64-bit form stores upper 32 bits
3537
if (inst.size() == 8)
3914
if (dstp.type == DRCUML_PTYPE_MEMORY)
3915
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
3916
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
3917
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
3540
if (dstp.is_memory())
3541
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
3542
else if (dstp.is_int_register())
3543
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
3923
/*-------------------------------------------------
3924
op_save - process a SAVE opcode
3925
-------------------------------------------------*/
3927
static x86code *op_save(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3929
drcuml_parameter dstp;
3931
/* validate instruction */
3932
assert(inst->size == 4);
3933
assert_no_condition(inst);
3934
assert_no_flags(inst);
3936
/* normalize parameters */
3937
param_normalize_1(drcbe, inst, &dstp, PTYPE_M);
3939
/* copy live state to the destination */
3940
emit_mov_r32_imm(&dst, REG_ECX, dstp.value); // mov ecx,dstp
3941
emit_call(&dst, drcbe->save); // call save
3946
/*-------------------------------------------------
3947
op_restore - process a RESTORE opcode
3948
-------------------------------------------------*/
3950
static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3952
drcuml_parameter dstp;
3954
/* validate instruction */
3955
assert(inst->size == 4);
3956
assert_no_condition(inst);
3958
/* normalize parameters */
3959
param_normalize_1(drcbe, inst, &dstp, PTYPE_M);
3961
/* copy live state from the destination */
3962
emit_mov_r32_imm(&dst, REG_ECX, dstp.value); // mov ecx,dstp
3963
emit_call(&dst, drcbe->restore); // call restore
3969
/***************************************************************************
3971
***************************************************************************/
3973
/*-------------------------------------------------
3974
op_load - process a LOAD opcode
3975
-------------------------------------------------*/
3977
static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3979
drcuml_parameter dstp, basep, indp, scalesizep;
3980
int dstreg, scale, size;
3982
/* validate instruction */
3983
assert(inst->size == 4 || inst->size == 8);
3984
assert_no_condition(inst);
3985
assert_no_flags(inst);
3987
/* normalize parameters */
3988
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &scalesizep, PTYPE_I);
3989
scale = 1 << (scalesizep.value / 16);
3990
size = scalesizep.value % 16;
3992
/* pick a target register for the general case */
3993
dstreg = param_select_register(REG_EAX, &dstp, NULL);
3995
/* immediate index */
3996
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
3548
//-------------------------------------------------
3549
// op_save - process a SAVE opcode
3550
//-------------------------------------------------
3552
void drcbe_x86::op_save(x86code *&dst, const instruction &inst)
3554
// validate instruction
3555
assert(inst.size() == 4);
3556
assert_no_condition(inst);
3557
assert_no_flags(inst);
3559
// normalize parameters
3560
be_parameter dstp(*this, inst.param(0), PTYPE_M);
3562
// copy live state to the destination
3563
emit_mov_r32_imm(dst, REG_ECX, (FPTR)dstp.memory()); // mov ecx,dstp
3564
emit_call(dst, m_save); // call save
3568
//-------------------------------------------------
3569
// op_restore - process a RESTORE opcode
3570
//-------------------------------------------------
3572
void drcbe_x86::op_restore(x86code *&dst, const instruction &inst)
3574
// validate instruction
3575
assert(inst.size() == 4);
3576
assert_no_condition(inst);
3578
// normalize parameters
3579
be_parameter srcp(*this, inst.param(0), PTYPE_M);
3581
// copy live state from the destination
3582
emit_mov_r32_imm(dst, REG_ECX, (FPTR)srcp.memory()); // mov ecx,dstp
3583
emit_call(dst, m_restore); // call restore
3588
//**************************************************************************
3589
// INTEGER OPERATIONS
3590
//**************************************************************************
3592
//-------------------------------------------------
3593
// op_load - process a LOAD opcode
3594
//-------------------------------------------------
3596
void drcbe_x86::op_load(x86code *&dst, const instruction &inst)
3598
// validate instruction
3599
assert(inst.size() == 4 || inst.size() == 8);
3600
assert_no_condition(inst);
3601
assert_no_flags(inst);
3603
// normalize parameters
3604
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3605
be_parameter basep(*this, inst.param(1), PTYPE_M);
3606
be_parameter indp(*this, inst.param(2), PTYPE_MRI);
3607
const parameter &scalesizep = inst.param(3);
3608
assert(scalesizep.is_size_scale());
3609
int scale = 1 << scalesizep.scale();
3610
int size = scalesizep.size();
3612
// pick a target register for the general case
3613
int dstreg = dstp.select_register(REG_EAX);
3616
if (indp.is_immediate())
3998
if (size == DRCUML_SIZE_BYTE)
3999
emit_movzx_r32_m8(&dst, dstreg, MABS(basep.value + scale*indp.value)); // movzx dstreg,[basep + scale*indp]
4000
else if (size == DRCUML_SIZE_WORD)
4001
emit_movzx_r32_m16(&dst, dstreg, MABS(basep.value + scale*indp.value)); // movzx dstreg,[basep + scale*indp]
4002
else if (size == DRCUML_SIZE_DWORD)
4003
emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + scale*indp.value)); // mov dstreg,[basep + scale*indp]
4004
else if (size == DRCUML_SIZE_QWORD)
3618
if (size == SIZE_BYTE)
3619
emit_movzx_r32_m8(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movzx dstreg,[basep + scale*indp]
3620
else if (size == SIZE_WORD)
3621
emit_movzx_r32_m16(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movzx dstreg,[basep + scale*indp]
3622
else if (size == SIZE_DWORD)
3623
emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
3624
else if (size == SIZE_QWORD)
4006
emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + scale*indp.value + 4)); // mov edx,[basep + scale*indp + 4]
4007
emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + scale*indp.value)); // mov dstreg,[basep + scale*indp]
3626
emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(scale*indp.immediate() + 4))); // mov edx,[basep + scale*indp + 4]
3627
emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
4014
int indreg = param_select_register(REG_ECX, &indp, NULL);
4015
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
4016
if (size == DRCUML_SIZE_BYTE)
4017
emit_movzx_r32_m8(&dst, dstreg, MISD(indreg, scale, basep.value)); // movzx dstreg,[basep + scale*indp]
4018
else if (size == DRCUML_SIZE_WORD)
4019
emit_movzx_r32_m16(&dst, dstreg, MISD(indreg, scale, basep.value)); // movzx dstreg,[basep + scale*indp]
4020
else if (size == DRCUML_SIZE_DWORD)
4021
emit_mov_r32_m32(&dst, dstreg, MISD(indreg, scale, basep.value)); // mov dstreg,[basep + scale*indp]
4022
else if (size == DRCUML_SIZE_QWORD)
3634
int indreg = indp.select_register(REG_ECX);
3635
emit_mov_r32_p32(dst, indreg, indp);
3636
if (size == SIZE_BYTE)
3637
emit_movzx_r32_m8(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movzx dstreg,[basep + scale*indp]
3638
else if (size == SIZE_WORD)
3639
emit_movzx_r32_m16(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movzx dstreg,[basep + scale*indp]
3640
else if (size == SIZE_DWORD)
3641
emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
3642
else if (size == SIZE_QWORD)
4024
emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, scale, basep.value + 4)); // mov edx,[basep + scale*indp + 4]
4025
emit_mov_r32_m32(&dst, dstreg, MISD(indreg, scale, basep.value)); // mov dstreg,[basep + scale*indp]
3644
emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, scale)); // mov edx,[basep + scale*indp + 4]
3645
emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
4029
/* store low 32 bits */
4030
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
3649
// store low 32 bits
3650
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4032
/* 64-bit form stores upper 32 bits */
4033
if (inst->size == 8)
3652
// 64-bit form stores upper 32 bits
3653
if (inst.size() == 8)
4035
/* 1, 2, or 4-byte case */
4036
if (size != DRCUML_SIZE_QWORD)
3655
// 1, 2, or 4-byte case
3656
if (size != SIZE_QWORD)
4038
if (dstp.type == DRCUML_PTYPE_MEMORY)
4039
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
4040
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4041
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
3658
if (dstp.is_memory())
3659
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
3660
else if (dstp.is_int_register())
3661
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
4047
if (dstp.type == DRCUML_PTYPE_MEMORY)
4048
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
4049
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4050
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
4051
set_last_upper_reg(drcbe, dst, &dstp, REG_EDX);
3667
if (dstp.is_memory())
3668
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
3669
else if (dstp.is_int_register())
3670
emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
3671
set_last_upper_reg(dst, dstp, REG_EDX);
4054
set_last_lower_reg(drcbe, dst, &dstp, dstreg);
3674
set_last_lower_reg(dst, dstp, dstreg);
4059
/*-------------------------------------------------
4060
op_loads - process a LOADS opcode
4061
-------------------------------------------------*/
3678
//-------------------------------------------------
3679
// op_loads - process a LOADS opcode
3680
//-------------------------------------------------
4063
static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3682
void drcbe_x86::op_loads(x86code *&dst, const instruction &inst)
4065
drcuml_parameter dstp, basep, indp, scalesizep;
4066
int dstreg, scale, size;
4068
/* validate instruction */
4069
assert(inst->size == 4 || inst->size == 8);
3684
// validate instruction
3685
assert(inst.size() == 4 || inst.size() == 8);
4070
3686
assert_no_condition(inst);
4071
3687
assert_no_flags(inst);
4073
/* normalize parameters */
4074
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &scalesizep, PTYPE_I);
4075
scale = 1 << (scalesizep.value / 16);
4076
size = scalesizep.value % 16;
4078
/* pick a target register for the general case */
4079
dstreg = param_select_register(REG_EAX, &dstp, NULL);
4081
/* immediate index */
4082
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
3689
// normalize parameters
3690
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3691
be_parameter basep(*this, inst.param(1), PTYPE_M);
3692
be_parameter indp(*this, inst.param(2), PTYPE_MRI);
3693
const parameter &scalesizep = inst.param(3);
3694
assert(scalesizep.is_size_scale());
3695
int scale = 1 << scalesizep.scale();
3696
int size = scalesizep.size();
3698
// pick a target register for the general case
3699
int dstreg = dstp.select_register(REG_EAX);
3702
if (indp.is_immediate())
4084
if (size == DRCUML_SIZE_BYTE)
4085
emit_movsx_r32_m8(&dst, dstreg, MABS(basep.value + scale*indp.value)); // movsx dstreg,[basep + scale*indp]
4086
else if (size == DRCUML_SIZE_WORD)
4087
emit_movsx_r32_m16(&dst, dstreg, MABS(basep.value + scale*indp.value)); // movsx dstreg,[basep + scale*indp]
4088
else if (size == DRCUML_SIZE_DWORD)
4089
emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + scale*indp.value)); // mov dstreg,[basep + scale*indp]
4090
else if (size == DRCUML_SIZE_QWORD)
3704
if (size == SIZE_BYTE)
3705
emit_movsx_r32_m8(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movsx dstreg,[basep + scale*indp]
3706
else if (size == SIZE_WORD)
3707
emit_movsx_r32_m16(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movsx dstreg,[basep + scale*indp]
3708
else if (size == SIZE_DWORD)
3709
emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
3710
else if (size == SIZE_QWORD)
4092
emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + scale*indp.value + 4)); // mov edx,[basep + scale*indp + 4]
4093
emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + scale*indp.value)); // mov dstreg,[basep + scale*indp]
3712
emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(scale*indp.immediate() + 4))); // mov edx,[basep + scale*indp + 4]
3713
emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
4100
int indreg = param_select_register(REG_ECX, &indp, NULL);
4101
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
4102
if (size == DRCUML_SIZE_BYTE)
4103
emit_movsx_r32_m8(&dst, dstreg, MISD(indreg, scale, basep.value)); // movsx dstreg,[basep + scale*indp]
4104
else if (size == DRCUML_SIZE_WORD)
4105
emit_movsx_r32_m16(&dst, dstreg, MISD(indreg, scale, basep.value)); // movsx dstreg,[basep + scale*indp]
4106
else if (size == DRCUML_SIZE_DWORD)
4107
emit_mov_r32_m32(&dst, dstreg, MISD(indreg, scale, basep.value)); // mov dstreg,[basep + scale*indp]
4108
else if (size == DRCUML_SIZE_QWORD)
3720
int indreg = indp.select_register(REG_ECX);
3721
emit_mov_r32_p32(dst, indreg, indp);
3722
if (size == SIZE_BYTE)
3723
emit_movsx_r32_m8(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movsx dstreg,[basep + scale*indp]
3724
else if (size == SIZE_WORD)
3725
emit_movsx_r32_m16(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movsx dstreg,[basep + scale*indp]
3726
else if (size == SIZE_DWORD)
3727
emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
3728
else if (size == SIZE_QWORD)
4110
emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, scale, basep.value + 4)); // mov edx,[basep + scale*indp + 4]
4111
emit_mov_r32_m32(&dst, dstreg, MISD(indreg, scale, basep.value)); // mov dstreg,[basep + scale*indp]
3730
emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, scale)); // mov edx,[basep + scale*indp + 4]
3731
emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
4115
/* store low 32 bits */
4116
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
3735
// store low 32 bits
3736
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4118
/* 64-bit form stores upper 32 bits */
4119
if (inst->size == 8)
3738
// 64-bit form stores upper 32 bits
3739
if (inst.size() == 8)
4121
emit_cdq(&dst); // cdq
4122
if (dstp.type == DRCUML_PTYPE_MEMORY)
4123
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
4124
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4125
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
4126
set_last_upper_reg(drcbe, dst, &dstp, REG_EDX);
3741
emit_cdq(dst); // cdq
3742
if (dstp.is_memory())
3743
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
3744
else if (dstp.is_int_register())
3745
emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
3746
set_last_upper_reg(dst, dstp, REG_EDX);
4128
set_last_lower_reg(drcbe, dst, &dstp, dstreg);
3748
set_last_lower_reg(dst, dstp, dstreg);
4133
/*-------------------------------------------------
4134
op_store - process a STORE opcode
4135
-------------------------------------------------*/
3752
//-------------------------------------------------
3753
// op_store - process a STORE opcode
3754
//-------------------------------------------------
4137
static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3756
void drcbe_x86::op_store(x86code *&dst, const instruction &inst)
4139
drcuml_parameter srcp, basep, indp, scalesizep;
4140
int srcreg, scale, size;
4142
/* validate instruction */
4143
assert(inst->size == 4 || inst->size == 8);
3758
// validate instruction
3759
assert(inst.size() == 4 || inst.size() == 8);
4144
3760
assert_no_condition(inst);
4145
3761
assert_no_flags(inst);
4147
/* normalize parameters */
4148
param_normalize_4(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI, &scalesizep, PTYPE_I);
4149
scale = 1 << (scalesizep.value / 16);
4150
size = scalesizep.value % 16;
3763
// normalize parameters
3764
be_parameter basep(*this, inst.param(0), PTYPE_M);
3765
be_parameter indp(*this, inst.param(1), PTYPE_MRI);
3766
be_parameter srcp(*this, inst.param(2), PTYPE_MRI);
3767
const parameter &scalesizep = inst.param(3);
3768
int scale = 1 << (scalesizep.scale());
3769
int size = scalesizep.size();
4152
/* pick a source register for the general case */
4153
srcreg = param_select_register(REG_EAX, &srcp, NULL);
4154
if (size == DRCUML_SIZE_BYTE && (srcreg & 4))
3771
// pick a source register for the general case
3772
int srcreg = srcp.select_register(REG_EAX);
3773
if (size == SIZE_BYTE && (srcreg & 4))
4155
3774
srcreg = REG_EAX;
4157
/* degenerate case: constant index */
4158
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
3776
// degenerate case: constant index
3777
if (indp.is_immediate())
4160
/* immediate source */
4161
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
3780
if (srcp.is_immediate())
4163
if (size == DRCUML_SIZE_BYTE)
4164
emit_mov_m8_imm(&dst, MABS(basep.value + scale*indp.value), srcp.value); // mov [basep + scale*indp],srcp
4165
else if (size == DRCUML_SIZE_WORD)
4166
emit_mov_m16_imm(&dst, MABS(basep.value + scale*indp.value), srcp.value); // mov [basep + scale*indp],srcp
4167
else if (size == DRCUML_SIZE_DWORD)
4168
emit_mov_m32_imm(&dst, MABS(basep.value + scale*indp.value), srcp.value); // mov [basep + scale*indp],srcp
4169
else if (size == DRCUML_SIZE_QWORD)
3782
if (size == SIZE_BYTE)
3783
emit_mov_m8_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
3784
else if (size == SIZE_WORD)
3785
emit_mov_m16_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
3786
else if (size == SIZE_DWORD)
3787
emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
3788
else if (size == SIZE_QWORD)
4171
emit_mov_m32_imm(&dst, MABS(basep.value + scale*indp.value), srcp.value); // mov [basep + scale*indp],srcp
4172
emit_mov_m32_imm(&dst, MABS(basep.value + scale*indp.value + 4), srcp.value >> 32);
3790
emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
3791
emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate() + 4)), srcp.immediate() >> 32);
4173
3792
// mov [basep + scale*indp + 4],srcp >> 32
4177
/* variable source */
4180
if (size != DRCUML_SIZE_QWORD)
4181
emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
3799
if (size != SIZE_QWORD)
3800
emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
4183
emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
4184
if (size == DRCUML_SIZE_BYTE)
4185
emit_mov_m8_r8(&dst, MABS(basep.value + scale*indp.value), srcreg); // mov [basep + scale*indp],srcreg
4186
else if (size == DRCUML_SIZE_WORD)
4187
emit_mov_m16_r16(&dst, MABS(basep.value + scale*indp.value), srcreg); // mov [basep + scale*indp],srcreg
4188
else if (size == DRCUML_SIZE_DWORD)
4189
emit_mov_m32_r32(&dst, MABS(basep.value + scale*indp.value), srcreg); // mov [basep + scale*indp],srcreg
4190
else if (size == DRCUML_SIZE_QWORD)
3802
emit_mov_r64_p64(dst, srcreg, REG_EDX, srcp); // mov edx:srcreg,srcp
3803
if (size == SIZE_BYTE)
3804
emit_mov_m8_r8(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
3805
else if (size == SIZE_WORD)
3806
emit_mov_m16_r16(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
3807
else if (size == SIZE_DWORD)
3808
emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
3809
else if (size == SIZE_QWORD)
4192
emit_mov_m32_r32(&dst, MABS(basep.value + scale*indp.value), srcreg); // mov [basep + scale*indp],srcreg
4193
emit_mov_m32_r32(&dst, MABS(basep.value + scale*indp.value + 4), REG_EDX); // mov [basep + scale*indp + 4],edx
3811
emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
3812
emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate() + 4)), REG_EDX); // mov [basep + scale*indp + 4],edx
4198
/* normal case: variable index */
3817
// normal case: variable index
4201
int indreg = param_select_register(REG_ECX, &indp, NULL);
4202
emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
3820
int indreg = indp.select_register(REG_ECX);
3821
emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
4204
/* immediate source */
4205
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
3824
if (srcp.is_immediate())
4207
if (size == DRCUML_SIZE_BYTE)
4208
emit_mov_m8_imm(&dst, MISD(indreg, scale, basep.value), srcp.value); // mov [basep + 1*ecx],srcp
4209
else if (size == DRCUML_SIZE_WORD)
4210
emit_mov_m16_imm(&dst, MISD(indreg, scale, basep.value), srcp.value); // mov [basep + 2*ecx],srcp
4211
else if (size == DRCUML_SIZE_DWORD)
4212
emit_mov_m32_imm(&dst, MISD(indreg, scale, basep.value), srcp.value); // mov [basep + 4*ecx],srcp
4213
else if (size == DRCUML_SIZE_QWORD)
3826
if (size == SIZE_BYTE)
3827
emit_mov_m8_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 1*ecx],srcp
3828
else if (size == SIZE_WORD)
3829
emit_mov_m16_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 2*ecx],srcp
3830
else if (size == SIZE_DWORD)
3831
emit_mov_m32_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 4*ecx],srcp
3832
else if (size == SIZE_QWORD)
4215
emit_mov_m32_imm(&dst, MISD(indreg, scale, basep.value), srcp.value); // mov [basep + 8*ecx],srcp
4216
emit_mov_m32_imm(&dst, MISD(indreg, scale, basep.value + 4), srcp.value >> 32);
3834
emit_mov_m32_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 8*ecx],srcp
3835
emit_mov_m32_imm(dst, MABSI(basep.memory(4), indreg, scale), srcp.immediate() >> 32);
4217
3836
// mov [basep + 8*ecx + 4],srcp >> 32
4221
/* variable source */
4224
if (size != DRCUML_SIZE_QWORD)
4225
emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
3843
if (size != SIZE_QWORD)
3844
emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
4227
emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
4228
if (size == DRCUML_SIZE_BYTE)
4229
emit_mov_m8_r8(&dst, MISD(indreg, scale, basep.value), srcreg); // mov [basep + 1*ecx],srcreg
4230
else if (size == DRCUML_SIZE_WORD)
4231
emit_mov_m16_r16(&dst, MISD(indreg, scale, basep.value), srcreg); // mov [basep + 2*ecx],srcreg
4232
else if (size == DRCUML_SIZE_DWORD)
4233
emit_mov_m32_r32(&dst, MISD(indreg, scale, basep.value), srcreg); // mov [basep + 4*ecx],srcreg
4234
else if (size == DRCUML_SIZE_QWORD)
3846
emit_mov_r64_p64(dst, srcreg, REG_EDX, srcp); // mov edx:srcreg,srcp
3847
if (size == SIZE_BYTE)
3848
emit_mov_m8_r8(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 1*ecx],srcreg
3849
else if (size == SIZE_WORD)
3850
emit_mov_m16_r16(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 2*ecx],srcreg
3851
else if (size == SIZE_DWORD)
3852
emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 4*ecx],srcreg
3853
else if (size == SIZE_QWORD)
4236
emit_mov_m32_r32(&dst, MISD(indreg, scale, basep.value), srcreg); // mov [basep + 8*ecx],srcreg
4237
emit_mov_m32_r32(&dst, MISD(indreg, scale, basep.value + 4), REG_EDX); // mov [basep + 8*ecx],edx
3855
emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 8*ecx],srcreg
3856
emit_mov_m32_r32(dst, MABSI(basep.memory(4), indreg, scale), REG_EDX); // mov [basep + 8*ecx],edx
4245
/*-------------------------------------------------
4246
op_read - process a READ opcode
4247
-------------------------------------------------*/
3863
//-------------------------------------------------
3864
// op_read - process a READ opcode
3865
//-------------------------------------------------
4249
static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3867
void drcbe_x86::op_read(x86code *&dst, const instruction &inst)
4251
drcuml_parameter dstp, addrp, spacesizep;
4254
/* validate instruction */
4255
assert(inst->size == 4 || inst->size == 8);
3869
// validate instruction
3870
assert(inst.size() == 4 || inst.size() == 8);
4256
3871
assert_no_condition(inst);
4257
3872
assert_no_flags(inst);
4259
/* normalize parameters */
4260
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &spacesizep, PTYPE_I);
4262
/* pick a target register for the general case */
4263
dstreg = param_select_register(REG_EAX, &dstp, NULL);
4265
/* set up a call to the read byte handler */
4266
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
4267
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space
4268
if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
3874
// normalize parameters
3875
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3876
be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
3877
const parameter &spacesizep = inst.param(2);
3878
assert(spacesizep.is_size_space());
3880
// pick a target register for the general case
3881
int dstreg = dstp.select_register(REG_EAX);
3883
// set up a call to the read byte handler
3884
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
3885
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
3886
if (spacesizep.size() == SIZE_BYTE)
4270
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_byte);
3888
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_byte);
4271
3889
// call read_byte
4272
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
3890
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
4274
else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
3892
else if (spacesizep.size() == SIZE_WORD)
4276
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_word);
3894
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_word);
4277
3895
// call read_word
4278
emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
3896
emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
4280
else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
3898
else if (spacesizep.size() == SIZE_DWORD)
4282
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_dword);
3900
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_dword);
4283
3901
// call read_dword
4284
emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
3902
emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
4286
else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
3904
else if (spacesizep.size() == SIZE_QWORD)
4288
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_qword);
3906
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_qword);
4289
3907
// call read_qword
4290
emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
3908
emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
4293
/* store low 32 bits */
4294
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
3911
// store low 32 bits
3912
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4296
/* 64-bit form stores upper 32 bits */
4297
if (inst->size == 8)
3914
// 64-bit form stores upper 32 bits
3915
if (inst.size() == 8)
4299
/* 1, 2, or 4-byte case */
4300
if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
3917
// 1, 2, or 4-byte case
3918
if (spacesizep.size() != SIZE_QWORD)
4302
if (dstp.type == DRCUML_PTYPE_MEMORY)
4303
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
4304
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4305
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
3920
if (dstp.is_memory())
3921
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
3922
else if (dstp.is_int_register())
3923
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
4311
if (dstp.type == DRCUML_PTYPE_MEMORY)
4312
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
4313
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4314
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
3929
if (dstp.is_memory())
3930
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
3931
else if (dstp.is_int_register())
3932
emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
4321
/*-------------------------------------------------
4322
op_readm - process a READM opcode
4323
-------------------------------------------------*/
3938
//-------------------------------------------------
3939
// op_readm - process a READM opcode
3940
//-------------------------------------------------
4325
static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3942
void drcbe_x86::op_readm(x86code *&dst, const instruction &inst)
4327
drcuml_parameter dstp, addrp, maskp, spacesizep;
4330
/* validate instruction */
4331
assert(inst->size == 4 || inst->size == 8);
3944
// validate instruction
3945
assert(inst.size() == 4 || inst.size() == 8);
4332
3946
assert_no_condition(inst);
4333
3947
assert_no_flags(inst);
4335
/* normalize parameters */
4336
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
4338
/* pick a target register for the general case */
4339
dstreg = param_select_register(REG_EAX, &dstp, NULL);
4341
/* set up a call to the read byte handler */
4342
if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
4343
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 8), &maskp); // mov [esp+8],maskp
3949
// normalize parameters
3950
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
3951
be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
3952
be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
3953
const parameter &spacesizep = inst.param(3);
3954
assert(spacesizep.is_size_space());
3956
// pick a target register for the general case
3957
int dstreg = dstp.select_register(REG_EAX);
3959
// set up a call to the read byte handler
3960
if (spacesizep.size() != SIZE_QWORD)
3961
emit_mov_m32_p32(dst, MBD(REG_ESP, 8), maskp); // mov [esp+8],maskp
4345
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &maskp); // mov [esp+8],maskp
4346
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
4347
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space
4348
if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
3963
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), maskp); // mov [esp+8],maskp
3964
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
3965
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
3966
if (spacesizep.size() == SIZE_WORD)
4350
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_word_masked);
3968
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_word_masked);
4351
3969
// call read_word_masked
4352
emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
3970
emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
4354
else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
3972
else if (spacesizep.size() == SIZE_DWORD)
4356
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_dword_masked);
3974
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_dword_masked);
4357
3975
// call read_dword_masked
4358
emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
3976
emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
4360
else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
3978
else if (spacesizep.size() == SIZE_QWORD)
4362
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].read_qword_masked);
3980
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_qword_masked);
4363
3981
// call read_qword_masked
4364
emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
3982
emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
4367
/* store low 32 bits */
4368
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
3985
// store low 32 bits
3986
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4370
/* 64-bit form stores upper 32 bits */
4371
if (inst->size == 8)
3988
// 64-bit form stores upper 32 bits
3989
if (inst.size() == 8)
4373
/* 1, 2, or 4-byte case */
4374
if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
3991
// 1, 2, or 4-byte case
3992
if (spacesizep.size() != SIZE_QWORD)
4376
if (dstp.type == DRCUML_PTYPE_MEMORY)
4377
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
4378
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4379
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
3994
if (dstp.is_memory())
3995
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
3996
else if (dstp.is_int_register())
3997
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
4385
if (dstp.type == DRCUML_PTYPE_MEMORY)
4386
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
4387
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4388
emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
4003
if (dstp.is_memory())
4004
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
4005
else if (dstp.is_int_register())
4006
emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
4395
/*-------------------------------------------------
4396
op_write - process a WRITE opcode
4397
-------------------------------------------------*/
4012
//-------------------------------------------------
4013
// op_write - process a WRITE opcode
4014
//-------------------------------------------------
4399
static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4016
void drcbe_x86::op_write(x86code *&dst, const instruction &inst)
4401
drcuml_parameter addrp, srcp, spacesizep;
4403
/* validate instruction */
4404
assert(inst->size == 4 || inst->size == 8);
4018
// validate instruction
4019
assert(inst.size() == 4 || inst.size() == 8);
4405
4020
assert_no_condition(inst);
4406
4021
assert_no_flags(inst);
4408
/* normalize parameters */
4409
param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &spacesizep, PTYPE_I);
4023
// normalize parameters
4024
be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
4025
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4026
const parameter &spacesizep = inst.param(2);
4027
assert(spacesizep.is_size_space());
4411
/* set up a call to the write byte handler */
4412
if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
4413
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
4029
// set up a call to the write byte handler
4030
if (spacesizep.size() != SIZE_QWORD)
4031
emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
4415
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
4416
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
4417
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space
4418
if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
4419
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_byte);
4033
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
4034
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
4035
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
4036
if (spacesizep.size() == SIZE_BYTE)
4037
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_byte);
4420
4038
// call write_byte
4421
else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
4422
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_word);
4039
else if (spacesizep.size() == SIZE_WORD)
4040
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_word);
4423
4041
// call write_word
4424
else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
4425
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_dword);
4042
else if (spacesizep.size() == SIZE_DWORD)
4043
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_dword);
4426
4044
// call write_dword
4427
else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
4428
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_qword);
4045
else if (spacesizep.size() == SIZE_QWORD)
4046
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_qword);
4429
4047
// call write_qword
4434
/*-------------------------------------------------
4435
op_writem - process a WRITEM opcode
4436
-------------------------------------------------*/
4051
//-------------------------------------------------
4052
// op_writem - process a WRITEM opcode
4053
//-------------------------------------------------
4438
static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4055
void drcbe_x86::op_writem(x86code *&dst, const instruction &inst)
4440
drcuml_parameter addrp, srcp, maskp, spacesizep;
4442
/* validate instruction */
4443
assert(inst->size == 4 || inst->size == 8);
4057
// validate instruction
4058
assert(inst.size() == 4 || inst.size() == 8);
4444
4059
assert_no_condition(inst);
4445
4060
assert_no_flags(inst);
4447
/* normalize parameters */
4448
param_normalize_4(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
4062
// normalize parameters
4063
be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
4064
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4065
be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
4066
const parameter &spacesizep = inst.param(3);
4067
assert(spacesizep.is_size_space());
4450
/* set up a call to the write byte handler */
4451
if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
4069
// set up a call to the write byte handler
4070
if (spacesizep.size() != SIZE_QWORD)
4453
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 12), &maskp); // mov [esp+12],maskp
4454
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
4072
emit_mov_m32_p32(dst, MBD(REG_ESP, 12), maskp); // mov [esp+12],maskp
4073
emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
4458
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 16), &maskp); // mov [esp+16],maskp
4459
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
4077
emit_mov_m64_p64(dst, MBD(REG_ESP, 16), maskp); // mov [esp+16],maskp
4078
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
4461
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
4462
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space
4463
if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
4464
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_word_masked);
4080
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
4081
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
4082
if (spacesizep.size() == SIZE_WORD)
4083
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_word_masked);
4465
4084
// call write_word_masked
4466
else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
4467
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_dword_masked);
4085
else if (spacesizep.size() == SIZE_DWORD)
4086
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_dword_masked);
4468
4087
// call write_dword_masked
4469
else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
4470
emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_qword_masked);
4088
else if (spacesizep.size() == SIZE_QWORD)
4089
emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_qword_masked);
4471
4090
// call write_qword_masked
4476
/*-------------------------------------------------
4477
op_carry - process a CARRY opcode
4478
-------------------------------------------------*/
4094
//-------------------------------------------------
4095
// op_carry - process a CARRY opcode
4096
//-------------------------------------------------
4480
static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4098
void drcbe_x86::op_carry(x86code *&dst, const instruction &inst)
4482
drcuml_parameter srcp, bitp;
4484
/* validate instruction */
4485
assert(inst->size == 4 || inst->size == 8);
4100
// validate instruction
4101
assert(inst.size() == 4 || inst.size() == 8);
4486
4102
assert_no_condition(inst);
4487
assert_flags(inst, DRCUML_FLAG_C);
4489
/* normalize parameters */
4490
param_normalize_2(drcbe, inst, &srcp, PTYPE_MRI, &bitp, PTYPE_MRI);
4492
/* degenerate case: source is immediate */
4493
if (srcp.type == DRCUML_PTYPE_IMMEDIATE && bitp.type == DRCUML_PTYPE_IMMEDIATE)
4495
if (srcp.value & ((UINT64)1 << bitp.value))
4502
/* load non-immediate bit numbers into a register */
4503
if (bitp.type != DRCUML_PTYPE_IMMEDIATE)
4505
emit_mov_r32_p32(drcbe, &dst, REG_ECX, &bitp);
4506
emit_and_r32_imm(&dst, REG_ECX, inst->size * 8 - 1);
4510
if (inst->size == 4)
4512
if (bitp.type == DRCUML_PTYPE_IMMEDIATE)
4514
if (srcp.type == DRCUML_PTYPE_MEMORY)
4515
emit_bt_m32_imm(&dst, MABS(srcp.value), bitp.value); // bt [srcp],bitp
4516
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
4517
emit_bt_r32_imm(&dst, srcp.value, bitp.value); // bt srcp,bitp
4521
if (srcp.type == DRCUML_PTYPE_MEMORY)
4522
emit_bt_m32_r32(&dst, MABS(srcp.value), REG_ECX); // bt [srcp],ecx
4523
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
4524
emit_bt_r32_r32(&dst, srcp.value, REG_ECX); // bt [srcp],ecx
4103
assert_flags(inst, FLAG_C);
4105
// normalize parameters
4106
be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
4107
be_parameter bitp(*this, inst.param(1), PTYPE_MRI);
4109
// degenerate case: source is immediate
4110
if (srcp.is_immediate() && bitp.is_immediate())
4112
if (srcp.immediate() & ((UINT64)1 << bitp.immediate()))
4118
// load non-immediate bit numbers into a register
4119
if (!bitp.is_immediate())
4121
emit_mov_r32_p32(dst, REG_ECX, bitp);
4122
emit_and_r32_imm(dst, REG_ECX, inst.size() * 8 - 1);
4126
if (inst.size() == 4)
4128
if (bitp.is_immediate())
4130
if (srcp.is_memory())
4131
emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
4132
else if (srcp.is_int_register())
4133
emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
4137
if (srcp.is_memory())
4138
emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
4139
else if (srcp.is_int_register())
4140
emit_bt_r32_r32(dst, srcp.ireg(), REG_ECX); // bt [srcp],ecx
4531
if (bitp.type == DRCUML_PTYPE_IMMEDIATE)
4147
if (bitp.is_immediate())
4533
if (srcp.type == DRCUML_PTYPE_MEMORY)
4534
emit_bt_m32_imm(&dst, MABS(srcp.value), bitp.value); // bt [srcp],bitp
4535
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER && bitp.value < 32)
4536
emit_bt_r32_imm(&dst, srcp.value, bitp.value); // bt srcp,bitp
4537
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER && bitp.value >= 32)
4538
emit_bt_m32_imm(&dst, MABS(drcbe->reghi[srcp.value]), bitp.value - 32); // bt [srcp.hi],bitp
4149
if (srcp.is_memory())
4150
emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
4151
else if (srcp.is_int_register() && bitp.immediate() < 32)
4152
emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
4153
else if (srcp.is_int_register() && bitp.immediate() >= 32)
4154
emit_bt_m32_imm(dst, MABS(m_reghi[srcp.ireg()]), bitp.immediate() - 32); // bt [srcp.hi],bitp
4542
if (srcp.type == DRCUML_PTYPE_MEMORY)
4543
emit_bt_m32_r32(&dst, MABS(srcp.value), REG_ECX); // bt [srcp],ecx
4544
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
4158
if (srcp.is_memory())
4159
emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
4160
else if (srcp.is_int_register())
4546
emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov [srcp.lo],srcp
4547
emit_bt_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), REG_ECX); // bt [srcp],ecx
4162
emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov [srcp.lo],srcp
4163
emit_bt_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), REG_ECX); // bt [srcp],ecx
4555
/*-------------------------------------------------
4556
op_set - process a SET opcode
4557
-------------------------------------------------*/
4170
//-------------------------------------------------
4171
// op_set - process a SET opcode
4172
//-------------------------------------------------
4559
static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4174
void drcbe_x86::op_set(x86code *&dst, const instruction &inst)
4561
drcuml_parameter dstp;
4564
/* validate instruction */
4565
assert(inst->size == 4 || inst->size == 8);
4176
// validate instruction
4177
assert(inst.size() == 4 || inst.size() == 8);
4566
4178
assert_any_condition(inst);
4567
4179
assert_no_flags(inst);
4569
/* normalize parameters */
4570
param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
4572
/* pick a target register for the general case */
4573
dstreg = param_select_register(REG_EAX, &dstp, NULL);
4576
emit_setcc_r8(&dst, X86_CONDITION(inst->condition), REG_AL); // setcc al
4577
emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
4579
/* store low 32 bits */
4580
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4582
/* 64-bit form stores upper 32 bits */
4583
if (inst->size == 8)
4181
// normalize parameters
4182
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4184
// pick a target register for the general case
4185
int dstreg = dstp.select_register(REG_EAX);
4188
emit_setcc_r8(dst, X86_CONDITION(inst.condition()), REG_AL); // setcc al
4189
emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
4191
// store low 32 bits
4192
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4194
// 64-bit form stores upper 32 bits
4195
if (inst.size() == 8)
4586
if (dstp.type == DRCUML_PTYPE_MEMORY)
4587
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
4588
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4589
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
4198
if (dstp.is_memory())
4199
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
4200
else if (dstp.is_int_register())
4201
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
4595
/*-------------------------------------------------
4596
op_mov - process a MOV opcode
4597
-------------------------------------------------*/
4206
//-------------------------------------------------
4207
// op_mov - process a MOV opcode
4208
//-------------------------------------------------
4599
static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4210
void drcbe_x86::op_mov(x86code *&dst, const instruction &inst)
4601
drcuml_parameter dstp, srcp;
4602
4212
x86code *savedst = dst;
4603
emit_link skip = { 0 };
4606
/* validate instruction */
4607
assert(inst->size == 4 || inst->size == 8);
4214
// validate instruction
4215
assert(inst.size() == 4 || inst.size() == 8);
4608
4216
assert_any_condition(inst);
4609
4217
assert_no_flags(inst);
4611
/* normalize parameters, but only if we got here directly */
4612
/* other opcodes call through here with pre-normalized parameters */
4613
if (inst->opcode == DRCUML_OP_MOV)
4614
param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
4617
dstp = inst->param[0];
4618
srcp = inst->param[1];
4621
/* pick a target register for the general case */
4622
dstreg = param_select_register(REG_EAX, &dstp, NULL);
4624
/* always start with a jmp */
4625
if (inst->condition != DRCUML_COND_ALWAYS)
4626
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condition), &skip); // jcc skip
4629
if (inst->size == 4)
4631
/* register to memory */
4632
if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_INT_REGISTER)
4633
emit_mov_m32_r32(&dst, MABS(dstp.value), srcp.value); // mov [dstp],srcp
4635
/* immediate to memory */
4636
else if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_IMMEDIATE)
4637
emit_mov_m32_imm(&dst, MABS(dstp.value), srcp.value); // mov [dstp],srcp
4639
/* conditional memory to register */
4640
else if (inst->condition != DRCUML_COND_ALWAYS && dstp.type == DRCUML_PTYPE_INT_REGISTER && srcp.type == DRCUML_PTYPE_MEMORY)
4219
// normalize parameters
4220
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4221
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4223
// pick a target register for the general case
4224
int dstreg = dstp.select_register(REG_EAX);
4226
// always start with a jmp
4227
emit_link skip = { 0 };
4228
if (inst.condition() != uml::COND_ALWAYS)
4229
emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
4232
if (inst.size() == 4)
4234
// register to memory
4235
if (dstp.is_memory() && srcp.is_int_register())
4236
emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
4238
// immediate to memory
4239
else if (dstp.is_memory() && srcp.is_immediate())
4240
emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
4242
// conditional memory to register
4243
else if (inst.condition() != uml::COND_ALWAYS && dstp.is_int_register() && srcp.is_memory())
4643
4246
skip.target = NULL;
4644
emit_cmovcc_r32_m32(&dst, X86_CONDITION(inst->condition), dstp.value, MABS(srcp.value));
4247
emit_cmovcc_r32_m32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory()));
4645
4248
// cmovcc dstp,[srcp]
4648
/* conditional register to register */
4649
else if (inst->condition != DRCUML_COND_ALWAYS && dstp.type == DRCUML_PTYPE_INT_REGISTER && srcp.type == DRCUML_PTYPE_INT_REGISTER)
4251
// conditional register to register
4252
else if (inst.condition() != uml::COND_ALWAYS && dstp.is_int_register() && srcp.is_int_register())
4652
4255
skip.target = NULL;
4653
emit_cmovcc_r32_r32(&dst, X86_CONDITION(inst->condition), dstp.value, srcp.value);
4256
emit_cmovcc_r32_r32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg());
4654
4257
// cmovcc dstp,srcp
4660
emit_mov_r32_p32_keepflags(drcbe, &dst, dstreg, &srcp); // mov dstreg,srcp
4661
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4263
emit_mov_r32_p32_keepflags(dst, dstreg, srcp); // mov dstreg,srcp
4264
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4666
else if (inst->size == 8)
4269
else if (inst.size() == 8)
4668
/* register to memory */
4669
if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_INT_REGISTER)
4671
emit_mov_r32_m32(&dst, REG_EAX, MABS(drcbe->reghi[srcp.value])); // mov eax,reghi[srcp]
4672
emit_mov_m32_r32(&dst, MABS(dstp.value), srcp.value); // mov [dstp],srcp
4673
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EAX); // mov [dstp+4],eax
4676
/* immediate to memory */
4677
else if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_IMMEDIATE)
4679
emit_mov_m32_imm(&dst, MABS(dstp.value), srcp.value); // mov [dstp],srcp
4680
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), srcp.value >> 32); // mov [dstp+4],srcp >> 32
4271
// register to memory
4272
if (dstp.is_memory() && srcp.is_int_register())
4274
emit_mov_r32_m32(dst, REG_EAX, MABS(m_reghi[srcp.ireg()])); // mov eax,reghi[srcp]
4275
emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
4276
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EAX); // mov [dstp+4],eax
4279
// immediate to memory
4280
else if (dstp.is_memory() && srcp.is_immediate())
4282
emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
4283
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), srcp.immediate() >> 32); // mov [dstp+4],srcp >> 32
4686
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &srcp); // mov edx:dstreg,srcp
4687
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
4289
emit_mov_r64_p64(dst, dstreg, REG_EDX, srcp); // mov edx:dstreg,srcp
4290
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
4691
/* resolve the jump */
4692
4295
if (skip.target != NULL)
4693
track_resolve_link(drcbe, &dst, &skip);
4698
/*-------------------------------------------------
4699
op_sext - process a SEXT opcode
4700
-------------------------------------------------*/
4702
static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4704
drcuml_parameter dstp, srcp, sizep;
4707
/* validate instruction */
4708
assert(inst->size == 4 || inst->size == 8);
4709
assert_no_condition(inst);
4710
assert_flags(inst, DRCUML_FLAG_S | DRCUML_FLAG_Z);
4712
/* normalize parameters */
4713
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
4715
/* pick a target register for the general case */
4716
dstreg = (inst->size == 8) ? REG_EAX : param_select_register(REG_EAX, &dstp, NULL);
4718
/* convert 8-bit source registers to EAX */
4719
if (sizep.value == DRCUML_SIZE_BYTE && srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
4721
emit_mov_r32_r32(&dst, REG_EAX, srcp.value); // mov eax,srcp
4722
srcp.value = REG_EAX;
4726
if (srcp.type == DRCUML_PTYPE_MEMORY)
4728
if (sizep.value == DRCUML_SIZE_BYTE)
4729
emit_movsx_r32_m8(&dst, dstreg, MABS(srcp.value)); // movsx dstreg,[srcp]
4730
else if (sizep.value == DRCUML_SIZE_WORD)
4731
emit_movsx_r32_m16(&dst, dstreg, MABS(srcp.value)); // movsx dstreg,[srcp]
4732
else if (sizep.value == DRCUML_SIZE_DWORD)
4733
emit_mov_r32_m32(&dst, dstreg, MABS(srcp.value)); // mov dstreg,[srcp]
4735
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
4737
if (sizep.value == DRCUML_SIZE_BYTE)
4738
emit_movsx_r32_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
4739
else if (sizep.value == DRCUML_SIZE_WORD)
4740
emit_movsx_r32_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
4741
else if (sizep.value == DRCUML_SIZE_DWORD && dstreg != srcp.value)
4742
emit_mov_r32_r32(&dst, dstreg, srcp.value); // mov dstreg,srcp
4744
if (inst->flags != 0)
4745
emit_test_r32_r32(&dst, dstreg, dstreg); // test dstreg,dstreg
4747
/* 32-bit form: store the low 32 bits */
4748
if (inst->size == 4)
4749
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4751
/* 64-bit form: sign extend to 64 bits and store edx:eax */
4752
else if (inst->size == 8)
4754
emit_cdq(&dst); // cdq
4755
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
4761
/*-------------------------------------------------
4762
op_roland - process an ROLAND opcode
4763
-------------------------------------------------*/
4765
static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4767
drcuml_parameter dstp, srcp, shiftp, maskp;
4770
/* validate instruction */
4771
assert(inst->size == 4 || inst->size == 8);
4772
assert_no_condition(inst);
4773
assert_flags(inst, DRCUML_FLAG_S | DRCUML_FLAG_Z);
4775
/* normalize parameters */
4776
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &shiftp, PTYPE_MRI, &maskp, PTYPE_MRI);
4778
/* pick a target register for the general case */
4779
dstreg = param_select_register2(REG_EAX, &dstp, &shiftp, &maskp);
4782
if (inst->size == 4)
4784
emit_mov_r32_p32(drcbe, &dst, dstreg, &srcp); // mov dstreg,srcp
4785
emit_rol_r32_p32(drcbe, &dst, dstreg, &shiftp, inst); // rol dstreg,shiftp
4786
emit_and_r32_p32(drcbe, &dst, dstreg, &maskp, inst); // and dstreg,maskp
4787
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4791
else if (inst->size == 8)
4793
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &srcp); // mov edx:dstreg,srcp
4794
emit_rol_r64_p64(drcbe, &dst, dstreg, REG_EDX, &shiftp, inst); // rol edx:dstreg,shiftp
4795
emit_and_r64_p64(drcbe, &dst, dstreg, REG_EDX, &maskp, inst); // and edx:dstreg,maskp
4796
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
4802
/*-------------------------------------------------
4803
op_rolins - process an ROLINS opcode
4804
-------------------------------------------------*/
4806
static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4808
drcuml_parameter dstp, srcp, shiftp, maskp;
4811
/* validate instruction */
4812
assert(inst->size == 4 || inst->size == 8);
4813
assert_no_condition(inst);
4814
assert_flags(inst, DRCUML_FLAG_S | DRCUML_FLAG_Z);
4816
/* normalize parameters */
4817
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &shiftp, PTYPE_MRI, &maskp, PTYPE_MRI);
4819
/* pick a target register for the general case */
4820
dstreg = param_select_register2(REG_ECX, &dstp, &shiftp, &maskp);
4823
if (inst->size == 4)
4825
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &srcp); // mov eax,srcp
4826
emit_rol_r32_p32(drcbe, &dst, REG_EAX, &shiftp, inst); // rol eax,shiftp
4827
emit_mov_r32_p32(drcbe, &dst, dstreg, &dstp); // mov dstreg,dstp
4828
if (maskp.type == DRCUML_PTYPE_IMMEDIATE)
4296
track_resolve_link(dst, skip);
4300
//-------------------------------------------------
4301
// op_sext - process a SEXT opcode
4302
//-------------------------------------------------
4304
void drcbe_x86::op_sext(x86code *&dst, const instruction &inst)
4306
// validate instruction
4307
assert(inst.size() == 4 || inst.size() == 8);
4308
assert_no_condition(inst);
4309
assert_flags(inst, FLAG_S | FLAG_Z);
4311
// normalize parameters
4312
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4313
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4314
const parameter &sizep = inst.param(2);
4315
assert(sizep.is_size());
4317
// pick a target register for the general case
4318
int dstreg = (inst.size() == 8) ? REG_EAX : dstp.select_register(REG_EAX);
4320
// convert 8-bit source registers to EAX
4321
if (sizep.size() == SIZE_BYTE && srcp.is_int_register() && (srcp.ireg() & 4))
4323
emit_mov_r32_r32(dst, REG_EAX, srcp.ireg()); // mov eax,srcp
4324
srcp = be_parameter::make_ireg(REG_EAX);
4328
if (srcp.is_memory())
4330
if (sizep.size() == SIZE_BYTE)
4331
emit_movsx_r32_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
4332
else if (sizep.size() == SIZE_WORD)
4333
emit_movsx_r32_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
4334
else if (sizep.size() == SIZE_DWORD)
4335
emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
4337
else if (srcp.is_int_register())
4339
if (sizep.size() == SIZE_BYTE)
4340
emit_movsx_r32_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
4341
else if (sizep.size() == SIZE_WORD)
4342
emit_movsx_r32_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
4343
else if (sizep.size() == SIZE_DWORD && dstreg != srcp.ireg())
4344
emit_mov_r32_r32(dst, dstreg, srcp.ireg()); // mov dstreg,srcp
4346
if (inst.flags() != 0)
4347
emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
4349
// 32-bit form: store the low 32 bits
4350
if (inst.size() == 4)
4351
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4353
// 64-bit form: sign extend to 64 bits and store edx:eax
4354
else if (inst.size() == 8)
4356
emit_cdq(dst); // cdq
4357
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
4362
//-------------------------------------------------
4363
// op_roland - process an ROLAND opcode
4364
//-------------------------------------------------
4366
void drcbe_x86::op_roland(x86code *&dst, const instruction &inst)
4368
// validate instruction
4369
assert(inst.size() == 4 || inst.size() == 8);
4370
assert_no_condition(inst);
4371
assert_flags(inst, FLAG_S | FLAG_Z);
4373
// normalize parameters
4374
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4375
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4376
be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
4377
be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
4379
// pick a target register for the general case
4380
int dstreg = dstp.select_register(REG_EAX, shiftp, maskp);
4383
if (inst.size() == 4)
4385
emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp
4386
emit_rol_r32_p32(dst, dstreg, shiftp, inst); // rol dstreg,shiftp
4387
emit_and_r32_p32(dst, dstreg, maskp, inst); // and dstreg,maskp
4388
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4392
else if (inst.size() == 8)
4394
emit_mov_r64_p64(dst, dstreg, REG_EDX, srcp); // mov edx:dstreg,srcp
4395
emit_rol_r64_p64(dst, dstreg, REG_EDX, shiftp, inst); // rol edx:dstreg,shiftp
4396
emit_and_r64_p64(dst, dstreg, REG_EDX, maskp, inst); // and edx:dstreg,maskp
4397
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
4402
//-------------------------------------------------
4403
// op_rolins - process an ROLINS opcode
4404
//-------------------------------------------------
4406
void drcbe_x86::op_rolins(x86code *&dst, const instruction &inst)
4408
// validate instruction
4409
assert(inst.size() == 4 || inst.size() == 8);
4410
assert_no_condition(inst);
4411
assert_flags(inst, FLAG_S | FLAG_Z);
4413
// normalize parameters
4414
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4415
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
4416
be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
4417
be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
4419
// pick a target register for the general case
4420
int dstreg = dstp.select_register(REG_ECX, shiftp, maskp);
4423
if (inst.size() == 4)
4425
emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
4426
emit_rol_r32_p32(dst, REG_EAX, shiftp, inst); // rol eax,shiftp
4427
emit_mov_r32_p32(dst, dstreg, dstp); // mov dstreg,dstp
4428
if (maskp.is_immediate())
4830
emit_and_r32_imm(&dst, REG_EAX, maskp.value); // and eax,maskp
4831
emit_and_r32_imm(&dst, dstreg, ~maskp.value); // and dstreg,~maskp
4430
emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp
4431
emit_and_r32_imm(dst, dstreg, ~maskp.immediate()); // and dstreg,~maskp
4835
emit_mov_r32_p32(drcbe, &dst, REG_EDX, &maskp); // mov edx,maskp
4836
emit_and_r32_r32(&dst, REG_EAX, REG_EDX); // and eax,edx
4837
emit_not_r32(&dst, REG_EDX); // not edx
4838
emit_and_r32_r32(&dst, dstreg, REG_EDX); // and dstreg,edx
4435
emit_mov_r32_p32(dst, REG_EDX, maskp); // mov edx,maskp
4436
emit_and_r32_r32(dst, REG_EAX, REG_EDX); // and eax,edx
4437
emit_not_r32(dst, REG_EDX); // not edx
4438
emit_and_r32_r32(dst, dstreg, REG_EDX); // and dstreg,edx
4840
emit_or_r32_r32(&dst, dstreg, REG_EAX); // or dstreg,eax
4841
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4440
emit_or_r32_r32(dst, dstreg, REG_EAX); // or dstreg,eax
4441
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4845
else if (inst->size == 8)
4445
else if (inst.size() == 8)
4847
emit_mov_r64_p64(drcbe, &dst, REG_EAX, REG_EDX, &srcp); // mov edx:eax,srcp
4848
emit_rol_r64_p64(drcbe, &dst, REG_EAX, REG_EDX, &shiftp, inst); // rol edx:eax,shiftp
4849
if (maskp.type == DRCUML_PTYPE_IMMEDIATE)
4447
emit_mov_r64_p64(dst, REG_EAX, REG_EDX, srcp); // mov edx:eax,srcp
4448
emit_rol_r64_p64(dst, REG_EAX, REG_EDX, shiftp, inst); // rol edx:eax,shiftp
4449
if (maskp.is_immediate())
4851
emit_and_r32_imm(&dst, REG_EAX, maskp.value); // and eax,maskp
4852
emit_and_r32_imm(&dst, REG_EDX, maskp.value >> 32); // and edx,maskp >> 32
4853
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4451
emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp
4452
emit_and_r32_imm(dst, REG_EDX, maskp.immediate() >> 32); // and edx,maskp >> 32
4453
if (dstp.is_int_register())
4855
emit_and_r32_imm(&dst, dstp.value, ~maskp.value); // and dstp.lo,~maskp
4856
emit_and_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), ~maskp.value >> 32);// and dstp.hi,~maskp >> 32
4857
emit_or_r32_r32(&dst, dstp.value, REG_EAX); // or dstp.lo,eax
4858
emit_or_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // or dstp.hi,edx
4455
emit_and_r32_imm(dst, dstp.ireg(), ~maskp.immediate()); // and dstp.lo,~maskp
4456
emit_and_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), ~maskp.immediate() >> 32);// and dstp.hi,~maskp >> 32
4457
emit_or_r32_r32(dst, dstp.ireg(), REG_EAX); // or dstp.lo,eax
4458
emit_or_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // or dstp.hi,edx
4862
emit_and_m32_imm(&dst, MABS(dstp.value), ~maskp.value); // and dstp.lo,~maskp
4863
emit_and_m32_imm(&dst, MABS(dstp.value + 4), ~maskp.value >> 32); // and dstp.hi,~maskp >> 32
4864
emit_or_m32_r32(&dst, MABS(dstp.value), REG_EAX); // or dstp.lo,eax
4865
emit_or_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // or dstp.hi,edx
4462
emit_and_m32_imm(dst, MABS(dstp.memory()), ~maskp.immediate()); // and dstp.lo,~maskp
4463
emit_and_m32_imm(dst, MABS(dstp.memory(4)), ~maskp.immediate() >> 32); // and dstp.hi,~maskp >> 32
4464
emit_or_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // or dstp.lo,eax
4465
emit_or_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // or dstp.hi,edx
4870
4470
int tempreg = REG_EBX;
4871
emit_mov_m32_r32(&dst, MBD(REG_ESP, -8), tempreg); // mov [esp-8],ebx
4872
emit_mov_r64_p64(drcbe, &dst, tempreg, REG_ECX, &maskp); // mov ecx:ebx,maskp
4873
emit_and_r32_r32(&dst, REG_EAX, tempreg); // and eax,ebx
4874
emit_and_r32_r32(&dst, REG_EDX, REG_ECX); // and edx,ecx
4875
emit_not_r32(&dst, tempreg); // not ebx
4876
emit_not_r32(&dst, REG_ECX); // not ecx
4877
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
4471
emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg); // mov [esp-8],ebx
4472
emit_mov_r64_p64(dst, tempreg, REG_ECX, maskp); // mov ecx:ebx,maskp
4473
emit_and_r32_r32(dst, REG_EAX, tempreg); // and eax,ebx
4474
emit_and_r32_r32(dst, REG_EDX, REG_ECX); // and edx,ecx
4475
emit_not_r32(dst, tempreg); // not ebx
4476
emit_not_r32(dst, REG_ECX); // not ecx
4477
if (dstp.is_int_register())
4879
emit_and_r32_r32(&dst, dstp.value, tempreg); // and dstp.lo,ebx
4880
emit_and_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_ECX); // and dstp.hi,ecx
4881
emit_or_r32_r32(&dst, dstp.value, REG_EAX); // or dstp.lo,eax
4882
emit_or_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // or dstp.hi,edx
4479
emit_and_r32_r32(dst, dstp.ireg(), tempreg); // and dstp.lo,ebx
4480
emit_and_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_ECX); // and dstp.hi,ecx
4481
emit_or_r32_r32(dst, dstp.ireg(), REG_EAX); // or dstp.lo,eax
4482
emit_or_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // or dstp.hi,edx
4886
emit_and_m32_r32(&dst, MABS(dstp.value), tempreg); // and dstp.lo,ebx
4887
emit_and_m32_r32(&dst, MABS(dstp.value + 4), REG_ECX); // and dstp.hi,ecx
4888
emit_or_m32_r32(&dst, MABS(dstp.value), REG_EAX); // or dstp.lo,eax
4889
emit_or_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // or dstp.hi,edx
4486
emit_and_m32_r32(dst, MABS(dstp.memory()), tempreg); // and dstp.lo,ebx
4487
emit_and_m32_r32(dst, MABS(dstp.memory(4)), REG_ECX); // and dstp.hi,ecx
4488
emit_or_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // or dstp.lo,eax
4489
emit_or_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // or dstp.hi,edx
4891
emit_mov_r32_m32(&dst, tempreg, MBD(REG_ESP, -8)); // mov ebx,[esp-8]
4491
emit_mov_r32_m32(dst, tempreg, MBD(REG_ESP, -8)); // mov ebx,[esp-8]
4893
if (inst->flags == DRCUML_FLAG_Z)
4894
emit_or_r32_r32(&dst, REG_EAX, REG_EDX); // or eax,edx
4895
else if (inst->flags == DRCUML_FLAG_S)
4493
if (inst.flags() == FLAG_Z)
4494
emit_or_r32_r32(dst, REG_EAX, REG_EDX); // or eax,edx
4495
else if (inst.flags() == FLAG_S)
4896
4496
;// do nothing -- final OR will have the right result
4897
else if (inst->flags == (DRCUML_FLAG_Z | DRCUML_FLAG_S))
4899
emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
4900
emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
4901
emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
4902
emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
4909
/*-------------------------------------------------
4910
op_add - process a ADD opcode
4911
-------------------------------------------------*/
4913
static x86code *op_add(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4915
drcuml_parameter dstp, src1p, src2p;
4918
/* validate instruction */
4919
assert(inst->size == 4 || inst->size == 8);
4920
assert_no_condition(inst);
4921
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
4923
/* normalize parameters */
4924
param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
4926
/* pick a target register for the general case */
4927
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
4930
if (inst->size == 4)
4932
/* dstp == src1p in memory */
4933
if (dstp.type == DRCUML_PTYPE_MEMORY && src1p.type == DRCUML_PTYPE_MEMORY && src1p.value == dstp.value)
4934
emit_add_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // add [dstp],src2p
4936
/* reg = reg + imm */
4937
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER && src1p.type == DRCUML_PTYPE_INT_REGISTER && src2p.type == DRCUML_PTYPE_IMMEDIATE && inst->flags == 0)
4938
emit_lea_r32_m32(&dst, dstp.value, MBD(src1p.value, src2p.value)); // lea dstp,[src1p+src2p]
4940
/* reg = reg + reg */
4941
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER && src1p.type == DRCUML_PTYPE_INT_REGISTER && src2p.type == DRCUML_PTYPE_INT_REGISTER && inst->flags == 0)
4942
emit_lea_r32_m32(&dst, dstp.value, MBISD(src1p.value, src2p.value, 1, 0)); // lea dstp,[src1p+src2p]
4947
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
4948
emit_add_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // add dstreg,src2p
4949
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
4954
else if (inst->size == 8)
4956
/* dstp == src1p in memory */
4957
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
4958
emit_add_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // add [dstp],src2p
4963
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
4964
emit_add_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // add dstreg:dstp,src2p
4965
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
4972
/*-------------------------------------------------
4973
op_addc - process a ADDC opcode
4974
-------------------------------------------------*/
4976
static x86code *op_addc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4978
drcuml_parameter dstp, src1p, src2p;
4981
/* validate instruction */
4982
assert(inst->size == 4 || inst->size == 8);
4983
assert_no_condition(inst);
4984
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
4986
/* normalize parameters */
4987
param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
4989
/* pick a target register for the general case */
4990
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
4993
if (inst->size == 4)
4995
/* dstp == src1p in memory */
4996
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
4997
emit_adc_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // adc [dstp],src2p
5002
emit_mov_r32_p32_keepflags(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5003
emit_adc_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // adc dstreg,src2p
5004
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5009
else if (inst->size == 8)
5011
/* dstp == src1p in memory */
5012
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5013
emit_adc_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // adc [dstp],src2p
5018
emit_mov_r64_p64_keepflags(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5019
emit_adc_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // adc dstreg:dstp,src2p
5020
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5027
/*-------------------------------------------------
5028
op_sub - process a SUB opcode
5029
-------------------------------------------------*/
5031
static x86code *op_sub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5033
drcuml_parameter dstp, src1p, src2p;
5036
/* validate instruction */
5037
assert(inst->size == 4 || inst->size == 8);
5038
assert_no_condition(inst);
5039
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5041
/* normalize parameters */
5042
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5044
/* pick a target register for the general case */
5045
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5048
if (inst->size == 4)
5050
/* dstp == src1p in memory */
5051
if (dstp.type == DRCUML_PTYPE_MEMORY && src1p.type == DRCUML_PTYPE_MEMORY && src1p.value == dstp.value)
5052
emit_sub_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // sub [dstp],src2p
5054
/* reg = reg - imm */
5055
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER && src1p.type == DRCUML_PTYPE_INT_REGISTER && src2p.type == DRCUML_PTYPE_IMMEDIATE && inst->flags == 0)
5056
emit_lea_r32_m32(&dst, dstp.value, MBD(src1p.value, -src2p.value)); // lea dstp,[src1p-src2p]
5061
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5062
emit_sub_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // sub dstreg,src2p
5063
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5068
else if (inst->size == 8)
5070
/* dstp == src1p in memory */
5071
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5072
emit_sub_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // sub [dstp],src2p
5077
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5078
emit_sub_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // sub dstreg:dstp,src2p
5079
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5086
/*-------------------------------------------------
5087
op_subc - process a SUBC opcode
5088
-------------------------------------------------*/
5090
static x86code *op_subc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5092
drcuml_parameter dstp, src1p, src2p;
5095
/* validate instruction */
5096
assert(inst->size == 4 || inst->size == 8);
5097
assert_no_condition(inst);
5098
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5100
/* normalize parameters */
5101
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5103
/* pick a target register for the general case */
5104
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5107
if (inst->size == 4)
5109
/* dstp == src1p in memory */
5110
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5111
emit_sbb_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // sbb [dstp],src2p
5116
emit_mov_r32_p32_keepflags(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5117
emit_sbb_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // sbb dstreg,src2p
5118
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5123
else if (inst->size == 8)
5125
/* dstp == src1p in memory */
5126
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5127
emit_sbb_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // sbb [dstp],src2p
5132
emit_mov_r64_p64_keepflags(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5133
emit_sbb_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // sbb dstreg:dstp,src2p
5134
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5141
/*-------------------------------------------------
5142
op_cmp - process a CMP opcode
5143
-------------------------------------------------*/
5145
static x86code *op_cmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5147
drcuml_parameter src1p, src2p;
5150
/* validate instruction */
5151
assert(inst->size == 4 || inst->size == 8);
5152
assert_no_condition(inst);
5153
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5155
/* normalize parameters */
5156
param_normalize_2(drcbe, inst, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5158
/* pick a target register for the general case */
5159
src1reg = param_select_register(REG_EAX, &src1p, NULL);
5162
if (inst->size == 4)
5164
/* memory versus anything */
5165
if (src1p.type == DRCUML_PTYPE_MEMORY)
5166
emit_cmp_m32_p32(drcbe, &dst, MABS(src1p.value), &src2p, inst); // cmp [dstp],src2p
5171
if (src1p.type == DRCUML_PTYPE_IMMEDIATE)
5172
emit_mov_r32_imm(&dst, src1reg, src1p.value); // mov src1reg,imm
5173
emit_cmp_r32_p32(drcbe, &dst, src1reg, &src2p, inst); // cmp src1reg,src2p
4497
else if (inst.flags() == (FLAG_Z | FLAG_S))
4499
emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
4500
emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
4501
emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
4502
emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
4508
//-------------------------------------------------
4509
// op_add - process a ADD opcode
4510
//-------------------------------------------------
4512
void drcbe_x86::op_add(x86code *&dst, const instruction &inst)
4514
// validate instruction
4515
assert(inst.size() == 4 || inst.size() == 8);
4516
assert_no_condition(inst);
4517
assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
4519
// normalize parameters
4520
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4521
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
4522
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
4523
normalize_commutative(src1p, src2p);
4525
// pick a target register for the general case
4526
int dstreg = dstp.select_register(REG_EAX, src2p);
4529
if (inst.size() == 4)
4531
// dstp == src1p in memory
4532
if (dstp.is_memory() && dstp == src1p)
4533
emit_add_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
4536
else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
4537
emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p]
4540
else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0)
4541
emit_lea_r32_m32(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0)); // lea dstp,[src1p+src2p]
4546
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
4547
emit_add_r32_p32(dst, dstreg, src2p, inst); // add dstreg,src2p
4548
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4553
else if (inst.size() == 8)
4555
// dstp == src1p in memory
4556
if (dstp.is_memory() && dstp == src1p)
4557
emit_add_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
4562
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
4563
emit_add_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // add dstreg:dstp,src2p
4564
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
4570
//-------------------------------------------------
4571
// op_addc - process a ADDC opcode
4572
//-------------------------------------------------
4574
void drcbe_x86::op_addc(x86code *&dst, const instruction &inst)
4576
// validate instruction
4577
assert(inst.size() == 4 || inst.size() == 8);
4578
assert_no_condition(inst);
4579
assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
4581
// normalize parameters
4582
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4583
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
4584
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
4585
normalize_commutative(src1p, src2p);
4587
// pick a target register for the general case
4588
int dstreg = dstp.select_register(REG_EAX, src2p);
4591
if (inst.size() == 4)
4593
// dstp == src1p in memory
4594
if (dstp.is_memory() && dstp == src1p)
4595
emit_adc_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
4600
emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
4601
emit_adc_r32_p32(dst, dstreg, src2p, inst); // adc dstreg,src2p
4602
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4607
else if (inst.size() == 8)
4609
// dstp == src1p in memory
4610
if (dstp.is_memory() && dstp == src1p)
4611
emit_adc_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
4616
emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
4617
emit_adc_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // adc dstreg:dstp,src2p
4618
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
4624
//-------------------------------------------------
4625
// op_sub - process a SUB opcode
4626
//-------------------------------------------------
4628
void drcbe_x86::op_sub(x86code *&dst, const instruction &inst)
4630
// validate instruction
4631
assert(inst.size() == 4 || inst.size() == 8);
4632
assert_no_condition(inst);
4633
assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
4635
// normalize parameters
4636
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4637
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
4638
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
4640
// pick a target register for the general case
4641
int dstreg = dstp.select_register(REG_EAX, src2p);
4644
if (inst.size() == 4)
4646
// dstp == src1p in memory
4647
if (dstp.is_memory() && dstp == src1p)
4648
emit_sub_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
4651
else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
4652
emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p]
4657
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
4658
emit_sub_r32_p32(dst, dstreg, src2p, inst); // sub dstreg,src2p
4659
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4664
else if (inst.size() == 8)
4666
// dstp == src1p in memory
4667
if (dstp.is_memory() && dstp == src1p)
4668
emit_sub_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
4673
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
4674
emit_sub_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sub dstreg:dstp,src2p
4675
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
4681
//-------------------------------------------------
4682
// op_subc - process a SUBC opcode
4683
//-------------------------------------------------
4685
void drcbe_x86::op_subc(x86code *&dst, const instruction &inst)
4687
// validate instruction
4688
assert(inst.size() == 4 || inst.size() == 8);
4689
assert_no_condition(inst);
4690
assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
4692
// normalize parameters
4693
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4694
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
4695
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
4697
// pick a target register for the general case
4698
int dstreg = dstp.select_register(REG_EAX, src2p);
4701
if (inst.size() == 4)
4703
// dstp == src1p in memory
4704
if (dstp.is_memory() && dstp == src1p)
4705
emit_sbb_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
4710
emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
4711
emit_sbb_r32_p32(dst, dstreg, src2p, inst); // sbb dstreg,src2p
4712
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
4717
else if (inst.size() == 8)
4719
// dstp == src1p in memory
4720
if (dstp.is_memory() && dstp == src1p)
4721
emit_sbb_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
4726
emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
4727
emit_sbb_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sbb dstreg:dstp,src2p
4728
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
4734
//-------------------------------------------------
4735
// op_cmp - process a CMP opcode
4736
//-------------------------------------------------
4738
void drcbe_x86::op_cmp(x86code *&dst, const instruction &inst)
4740
// validate instruction
4741
assert(inst.size() == 4 || inst.size() == 8);
4742
assert_no_condition(inst);
4743
assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
4745
// normalize parameters
4746
be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
4747
be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
4749
// pick a target register for the general case
4750
int src1reg = src1p.select_register(REG_EAX);
4753
if (inst.size() == 4)
4755
// memory versus anything
4756
if (src1p.is_memory())
4757
emit_cmp_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p
4762
if (src1p.is_immediate())
4763
emit_mov_r32_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm
4764
emit_cmp_r32_p32(dst, src1reg, src2p, inst); // cmp src1reg,src2p
5181
emit_mov_r64_p64(drcbe, &dst, REG_EAX, REG_EDX, &src1p); // mov eax:dstp,[src1p]
5182
emit_cmp_r64_p64(drcbe, &dst, REG_EAX, REG_EDX, &src2p, inst); // cmp eax:dstp,src2p
4772
emit_mov_r64_p64(dst, REG_EAX, REG_EDX, src1p); // mov eax:dstp,[src1p]
4773
emit_cmp_r64_p64(dst, REG_EAX, REG_EDX, src2p, inst); // cmp eax:dstp,src2p
5188
/*-------------------------------------------------
5189
op_mulu - process a MULU opcode
5190
-------------------------------------------------*/
4778
//-------------------------------------------------
4779
// op_mulu - process a MULU opcode
4780
//-------------------------------------------------
5192
static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4782
void drcbe_x86::op_mulu(x86code *&dst, const instruction &inst)
5194
UINT8 zsflags = inst->flags & (DRCUML_FLAG_Z | DRCUML_FLAG_S);
5195
UINT8 vflag = inst->flags & DRCUML_FLAG_V;
5196
drcuml_parameter dstp, edstp, src1p, src2p;
4784
UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
4785
UINT8 vflag = inst.flags() & FLAG_V;
5199
/* validate instruction */
5200
assert(inst->size == 4 || inst->size == 8);
4787
// validate instruction
4788
assert(inst.size() == 4 || inst.size() == 8);
5201
4789
assert_no_condition(inst);
5202
assert_flags(inst, DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5204
/* normalize parameters */
5205
param_normalize_4_commutative(drcbe, inst, &dstp, PTYPE_MR, &edstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5206
compute_hi = (dstp.type != edstp.type || dstp.value != edstp.value);
5209
if (inst->size == 4)
4790
assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
4792
// normalize parameters
4793
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4794
be_parameter edstp(*this, inst.param(1), PTYPE_MR);
4795
be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
4796
be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
4797
normalize_commutative(src1p, src2p);
4798
bool compute_hi = (dstp != edstp);
4801
if (inst.size() == 4)
5212
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &src1p); // mov eax,src1p
5213
if (src2p.type == DRCUML_PTYPE_MEMORY)
5214
emit_mul_m32(&dst, MABS(src2p.value)); // mul [src2p]
5215
else if (src2p.type == DRCUML_PTYPE_INT_REGISTER)
5216
emit_mul_r32(&dst, src2p.value); // mul src2p
5217
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE)
4804
emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
4805
if (src2p.is_memory())
4806
emit_mul_m32(dst, MABS(src2p.memory())); // mul [src2p]
4807
else if (src2p.is_int_register())
4808
emit_mul_r32(dst, src2p.ireg()); // mul src2p
4809
else if (src2p.is_immediate())
5219
emit_mov_r32_imm(&dst, REG_EDX, src2p.value); // mov edx,src2p
5220
emit_mul_r32(&dst, REG_EDX); // mul edx
4811
emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
4812
emit_mul_r32(dst, REG_EDX); // mul edx
5222
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
4814
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5223
4815
if (compute_hi)
5224
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
4816
emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
5227
if (inst->flags != 0)
4819
if (inst.flags() != 0)
5229
4821
if (zsflags != 0)
5232
emit_pushf(&dst); // pushf
4824
emit_pushf(dst); // pushf
5233
4825
if (compute_hi)
5235
if (zsflags == DRCUML_FLAG_Z)
5236
emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
5237
else if (zsflags == DRCUML_FLAG_S)
5238
emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
4827
if (zsflags == FLAG_Z)
4828
emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
4829
else if (zsflags == FLAG_S)
4830
emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
5241
emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
5242
emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
5243
emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
5244
emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
4833
emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
4834
emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
4835
emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
4836
emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
5248
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
4840
emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
5250
/* we rely on the fact that OF is cleared by all logical operations above */
4842
// we rely on the fact that OF is cleared by all logical operations above
5253
emit_pushf(&dst); // pushf
5254
emit_pop_r32(&dst, REG_EAX); // pop eax
5255
emit_and_m32_imm(&dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
5256
emit_or_m32_r32(&dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
5257
emit_popf(&dst); // popf
4845
emit_pushf(dst); // pushf
4846
emit_pop_r32(dst, REG_EAX); // pop eax
4847
emit_and_m32_imm(dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
4848
emit_or_m32_r32(dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
4849
emit_popf(dst); // popf
5264
else if (inst->size == 8)
4856
else if (inst.size() == 8)
5267
emit_mov_m32_imm(&dst, MBD(REG_ESP, 24), inst->flags); // mov [esp+24],flags
5268
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 16), &src2p); // mov [esp+16],src2p
5269
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &src1p); // mov [esp+8],src1p
4859
emit_mov_m32_imm(dst, MBD(REG_ESP, 24), inst.flags()); // mov [esp+24],flags
4860
emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
4861
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
5270
4862
if (!compute_hi)
5271
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo); // mov [esp+4],&reslo
4863
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
5273
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reshi); // mov [esp+4],&reshi
5274
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)&drcbe->reslo); // mov [esp],&reslo
5275
emit_call(&dst, (x86code *)dmulu); // call dmulu
5276
if (inst->flags != 0)
5277
emit_push_m32(&dst, MISD(REG_EAX, 4, flags_unmap)); // push flags_unmap[eax*4]
5278
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
5279
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
5280
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
4865
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // mov [esp+4],&reshi
4866
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
4867
emit_call(dst, (x86code *)dmulu); // call dmulu
4868
if (inst.flags() != 0)
4869
emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
4870
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
4871
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
4872
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5281
4873
if (compute_hi)
5283
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
5284
emit_mov_r32_m32(&dst, REG_ECX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov ecx,reshi.hi
5285
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_ECX); // mov edstp,ecx:eax
4875
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
4876
emit_mov_r32_m32(dst, REG_ECX, MABS((UINT32 *)&m_reshi + 1)); // mov ecx,reshi.hi
4877
emit_mov_p64_r64(dst, edstp, REG_EAX, REG_ECX); // mov edstp,ecx:eax
5287
if (inst->flags != 0)
5288
emit_popf(&dst); // popf
4879
if (inst.flags() != 0)
4880
emit_popf(dst); // popf
5294
/*-------------------------------------------------
5295
op_muls - process a MULS opcode
5296
-------------------------------------------------*/
4885
//-------------------------------------------------
4886
// op_muls - process a MULS opcode
4887
//-------------------------------------------------
5298
static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4889
void drcbe_x86::op_muls(x86code *&dst, const instruction &inst)
5300
UINT8 zsflags = inst->flags & (DRCUML_FLAG_Z | DRCUML_FLAG_S);
5301
UINT8 vflag = inst->flags & DRCUML_FLAG_V;
5302
drcuml_parameter dstp, edstp, src1p, src2p;
4891
UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
4892
UINT8 vflag = inst.flags() & FLAG_V;
5305
/* validate instruction */
5306
assert(inst->size == 4 || inst->size == 8);
4894
// validate instruction
4895
assert(inst.size() == 4 || inst.size() == 8);
5307
4896
assert_no_condition(inst);
5308
assert_flags(inst, DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5310
/* normalize parameters */
5311
param_normalize_4_commutative(drcbe, inst, &dstp, PTYPE_MR, &edstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5312
compute_hi = (dstp.type != edstp.type || dstp.value != edstp.value);
5315
if (inst->size == 4)
4897
assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
4899
// normalize parameters
4900
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
4901
be_parameter edstp(*this, inst.param(1), PTYPE_MR);
4902
be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
4903
be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
4904
normalize_commutative(src1p, src2p);
4905
bool compute_hi = (dstp != edstp);
4908
if (inst.size() == 4)
5317
/* 32-bit destination with memory/immediate or register/immediate */
5318
if (!compute_hi && src1p.type != DRCUML_PTYPE_IMMEDIATE && src2p.type == DRCUML_PTYPE_IMMEDIATE)
4910
// 32-bit destination with memory/immediate or register/immediate
4911
if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate())
5320
if (src1p.type == DRCUML_PTYPE_MEMORY)
5321
emit_imul_r32_m32_imm(&dst, REG_EAX, MABS(src1p.value), src2p.value); // imul eax,[src1p],src2p
5322
else if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
5323
emit_imul_r32_r32_imm(&dst, REG_EAX, src1p.value, src2p.value); // imul eax,src1p,src2p
5324
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
4913
if (src1p.is_memory())
4914
emit_imul_r32_m32_imm(dst, REG_EAX, MABS(src1p.memory()), src2p.immediate()); // imul eax,[src1p],src2p
4915
else if (src1p.is_int_register())
4916
emit_imul_r32_r32_imm(dst, REG_EAX, src1p.ireg(), src2p.immediate()); // imul eax,src1p,src2p
4917
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5327
/* 32-bit destination, general case */
4920
// 32-bit destination, general case
5328
4921
else if (!compute_hi)
5330
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &src1p); // mov eax,src1p
5331
if (src2p.type == DRCUML_PTYPE_MEMORY)
5332
emit_imul_r32_m32(&dst, REG_EAX, MABS(src2p.value)); // imul eax,[src2p]
5333
else if (src2p.type == DRCUML_PTYPE_INT_REGISTER)
5334
emit_imul_r32_r32(&dst, REG_EAX, src2p.value); // imul eax,src2p
5335
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
4923
emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
4924
if (src2p.is_memory())
4925
emit_imul_r32_m32(dst, REG_EAX, MABS(src2p.memory())); // imul eax,[src2p]
4926
else if (src2p.is_int_register())
4927
emit_imul_r32_r32(dst, REG_EAX, src2p.ireg()); // imul eax,src2p
4928
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5338
/* 64-bit destination, general case */
4931
// 64-bit destination, general case
5341
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &src1p); // mov eax,src1p
5342
if (src2p.type == DRCUML_PTYPE_MEMORY)
5343
emit_imul_m32(&dst, MABS(src2p.value)); // imul [src2p]
5344
else if (src2p.type == DRCUML_PTYPE_INT_REGISTER)
5345
emit_imul_r32(&dst, src2p.value); // imul src2p
5346
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE)
4934
emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
4935
if (src2p.is_memory())
4936
emit_imul_m32(dst, MABS(src2p.memory())); // imul [src2p]
4937
else if (src2p.is_int_register())
4938
emit_imul_r32(dst, src2p.ireg()); // imul src2p
4939
else if (src2p.is_immediate())
5348
emit_mov_r32_imm(&dst, REG_EDX, src2p.value); // mov edx,src2p
5349
emit_imul_r32(&dst, REG_EDX); // imul edx
4941
emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
4942
emit_imul_r32(dst, REG_EDX); // imul edx
5351
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
5352
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
4944
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
4945
emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
5356
if (inst->flags != 0)
4949
if (inst.flags() != 0)
5358
4951
if (zsflags != 0)
5361
emit_pushf(&dst); // pushf
4954
emit_pushf(dst); // pushf
5362
4955
if (compute_hi)
5364
if (inst->flags == DRCUML_FLAG_Z)
5365
emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
5366
else if (inst->flags == DRCUML_FLAG_S)
5367
emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
4957
if (inst.flags() == FLAG_Z)
4958
emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
4959
else if (inst.flags() == FLAG_S)
4960
emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
5370
emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
5371
emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
5372
emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
5373
emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
4963
emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
4964
emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
4965
emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
4966
emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
5377
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
4970
emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
5379
/* we rely on the fact that OF is cleared by all logical operations above */
4972
// we rely on the fact that OF is cleared by all logical operations above
5382
emit_pushf(&dst); // pushf
5383
emit_pop_r32(&dst, REG_EAX); // pop eax
5384
emit_and_m32_imm(&dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
5385
emit_or_m32_r32(&dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
5386
emit_popf(&dst); // popf
4975
emit_pushf(dst); // pushf
4976
emit_pop_r32(dst, REG_EAX); // pop eax
4977
emit_and_m32_imm(dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
4978
emit_or_m32_r32(dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
4979
emit_popf(dst); // popf
5393
else if (inst->size == 8)
4986
else if (inst.size() == 8)
5396
emit_mov_m32_imm(&dst, MBD(REG_ESP, 24), inst->flags); // mov [esp+24],flags
5397
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 16), &src2p); // mov [esp+16],src2p
5398
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &src1p); // mov [esp+8],src1p
4989
emit_mov_m32_imm(dst, MBD(REG_ESP, 24), inst.flags()); // mov [esp+24],flags
4990
emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
4991
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
5399
4992
if (!compute_hi)
5400
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo); // mov [esp+4],&reslo
4993
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
5402
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reshi); // push [esp+4],&reshi
5403
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)&drcbe->reslo); // mov [esp],&reslo
5404
emit_call(&dst, (x86code *)dmuls); // call dmuls
5405
if (inst->flags != 0)
5406
emit_push_m32(&dst, MISD(REG_EAX, 4, flags_unmap)); // push flags_unmap[eax*4]
5407
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
5408
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
5409
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
4995
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
4996
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
4997
emit_call(dst, (x86code *)dmuls); // call dmuls
4998
if (inst.flags() != 0)
4999
emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
5000
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
5001
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
5002
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5410
5003
if (compute_hi)
5412
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
5413
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov edx,reshi.hi
5414
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5416
if (inst->flags != 0)
5417
emit_popf(&dst); // popf
5423
/*-------------------------------------------------
5424
op_divu - process a DIVU opcode
5425
-------------------------------------------------*/
5427
static x86code *op_divu(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5429
drcuml_parameter dstp, edstp, src1p, src2p;
5433
/* validate instruction */
5434
assert(inst->size == 4 || inst->size == 8);
5435
assert_no_condition(inst);
5436
assert_flags(inst, DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5438
/* normalize parameters */
5439
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &edstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5440
compute_rem = (dstp.type != edstp.type || dstp.value != edstp.value);
5443
if (inst->size == 4)
5446
emit_mov_r32_p32(drcbe, &dst, REG_ECX, &src2p); // mov ecx,src2p
5447
if (inst->flags != 0)
5449
emit_mov_r32_imm(&dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
5450
emit_add_r32_r32(&dst, REG_EAX, REG_EAX); // add eax,eax
5452
emit_jecxz_link(&dst, &skip); // jecxz skip
5453
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &src1p); // mov eax,src1p
5454
emit_xor_r32_r32(&dst, REG_EDX, REG_EDX); // xor edx,edx
5455
emit_div_r32(&dst, REG_ECX); // div ecx
5456
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
5458
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
5459
if (inst->flags != 0)
5460
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
5461
track_resolve_link(drcbe, &dst, &skip); // skip:
5465
else if (inst->size == 8)
5468
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 16), &src2p); // mov [esp+16],src2p
5469
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &src1p); // mov [esp+8],src1p
5471
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo); // mov [esp+4],&reslo
5473
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reshi); // push [esp+4],&reshi
5474
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)&drcbe->reslo); // mov [esp],&reslo
5475
emit_call(&dst, (x86code *)ddivu); // call ddivu
5476
if (inst->flags != 0)
5477
emit_push_m32(&dst, MISD(REG_EAX, 4, flags_unmap)); // push flags_unmap[eax*4]
5478
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
5479
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
5480
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5483
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
5484
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov edx,reshi.hi
5485
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5487
if (inst->flags != 0)
5488
emit_popf(&dst); // popf
5494
/*-------------------------------------------------
5495
op_divs - process a DIVS opcode
5496
-------------------------------------------------*/
5498
static x86code *op_divs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5500
drcuml_parameter dstp, edstp, src1p, src2p;
5504
/* validate instruction */
5505
assert(inst->size == 4 || inst->size == 8);
5506
assert_no_condition(inst);
5507
assert_flags(inst, DRCUML_FLAG_V | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5509
/* normalize parameters */
5510
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &edstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5511
compute_rem = (dstp.type != edstp.type || dstp.value != edstp.value);
5514
if (inst->size == 4)
5517
emit_mov_r32_p32(drcbe, &dst, REG_ECX, &src2p); // mov ecx,src2p
5518
if (inst->flags != 0)
5520
emit_mov_r32_imm(&dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
5521
emit_add_r32_r32(&dst, REG_EAX, REG_EAX); // add eax,eax
5523
emit_jecxz_link(&dst, &skip); // jecxz skip
5524
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &src1p); // mov eax,src1p
5525
emit_cdq(&dst); // cdq
5526
emit_idiv_r32(&dst, REG_ECX); // idiv ecx
5527
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
5529
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
5530
if (inst->flags != 0)
5531
emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
5532
track_resolve_link(drcbe, &dst, &skip); // skip:
5536
else if (inst->size == 8)
5539
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 16), &src2p); // mov [esp+16],src2p
5540
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &src1p); // mov [esp+8],src1p
5542
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo); // mov [esp+4],&reslo
5544
emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reshi); // push [esp+4],&reshi
5545
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)&drcbe->reslo); // mov [esp],&reslo
5546
emit_call(&dst, (x86code *)ddivs); // call ddivs
5547
if (inst->flags != 0)
5548
emit_push_m32(&dst, MISD(REG_EAX, 4, flags_unmap)); // push flags_unmap[eax*4]
5549
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
5550
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
5551
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5554
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
5555
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov edx,reshi.hi
5556
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5558
if (inst->flags != 0)
5559
emit_popf(&dst); // popf
5565
/*-------------------------------------------------
5566
op_and - process a AND opcode
5567
-------------------------------------------------*/
5569
static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5571
drcuml_parameter dstp, src1p, src2p;
5574
/* validate instruction */
5575
assert(inst->size == 4 || inst->size == 8);
5576
assert_no_condition(inst);
5577
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5579
/* normalize parameters */
5580
param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5582
/* pick a target register for the general case */
5583
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5586
if (inst->size == 4)
5588
/* dstp == src1p in memory */
5589
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5590
emit_and_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // and [dstp],src2p
5592
/* AND with immediate 0xff */
5593
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
5595
if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
5596
emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
5597
else if (src1p.type == DRCUML_PTYPE_MEMORY)
5598
emit_movzx_r32_m8(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
5599
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5602
/* AND with immediate 0xffff */
5603
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
5605
if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
5606
emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
5607
else if (src1p.type == DRCUML_PTYPE_MEMORY)
5608
emit_movzx_r32_m16(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
5609
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5615
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5616
emit_and_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // and dstreg,src2p
5617
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5622
else if (inst->size == 8)
5624
/* dstp == src1p in memory */
5625
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5626
emit_and_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // and [dstp],src2p
5628
/* AND with immediate 0xff */
5629
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
5631
if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
5632
emit_movzx_r32_r8(&dst, dstreg, src1p.value); // movzx dstreg,src1p
5633
else if (src1p.type == DRCUML_PTYPE_MEMORY)
5634
emit_movzx_r32_m8(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
5635
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5636
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
5637
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
5638
else if (dstp.type == DRCUML_PTYPE_MEMORY)
5639
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
5642
/* AND with immediate 0xffff */
5643
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
5645
if (src1p.type == DRCUML_PTYPE_INT_REGISTER)
5646
emit_movzx_r32_r16(&dst, dstreg, src1p.value); // movzx dstreg,src1p
5647
else if (src1p.type == DRCUML_PTYPE_MEMORY)
5648
emit_movzx_r32_m16(&dst, dstreg, MABS(src1p.value)); // movzx dstreg,[src1p]
5649
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5650
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
5651
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
5652
else if (dstp.type == DRCUML_PTYPE_MEMORY)
5653
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
5656
/* AND with immediate 0xffffffff */
5657
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffffffff && inst->flags == 0)
5659
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5660
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5661
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
5662
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
5663
else if (dstp.type == DRCUML_PTYPE_MEMORY)
5664
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
5667
/* AND with immediate 0xffffffff00000000 */
5668
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == U64(0xffffffff00000000) && inst->flags == 0)
5670
if (src1p.type != dstp.type || src1p.value != dstp.value)
5005
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
5006
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
5007
emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5009
if (inst.flags() != 0)
5010
emit_popf(dst); // popf
5015
//-------------------------------------------------
5016
// op_divu - process a DIVU opcode
5017
//-------------------------------------------------
5019
void drcbe_x86::op_divu(x86code *&dst, const instruction &inst)
5021
// validate instruction
5022
assert(inst.size() == 4 || inst.size() == 8);
5023
assert_no_condition(inst);
5024
assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
5026
// normalize parameters
5027
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5028
be_parameter edstp(*this, inst.param(1), PTYPE_MR);
5029
be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
5030
be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
5031
bool compute_rem = (dstp != edstp);
5034
if (inst.size() == 4)
5037
emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
5038
if (inst.flags() != 0)
5040
emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
5041
emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
5044
emit_jecxz_link(dst, skip); // jecxz skip
5045
emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
5046
emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
5047
emit_div_r32(dst, REG_ECX); // div ecx
5048
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5050
emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
5051
if (inst.flags() != 0)
5052
emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
5053
track_resolve_link(dst, skip); // skip:
5057
else if (inst.size() == 8)
5060
emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
5061
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
5063
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
5065
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
5066
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
5067
emit_call(dst, (x86code *)ddivu); // call ddivu
5068
if (inst.flags() != 0)
5069
emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
5070
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
5071
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
5072
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5075
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
5076
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
5077
emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5079
if (inst.flags() != 0)
5080
emit_popf(dst); // popf
5085
//-------------------------------------------------
5086
// op_divs - process a DIVS opcode
5087
//-------------------------------------------------
5089
void drcbe_x86::op_divs(x86code *&dst, const instruction &inst)
5091
// validate instruction
5092
assert(inst.size() == 4 || inst.size() == 8);
5093
assert_no_condition(inst);
5094
assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
5096
// normalize parameters
5097
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5098
be_parameter edstp(*this, inst.param(1), PTYPE_MR);
5099
be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
5100
be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
5101
bool compute_rem = (dstp != edstp);
5104
if (inst.size() == 4)
5107
emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
5108
if (inst.flags() != 0)
5110
emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
5111
emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
5114
emit_jecxz_link(dst, skip); // jecxz skip
5115
emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
5116
emit_cdq(dst); // cdq
5117
emit_idiv_r32(dst, REG_ECX); // idiv ecx
5118
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5120
emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
5121
if (inst.flags() != 0)
5122
emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
5123
track_resolve_link(dst, skip); // skip:
5127
else if (inst.size() == 8)
5130
emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
5131
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
5133
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
5135
emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
5136
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
5137
emit_call(dst, (x86code *)ddivs); // call ddivs
5138
if (inst.flags() != 0)
5139
emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
5140
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
5141
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
5142
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5145
emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
5146
emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
5147
emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
5149
if (inst.flags() != 0)
5150
emit_popf(dst); // popf
5155
//-------------------------------------------------
5156
// op_and - process a AND opcode
5157
//-------------------------------------------------
5159
void drcbe_x86::op_and(x86code *&dst, const instruction &inst)
5161
// validate instruction
5162
assert(inst.size() == 4 || inst.size() == 8);
5163
assert_no_condition(inst);
5164
assert_flags(inst, FLAG_Z | FLAG_S);
5166
// normalize parameters
5167
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5168
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5169
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5170
normalize_commutative(src1p, src2p);
5172
// pick a target register for the general case
5173
int dstreg = dstp.select_register(REG_EAX, src2p);
5176
if (inst.size() == 4)
5178
// dstp == src1p in memory
5179
if (dstp.is_memory() && dstp == src1p)
5180
emit_and_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
5182
// AND with immediate 0xff
5183
else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
5185
if (src1p.is_int_register())
5186
emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
5187
else if (src1p.is_memory())
5188
emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
5189
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5192
// AND with immediate 0xffff
5193
else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
5195
if (src1p.is_int_register())
5196
emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
5197
else if (src1p.is_memory())
5198
emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
5199
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5205
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5206
emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p
5207
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5212
else if (inst.size() == 8)
5214
// dstp == src1p in memory
5215
if (dstp.is_memory() && dstp == src1p)
5216
emit_and_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
5218
// AND with immediate 0xff
5219
else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
5221
if (src1p.is_int_register())
5222
emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
5223
else if (src1p.is_memory())
5224
emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
5225
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5226
if (dstp.is_int_register())
5227
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
5228
else if (dstp.is_memory())
5229
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
5232
// AND with immediate 0xffff
5233
else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
5235
if (src1p.is_int_register())
5236
emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
5237
else if (src1p.is_memory())
5238
emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
5239
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5240
if (dstp.is_int_register())
5241
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
5242
else if (dstp.is_memory())
5243
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
5246
// AND with immediate 0xffffffff
5247
else if (src2p.is_immediate_value(0xffffffff) && inst.flags() == 0)
5249
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5250
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5251
if (dstp.is_int_register())
5252
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
5253
else if (dstp.is_memory())
5254
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
5257
// AND with immediate 0xffffffff00000000
5258
else if (src2p.is_immediate_value(U64(0xffffffff00000000)) && inst.flags() == 0)
5672
emit_mov_r64_p64(drcbe, &dst, REG_NONE, REG_EDX, &src1p); // mov dstreg,src1p
5673
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_NONE, REG_EDX); // mov dstp,dstreg
5262
emit_mov_r64_p64(dst, REG_NONE, REG_EDX, src1p); // mov dstreg,src1p
5263
emit_mov_p64_r64(dst, dstp, REG_NONE, REG_EDX); // mov dstp,dstreg
5675
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
5676
emit_xor_r32_r32(&dst, dstp.value, dstp.value); // xor dstlo,dstlo
5677
else if (dstp.type == DRCUML_PTYPE_MEMORY)
5678
emit_mov_m32_imm(&dst, MABS(dstp.value), 0); // mov dstlo,0
5681
/* AND with immediate <= 0xffffffff */
5682
else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value <= 0xffffffff && inst->flags == 0)
5684
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5685
emit_and_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // and dstreg,src2p
5686
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5687
if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
5688
emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov dsthi,0
5689
else if (dstp.type == DRCUML_PTYPE_MEMORY)
5690
emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov dsthi,0
5696
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5697
emit_and_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // and dstreg:dstp,src2p
5698
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5705
/*-------------------------------------------------
5706
op_test - process a TEST opcode
5707
-------------------------------------------------*/
5709
static x86code *op_test(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5711
drcuml_parameter src1p, src2p;
5714
/* validate instruction */
5715
assert(inst->size == 4 || inst->size == 8);
5716
assert_no_condition(inst);
5717
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5719
/* normalize parameters */
5720
param_normalize_2_commutative(drcbe, inst, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5722
/* pick a target register for the general case */
5723
src1reg = param_select_register(REG_EAX, &src1p, NULL);
5726
if (inst->size == 4)
5728
/* src1p in memory */
5729
if (src1p.type == DRCUML_PTYPE_MEMORY)
5730
emit_test_m32_p32(drcbe, &dst, MABS(src1p.value), &src2p, inst); // test [src1p],src2p
5735
emit_mov_r32_p32(drcbe, &dst, src1reg, &src1p); // mov src1reg,src1p
5736
emit_test_r32_p32(drcbe, &dst, src1reg, &src2p, inst); // test src1reg,src2p
5741
else if (inst->size == 8)
5743
/* src1p in memory */
5744
if (src1p.type == DRCUML_PTYPE_MEMORY)
5745
emit_test_m64_p64(drcbe, &dst, MABS(src1p.value), &src2p, inst); // test [dstp],src2p
5750
emit_mov_r64_p64(drcbe, &dst, src1reg, REG_EDX, &src1p); // mov src1reg:dstp,[src1p]
5751
emit_test_r64_p64(drcbe, &dst, src1reg, REG_EDX, &src2p, inst); // test src1reg:dstp,src2p
5758
/*-------------------------------------------------
5759
op_or - process a OR opcode
5760
-------------------------------------------------*/
5762
static x86code *op_or(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5764
drcuml_parameter dstp, src1p, src2p;
5767
/* validate instruction */
5768
assert(inst->size == 4 || inst->size == 8);
5769
assert_no_condition(inst);
5770
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5772
/* normalize parameters */
5773
param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5775
/* pick a target register for the general case */
5776
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5779
if (inst->size == 4)
5781
/* dstp == src1p in memory */
5782
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5783
emit_or_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // or [dstp],src2p
5788
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5789
emit_or_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // or dstreg,src2p
5790
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5795
else if (inst->size == 8)
5797
/* dstp == src1p in memory */
5798
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5799
emit_or_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // or [dstp],src2p
5804
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5805
emit_or_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // or dstreg:dstp,src2p
5806
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5813
/*-------------------------------------------------
5814
op_xor - process a XOR opcode
5815
-------------------------------------------------*/
5817
static x86code *op_xor(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5819
drcuml_parameter dstp, src1p, src2p;
5822
/* validate instruction */
5823
assert(inst->size == 4 || inst->size == 8);
5824
assert_no_condition(inst);
5825
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5827
/* normalize parameters */
5828
param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5830
/* pick a target register for the general case */
5831
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5834
if (inst->size == 4)
5836
/* dstp == src1p in memory */
5837
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5838
emit_xor_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // xor [dstp],src2p
5843
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
5844
emit_xor_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // xor dstreg,src2p
5845
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5850
else if (inst->size == 8)
5852
/* dstp == src1p in memory */
5853
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5854
emit_xor_m64_p64(drcbe, &dst, MABS(dstp.value), &src2p, inst); // xor [dstp],src2p
5859
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
5860
emit_xor_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // xor dstreg:dstp,src2p
5861
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5868
/*-------------------------------------------------
5869
op_lzcnt - process a LZCNT opcode
5870
-------------------------------------------------*/
5872
static x86code *op_lzcnt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5874
drcuml_parameter dstp, srcp;
5877
/* validate instruction */
5878
assert(inst->size == 4 || inst->size == 8);
5879
assert_no_condition(inst);
5880
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5882
/* normalize parameters */
5883
param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
5885
/* pick a target register for the general case */
5886
dstreg = param_select_register(REG_EAX, &dstp, NULL);
5889
if (inst->size == 4)
5891
emit_mov_r32_p32(drcbe, &dst, dstreg, &srcp); // mov dstreg,src1p
5892
emit_mov_r32_imm(&dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
5893
emit_bsr_r32_r32(&dst, dstreg, dstreg); // bsr dstreg,dstreg
5894
emit_cmovcc_r32_r32(&dst, COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
5895
emit_xor_r32_imm(&dst, dstreg, 31); // xor dstreg,31
5896
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5900
else if (inst->size == 8)
5265
if (dstp.is_int_register())
5266
emit_xor_r32_r32(dst, dstp.ireg(), dstp.ireg()); // xor dstlo,dstlo
5267
else if (dstp.is_memory())
5268
emit_mov_m32_imm(dst, MABS(dstp.memory()), 0); // mov dstlo,0
5271
// AND with immediate <= 0xffffffff
5272
else if (src2p.is_immediate() && src2p.immediate() <= 0xffffffff && inst.flags() == 0)
5274
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5275
emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p
5276
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5277
if (dstp.is_int_register())
5278
emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
5279
else if (dstp.is_memory())
5280
emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
5286
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5287
emit_and_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // and dstreg:dstp,src2p
5288
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5294
//-------------------------------------------------
5295
// op_test - process a TEST opcode
5296
//-------------------------------------------------
5298
void drcbe_x86::op_test(x86code *&dst, const instruction &inst)
5300
// validate instruction
5301
assert(inst.size() == 4 || inst.size() == 8);
5302
assert_no_condition(inst);
5303
assert_flags(inst, FLAG_Z | FLAG_S);
5305
// normalize parameters
5306
be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
5307
be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
5308
normalize_commutative(src1p, src2p);
5310
// pick a target register for the general case
5311
int src1reg = src1p.select_register(REG_EAX);
5314
if (inst.size() == 4)
5317
if (src1p.is_memory())
5318
emit_test_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p
5323
emit_mov_r32_p32(dst, src1reg, src1p); // mov src1reg,src1p
5324
emit_test_r32_p32(dst, src1reg, src2p, inst); // test src1reg,src2p
5329
else if (inst.size() == 8)
5332
if (src1p.is_memory())
5333
emit_test_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // test [dstp],src2p
5338
emit_mov_r64_p64(dst, src1reg, REG_EDX, src1p); // mov src1reg:dstp,[src1p]
5339
emit_test_r64_p64(dst, src1reg, REG_EDX, src2p, inst); // test src1reg:dstp,src2p
5345
//-------------------------------------------------
5346
// op_or - process a OR opcode
5347
//-------------------------------------------------
5349
void drcbe_x86::op_or(x86code *&dst, const instruction &inst)
5351
// validate instruction
5352
assert(inst.size() == 4 || inst.size() == 8);
5353
assert_no_condition(inst);
5354
assert_flags(inst, FLAG_Z | FLAG_S);
5356
// normalize parameters
5357
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5358
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5359
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5360
normalize_commutative(src1p, src2p);
5362
// pick a target register for the general case
5363
int dstreg = dstp.select_register(REG_EAX, src2p);
5366
if (inst.size() == 4)
5368
// dstp == src1p in memory
5369
if (dstp.is_memory() && dstp == src1p)
5370
emit_or_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
5375
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5376
emit_or_r32_p32(dst, dstreg, src2p, inst); // or dstreg,src2p
5377
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5382
else if (inst.size() == 8)
5384
// dstp == src1p in memory
5385
if (dstp.is_memory() && dstp == src1p)
5386
emit_or_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
5391
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5392
emit_or_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // or dstreg:dstp,src2p
5393
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5399
//-------------------------------------------------
5400
// op_xor - process a XOR opcode
5401
//-------------------------------------------------
5403
void drcbe_x86::op_xor(x86code *&dst, const instruction &inst)
5405
// validate instruction
5406
assert(inst.size() == 4 || inst.size() == 8);
5407
assert_no_condition(inst);
5408
assert_flags(inst, FLAG_Z | FLAG_S);
5410
// normalize parameters
5411
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5412
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5413
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5414
normalize_commutative(src1p, src2p);
5416
// pick a target register for the general case
5417
int dstreg = dstp.select_register(REG_EAX, src2p);
5420
if (inst.size() == 4)
5422
// dstp == src1p in memory
5423
if (dstp.is_memory() && dstp == src1p)
5424
emit_xor_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
5429
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5430
emit_xor_r32_p32(dst, dstreg, src2p, inst); // xor dstreg,src2p
5431
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5436
else if (inst.size() == 8)
5438
// dstp == src1p in memory
5439
if (dstp.is_memory() && dstp == src1p)
5440
emit_xor_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
5445
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5446
emit_xor_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // xor dstreg:dstp,src2p
5447
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5453
//-------------------------------------------------
5454
// op_lzcnt - process a LZCNT opcode
5455
//-------------------------------------------------
5457
void drcbe_x86::op_lzcnt(x86code *&dst, const instruction &inst)
5459
// validate instruction
5460
assert(inst.size() == 4 || inst.size() == 8);
5461
assert_no_condition(inst);
5462
assert_flags(inst, FLAG_Z | FLAG_S);
5464
// normalize parameters
5465
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5466
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
5468
// pick a target register for the general case
5469
int dstreg = dstp.select_register(REG_EAX);
5472
if (inst.size() == 4)
5474
emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
5475
emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
5476
emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg
5477
emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
5478
emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31
5479
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5483
else if (inst.size() == 8)
5485
emit_mov_r64_p64(dst, REG_EDX, dstreg, srcp); // mov dstreg:edx,srcp
5486
emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg
5902
5487
emit_link skip;
5904
emit_mov_r64_p64(drcbe, &dst, REG_EDX, dstreg, &srcp); // mov dstreg:edx,srcp
5905
emit_bsr_r32_r32(&dst, dstreg, dstreg); // bsr dstreg,dstreg
5906
emit_jcc_short_link(&dst, COND_NZ, &skip); // jnz skip
5907
emit_mov_r32_imm(&dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
5908
emit_bsr_r32_r32(&dst, dstreg, REG_EDX); // bsr dstreg,edx
5909
emit_cmovcc_r32_r32(&dst, COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
5910
emit_add_r32_imm(&dst, REG_ECX, 32); // add ecx,32
5911
track_resolve_link(drcbe, &dst, &skip); // skip:
5912
emit_xor_r32_r32(&dst, REG_EDX, REG_EDX); // xor edx,edx
5913
emit_xor_r32_imm(&dst, dstreg, 31); // xor dstreg,31
5914
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
5920
/*-------------------------------------------------
5921
op_bswap - process a BSWAP opcode
5922
-------------------------------------------------*/
5924
static x86code *op_bswap(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5926
drcuml_parameter dstp, srcp;
5929
/* validate instruction */
5930
assert(inst->size == 4 || inst->size == 8);
5931
assert_no_condition(inst);
5932
assert_flags(inst, DRCUML_FLAG_Z | DRCUML_FLAG_S);
5934
/* normalize parameters */
5935
param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
5937
/* pick a target register for the general case */
5938
dstreg = param_select_register(REG_EAX, &dstp, NULL);
5941
if (inst->size == 4)
5943
emit_mov_r32_p32(drcbe, &dst, dstreg, &srcp); // mov dstreg,src1p
5944
emit_bswap_r32(&dst, dstreg); // bswap dstreg
5945
if (inst->flags != 0)
5946
emit_test_r32_r32(&dst, dstreg, dstreg); // test dstreg,dstreg
5947
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
5951
else if (inst->size == 8)
5953
emit_mov_r64_p64(drcbe, &dst, REG_EDX, dstreg, &srcp); // mov dstreg:edx,srcp
5954
emit_bswap_r32(&dst, dstreg); // bswap dstreg
5955
emit_bswap_r32(&dst, REG_EDX); // bswap edx
5956
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
5957
if (inst->flags == DRCUML_FLAG_Z)
5958
emit_or_r32_r32(&dst, REG_EDX, dstreg); // or edx,eax
5959
else if (inst->flags == DRCUML_FLAG_S)
5960
emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
5963
emit_movzx_r32_r16(&dst, REG_ECX, dstreg); // movzx ecx,dstreg
5964
emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
5965
emit_mov_r32_r32(&dst, REG_ECX, dstreg); // mov ecx,dstreg
5966
emit_shr_r32_imm(&dst, REG_ECX, 16); // shr ecx,16
5967
emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
5974
/*-------------------------------------------------
5975
op_shl - process a SHL opcode
5976
-------------------------------------------------*/
5978
static x86code *op_shl(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5980
drcuml_parameter dstp, src1p, src2p;
5983
/* validate instruction */
5984
assert(inst->size == 4 || inst->size == 8);
5985
assert_no_condition(inst);
5986
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
5988
/* normalize parameters */
5989
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5991
/* pick a target register for the general case */
5992
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5995
if (inst->size == 4)
5997
/* dstp == src1p in memory */
5998
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
5999
emit_shl_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // shl [dstp],src2p
6004
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6005
emit_shl_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // shl dstreg,src2p
6006
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6011
else if (inst->size == 8)
6014
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6015
emit_shl_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // shl dstreg:dstp,src2p
6016
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6022
/*-------------------------------------------------
6023
op_shr - process a SHR opcode
6024
-------------------------------------------------*/
6026
static x86code *op_shr(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6028
drcuml_parameter dstp, src1p, src2p;
6031
/* validate instruction */
6032
assert(inst->size == 4 || inst->size == 8);
6033
assert_no_condition(inst);
6034
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6036
/* normalize parameters */
6037
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6039
/* pick a target register for the general case */
6040
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6043
if (inst->size == 4)
6045
/* dstp == src1p in memory */
6046
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6047
emit_shr_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // shr [dstp],src2p
6052
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6053
emit_shr_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // shr dstreg,src2p
6054
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6059
else if (inst->size == 8)
6062
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6063
emit_shr_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // shr dstreg:dstp,src2p
6064
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6070
/*-------------------------------------------------
6071
op_sar - process a SAR opcode
6072
-------------------------------------------------*/
6074
static x86code *op_sar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6076
drcuml_parameter dstp, src1p, src2p;
6079
/* validate instruction */
6080
assert(inst->size == 4 || inst->size == 8);
6081
assert_no_condition(inst);
6082
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6084
/* normalize parameters */
6085
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6087
/* pick a target register for the general case */
6088
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6091
if (inst->size == 4)
6093
/* dstp == src1p in memory */
6094
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6095
emit_sar_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // sar [dstp],src2p
6100
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6101
emit_sar_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // sar dstreg,src2p
6102
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6107
else if (inst->size == 8)
6110
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6111
emit_sar_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // sar dstreg:dstp,src2p
6112
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6118
/*-------------------------------------------------
6119
op_rol - process a rol opcode
6120
-------------------------------------------------*/
6122
static x86code *op_rol(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6124
drcuml_parameter dstp, src1p, src2p;
6127
/* validate instruction */
6128
assert(inst->size == 4 || inst->size == 8);
6129
assert_no_condition(inst);
6130
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6132
/* normalize parameters */
6133
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6135
/* pick a target register for the general case */
6136
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6139
if (inst->size == 4)
6141
/* dstp == src1p in memory */
6142
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6143
emit_rol_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // rol [dstp],src2p
6148
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6149
emit_rol_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // rol dstreg,src2p
6150
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6155
else if (inst->size == 8)
6158
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6159
emit_rol_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // rol dstreg:dstp,src2p
6160
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6166
/*-------------------------------------------------
6167
op_ror - process a ROR opcode
6168
-------------------------------------------------*/
6170
static x86code *op_ror(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6172
drcuml_parameter dstp, src1p, src2p;
6175
/* validate instruction */
6176
assert(inst->size == 4 || inst->size == 8);
6177
assert_no_condition(inst);
6178
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6180
/* normalize parameters */
6181
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6183
/* pick a target register for the general case */
6184
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6187
if (inst->size == 4)
6189
/* dstp == src1p in memory */
6190
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6191
emit_ror_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // ror [dstp],src2p
6196
emit_mov_r32_p32(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6197
emit_ror_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // ror dstreg,src2p
6198
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6203
else if (inst->size == 8)
6206
emit_mov_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6207
emit_ror_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // ror dstreg:dstp,src2p
6208
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6214
/*-------------------------------------------------
6215
op_rolc - process a ROLC opcode
6216
-------------------------------------------------*/
6218
static x86code *op_rolc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6220
drcuml_parameter dstp, src1p, src2p;
6223
/* validate instruction */
6224
assert(inst->size == 4 || inst->size == 8);
6225
assert_no_condition(inst);
6226
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6228
/* normalize parameters */
6229
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6231
/* pick a target register for the general case */
6232
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6235
if (inst->size == 4)
6237
/* dstp == src1p in memory */
6238
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6239
emit_rcl_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // rcl [dstp],src2p
6244
emit_mov_r32_p32_keepflags(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6245
emit_rcl_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // rcl dstreg,src2p
6246
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6251
else if (inst->size == 8)
6254
emit_mov_r64_p64_keepflags(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6255
emit_rcl_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // rcl dstreg:dstp,src2p
6256
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6262
/*-------------------------------------------------
6263
op_rorc - process a RORC opcode
6264
-------------------------------------------------*/
6266
static x86code *op_rorc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6268
drcuml_parameter dstp, src1p, src2p;
6271
/* validate instruction */
6272
assert(inst->size == 4 || inst->size == 8);
6273
assert_no_condition(inst);
6274
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_S);
6276
/* normalize parameters */
6277
param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6279
/* pick a target register for the general case */
6280
dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6283
if (inst->size == 4)
6285
/* dstp == src1p in memory */
6286
if (src1p.type == dstp.type && src1p.value == dstp.value && dstp.type == DRCUML_PTYPE_MEMORY)
6287
emit_rcr_m32_p32(drcbe, &dst, MABS(dstp.value), &src2p, inst); // rcr [dstp],src2p
6292
emit_mov_r32_p32_keepflags(drcbe, &dst, dstreg, &src1p); // mov dstreg,src1p
6293
emit_rcr_r32_p32(drcbe, &dst, dstreg, &src2p, inst); // rcr dstreg,src2p
6294
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
6299
else if (inst->size == 8)
6302
emit_mov_r64_p64_keepflags(drcbe, &dst, dstreg, REG_EDX, &src1p); // mov dstreg:dstp,[src1p]
6303
emit_rcr_r64_p64(drcbe, &dst, dstreg, REG_EDX, &src2p, inst); // rcr dstreg:dstp,src2p
6304
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
6311
/***************************************************************************
6312
FLOATING POINT OPERATIONS
6313
***************************************************************************/
6315
/*-------------------------------------------------
6316
op_fload - process a FLOAD opcode
6317
-------------------------------------------------*/
6319
static x86code *op_fload(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6321
drcuml_parameter dstp, basep, indp;
6323
/* validate instruction */
6324
assert(inst->size == 4 || inst->size == 8);
6325
assert_no_condition(inst);
6326
assert_no_flags(inst);
6328
/* normalize parameters */
6329
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &basep, PTYPE_M, &indp, PTYPE_MRI);
6331
/* immediate index */
6332
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
6334
emit_mov_r32_m32(&dst, REG_EAX, MABS(basep.value + 4*indp.value)); // mov eax,[basep + 4*indp]
6335
if (inst->size == 8)
6336
emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + 4 + 4*indp.value)); // mov edx,[basep + 4*indp + 4]
6342
int indreg = param_select_register(REG_ECX, &indp, NULL);
6343
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
6344
emit_mov_r32_m32(&dst, REG_EAX, MISD(indreg, 4, basep.value)); // mov eax,[basep + 4*indp]
6345
if (inst->size == 8)
6346
emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, 4, basep.value + 4)); // mov edx,[basep + 4*indp + 4]
6350
emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
6351
if (inst->size == 8)
6352
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp + 4],edx
6357
/*-------------------------------------------------
6358
op_fstore - process a FSTORE opcode
6359
-------------------------------------------------*/
6361
static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6363
drcuml_parameter srcp, basep, indp;
6365
/* validate instruction */
6366
assert(inst->size == 4 || inst->size == 8);
6367
assert_no_condition(inst);
6368
assert_no_flags(inst);
6370
/* normalize parameters */
6371
param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MF);
6374
emit_mov_r32_m32(&dst, REG_EAX, MABS(srcp.value)); // mov eax,[srcp]
6375
if (inst->size == 8)
6376
emit_mov_r32_m32(&dst, REG_EDX, MABS(srcp.value + 4)); // mov edx,[srcp + 4]
6378
/* immediate index */
6379
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
6381
emit_mov_m32_r32(&dst, MABS(basep.value + 4*indp.value), REG_EAX); // mov [basep + 4*indp],eax
6382
if (inst->size == 8)
6383
emit_mov_m32_r32(&dst, MABS(basep.value + 4 + 4*indp.value), REG_EDX); // mov [basep + 4*indp + 4],edx
6389
int indreg = param_select_register(REG_ECX, &indp, NULL);
6390
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
6391
emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value), REG_EAX); // mov [basep + 4*indp],eax
6392
if (inst->size == 8)
6393
emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value + 4), REG_EDX); // mov [basep + 4*indp + 4],edx
6399
/*-------------------------------------------------
6400
op_fread - process a FREAD opcode
6401
-------------------------------------------------*/
6403
static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6405
drcuml_parameter dstp, spacep, addrp;
6407
/* validate instruction */
6408
assert(inst->size == 4 || inst->size == 8);
6409
assert_no_condition(inst);
6410
assert_no_flags(inst);
6412
/* normalize parameters */
6413
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &addrp, PTYPE_MRI, &spacep, PTYPE_I);
6415
/* set up a call to the read dword/qword handler */
6416
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
6417
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacep.value]); // mov [esp],space
6418
if (inst->size == 4)
6419
emit_call(&dst, (x86code *)drcbe->accessors[spacep.value].read_dword); // call read_dword
6420
else if (inst->size == 8)
6421
emit_call(&dst, (x86code *)drcbe->accessors[spacep.value].read_qword); // call read_qword
6424
if (inst->size == 4)
6425
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
6426
else if (inst->size == 8)
6427
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
6433
/*-------------------------------------------------
6434
op_fwrite - process a FWRITE opcode
6435
-------------------------------------------------*/
6437
static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6439
drcuml_parameter spacep, addrp, srcp;
6441
/* validate instruction */
6442
assert(inst->size == 4 || inst->size == 8);
6443
assert_no_condition(inst);
6444
assert_no_flags(inst);
6446
/* normalize parameters */
6447
param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MF, &spacep, PTYPE_I);
6449
/* set up a call to the write dword/qword handler */
6450
if (inst->size == 4)
6451
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
6452
else if (inst->size == 8)
6453
emit_mov_m64_p64(drcbe, &dst, MBD(REG_ESP, 8), &srcp); // mov [esp+8],srcp
6454
emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp
6455
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacep.value]); // mov [esp],space
6456
if (inst->size == 4)
6457
emit_call(&dst, (x86code *)drcbe->accessors[spacep.value].write_dword); // call write_dword
6458
else if (inst->size == 8)
6459
emit_call(&dst, (x86code *)drcbe->accessors[spacep.value].write_qword); // call write_qword
6465
/*-------------------------------------------------
6466
op_fmov - process a FMOV opcode
6467
-------------------------------------------------*/
6469
static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6471
drcuml_parameter dstp, srcp;
5488
emit_jcc_short_link(dst, x86emit::COND_NZ, skip); // jnz skip
5489
emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
5490
emit_bsr_r32_r32(dst, dstreg, REG_EDX); // bsr dstreg,edx
5491
emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
5492
emit_add_r32_imm(dst, REG_ECX, 32); // add ecx,32
5493
track_resolve_link(dst, skip); // skip:
5494
emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
5495
emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31
5496
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
5501
//-------------------------------------------------
5502
// op_bswap - process a BSWAP opcode
5503
//-------------------------------------------------
5505
void drcbe_x86::op_bswap(x86code *&dst, const instruction &inst)
5507
// validate instruction
5508
assert(inst.size() == 4 || inst.size() == 8);
5509
assert_no_condition(inst);
5510
assert_flags(inst, FLAG_Z | FLAG_S);
5512
// normalize parameters
5513
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5514
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
5516
// pick a target register for the general case
5517
int dstreg = dstp.select_register(REG_EAX);
5520
if (inst.size() == 4)
5522
emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
5523
emit_bswap_r32(dst, dstreg); // bswap dstreg
5524
if (inst.flags() != 0)
5525
emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
5526
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5530
else if (inst.size() == 8)
5532
emit_mov_r64_p64(dst, REG_EDX, dstreg, srcp); // mov dstreg:edx,srcp
5533
emit_bswap_r32(dst, dstreg); // bswap dstreg
5534
emit_bswap_r32(dst, REG_EDX); // bswap edx
5535
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
5536
if (inst.flags() == FLAG_Z)
5537
emit_or_r32_r32(dst, REG_EDX, dstreg); // or edx,eax
5538
else if (inst.flags() == FLAG_S)
5539
emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
5542
emit_movzx_r32_r16(dst, REG_ECX, dstreg); // movzx ecx,dstreg
5543
emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
5544
emit_mov_r32_r32(dst, REG_ECX, dstreg); // mov ecx,dstreg
5545
emit_shr_r32_imm(dst, REG_ECX, 16); // shr ecx,16
5546
emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
5552
//-------------------------------------------------
5553
// op_shl - process a SHL opcode
5554
//-------------------------------------------------
5556
void drcbe_x86::op_shl(x86code *&dst, const instruction &inst)
5558
// validate instruction
5559
assert(inst.size() == 4 || inst.size() == 8);
5560
assert_no_condition(inst);
5561
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5563
// normalize parameters
5564
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5565
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5566
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5568
// pick a target register for the general case
5569
int dstreg = dstp.select_register(REG_EAX, src2p);
5572
if (inst.size() == 4)
5574
// dstp == src1p in memory
5575
if (dstp.is_memory() && dstp == src1p)
5576
emit_shl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p
5581
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5582
emit_shl_r32_p32(dst, dstreg, src2p, inst); // shl dstreg,src2p
5583
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5588
else if (inst.size() == 8)
5591
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5592
emit_shl_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // shl dstreg:dstp,src2p
5593
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5598
//-------------------------------------------------
5599
// op_shr - process a SHR opcode
5600
//-------------------------------------------------
5602
void drcbe_x86::op_shr(x86code *&dst, const instruction &inst)
5604
// validate instruction
5605
assert(inst.size() == 4 || inst.size() == 8);
5606
assert_no_condition(inst);
5607
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5609
// normalize parameters
5610
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5611
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5612
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5614
// pick a target register for the general case
5615
int dstreg = dstp.select_register(REG_EAX, src2p);
5618
if (inst.size() == 4)
5620
// dstp == src1p in memory
5621
if (dstp.is_memory() && dstp == src1p)
5622
emit_shr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p
5627
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5628
emit_shr_r32_p32(dst, dstreg, src2p, inst); // shr dstreg,src2p
5629
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5634
else if (inst.size() == 8)
5637
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5638
emit_shr_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // shr dstreg:dstp,src2p
5639
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5644
//-------------------------------------------------
5645
// op_sar - process a SAR opcode
5646
//-------------------------------------------------
5648
void drcbe_x86::op_sar(x86code *&dst, const instruction &inst)
5650
// validate instruction
5651
assert(inst.size() == 4 || inst.size() == 8);
5652
assert_no_condition(inst);
5653
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5655
// normalize parameters
5656
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5657
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5658
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5660
// pick a target register for the general case
5661
int dstreg = dstp.select_register(REG_EAX, src2p);
5664
if (inst.size() == 4)
5666
// dstp == src1p in memory
5667
if (dstp.is_memory() && dstp == src1p)
5668
emit_sar_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p
5673
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5674
emit_sar_r32_p32(dst, dstreg, src2p, inst); // sar dstreg,src2p
5675
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5680
else if (inst.size() == 8)
5683
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5684
emit_sar_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sar dstreg:dstp,src2p
5685
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5690
//-------------------------------------------------
5691
// op_rol - process a rol opcode
5692
//-------------------------------------------------
5694
void drcbe_x86::op_rol(x86code *&dst, const instruction &inst)
5696
// validate instruction
5697
assert(inst.size() == 4 || inst.size() == 8);
5698
assert_no_condition(inst);
5699
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5701
// normalize parameters
5702
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5703
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5704
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5706
// pick a target register for the general case
5707
int dstreg = dstp.select_register(REG_EAX, src2p);
5710
if (inst.size() == 4)
5712
// dstp == src1p in memory
5713
if (dstp.is_memory() && dstp == src1p)
5714
emit_rol_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p
5719
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5720
emit_rol_r32_p32(dst, dstreg, src2p, inst); // rol dstreg,src2p
5721
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5726
else if (inst.size() == 8)
5729
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5730
emit_rol_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rol dstreg:dstp,src2p
5731
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5736
//-------------------------------------------------
5737
// op_ror - process a ROR opcode
5738
//-------------------------------------------------
5740
void drcbe_x86::op_ror(x86code *&dst, const instruction &inst)
5742
// validate instruction
5743
assert(inst.size() == 4 || inst.size() == 8);
5744
assert_no_condition(inst);
5745
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5747
// normalize parameters
5748
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5749
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5750
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5752
// pick a target register for the general case
5753
int dstreg = dstp.select_register(REG_EAX, src2p);
5756
if (inst.size() == 4)
5758
// dstp == src1p in memory
5759
if (dstp.is_memory() && dstp == src1p)
5760
emit_ror_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p
5765
emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
5766
emit_ror_r32_p32(dst, dstreg, src2p, inst); // ror dstreg,src2p
5767
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5772
else if (inst.size() == 8)
5775
emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5776
emit_ror_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // ror dstreg:dstp,src2p
5777
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5782
//-------------------------------------------------
5783
// op_rolc - process a ROLC opcode
5784
//-------------------------------------------------
5786
void drcbe_x86::op_rolc(x86code *&dst, const instruction &inst)
5788
// validate instruction
5789
assert(inst.size() == 4 || inst.size() == 8);
5790
assert_no_condition(inst);
5791
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5793
// normalize parameters
5794
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5795
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5796
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5798
// pick a target register for the general case
5799
int dstreg = dstp.select_register(REG_EAX, src2p);
5802
if (inst.size() == 4)
5804
// dstp == src1p in memory
5805
if (dstp.is_memory() && dstp == src1p)
5806
emit_rcl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p
5811
emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
5812
emit_rcl_r32_p32(dst, dstreg, src2p, inst); // rcl dstreg,src2p
5813
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5818
else if (inst.size() == 8)
5821
emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5822
emit_rcl_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rcl dstreg:dstp,src2p
5823
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5828
//-------------------------------------------------
5829
// op_rorc - process a RORC opcode
5830
//-------------------------------------------------
5832
void drcbe_x86::op_rorc(x86code *&dst, const instruction &inst)
5834
// validate instruction
5835
assert(inst.size() == 4 || inst.size() == 8);
5836
assert_no_condition(inst);
5837
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
5839
// normalize parameters
5840
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
5841
be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
5842
be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
5844
// pick a target register for the general case
5845
int dstreg = dstp.select_register(REG_EAX, src2p);
5848
if (inst.size() == 4)
5850
// dstp == src1p in memory
5851
if (dstp.is_memory() && dstp == src1p)
5852
emit_rcr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p
5857
emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
5858
emit_rcr_r32_p32(dst, dstreg, src2p, inst); // rcr dstreg,src2p
5859
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
5864
else if (inst.size() == 8)
5867
emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
5868
emit_rcr_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rcr dstreg:dstp,src2p
5869
emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
5875
//**************************************************************************
5876
// FLOATING POINT OPERATIONS
5877
//**************************************************************************
5879
//-------------------------------------------------
5880
// op_fload - process a FLOAD opcode
5881
//-------------------------------------------------
5883
void drcbe_x86::op_fload(x86code *&dst, const instruction &inst)
5885
// validate instruction
5886
assert(inst.size() == 4 || inst.size() == 8);
5887
assert_no_condition(inst);
5888
assert_no_flags(inst);
5890
// normalize parameters
5891
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
5892
be_parameter basep(*this, inst.param(1), PTYPE_M);
5893
be_parameter indp(*this, inst.param(2), PTYPE_MRI);
5896
if (indp.is_immediate())
5898
emit_mov_r32_m32(dst, REG_EAX, MABS(basep.memory(4*indp.immediate()))); // mov eax,[basep + 4*indp]
5899
if (inst.size() == 8)
5900
emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(4 + 4*indp.immediate()))); // mov edx,[basep + 4*indp + 4]
5906
int indreg = indp.select_register(REG_ECX);
5907
emit_mov_r32_p32(dst, indreg, indp);
5908
emit_mov_r32_m32(dst, REG_EAX, MABSI(basep.memory(), indreg, 4)); // mov eax,[basep + 4*indp]
5909
if (inst.size() == 8)
5910
emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, 4)); // mov edx,[basep + 4*indp + 4]
5914
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
5915
if (inst.size() == 8)
5916
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp + 4],edx
5920
//-------------------------------------------------
5921
// op_fstore - process a FSTORE opcode
5922
//-------------------------------------------------
5924
void drcbe_x86::op_fstore(x86code *&dst, const instruction &inst)
5926
// validate instruction
5927
assert(inst.size() == 4 || inst.size() == 8);
5928
assert_no_condition(inst);
5929
assert_no_flags(inst);
5931
// normalize parameters
5932
be_parameter basep(*this, inst.param(0), PTYPE_M);
5933
be_parameter indp(*this, inst.param(1), PTYPE_MRI);
5934
be_parameter srcp(*this, inst.param(2), PTYPE_MF);
5937
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
5938
if (inst.size() == 8)
5939
emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp + 4]
5942
if (indp.is_immediate())
5944
emit_mov_m32_r32(dst, MABS(basep.memory(4*indp.immediate())), REG_EAX); // mov [basep + 4*indp],eax
5945
if (inst.size() == 8)
5946
emit_mov_m32_r32(dst, MABS(basep.memory(4 + 4*indp.immediate())), REG_EDX); // mov [basep + 4*indp + 4],edx
5952
int indreg = indp.select_register(REG_ECX);
5953
emit_mov_r32_p32(dst, indreg, indp);
5954
emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, 4), REG_EAX); // mov [basep + 4*indp],eax
5955
if (inst.size() == 8)
5956
emit_mov_m32_r32(dst, MABSI(basep.memory(4), indreg, 4), REG_EDX); // mov [basep + 4*indp + 4],edx
5961
//-------------------------------------------------
5962
// op_fread - process a FREAD opcode
5963
//-------------------------------------------------
5965
void drcbe_x86::op_fread(x86code *&dst, const instruction &inst)
5967
// validate instruction
5968
assert(inst.size() == 4 || inst.size() == 8);
5969
assert_no_condition(inst);
5970
assert_no_flags(inst);
5972
// normalize parameters
5973
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
5974
be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
5975
const parameter &spacep = inst.param(2);
5976
assert(spacep.is_size_space());
5977
assert((1 << spacep.size()) == inst.size());
5979
// set up a call to the read dword/qword handler
5980
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
5981
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacep.space()]); // mov [esp],space
5982
if (inst.size() == 4)
5983
emit_call(dst, (x86code *)m_accessors[spacep.space()].read_dword); // call read_dword
5984
else if (inst.size() == 8)
5985
emit_call(dst, (x86code *)m_accessors[spacep.space()].read_qword); // call read_qword
5988
if (inst.size() == 4)
5989
emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
5990
else if (inst.size() == 8)
5991
emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
5995
//-------------------------------------------------
5996
// op_fwrite - process a FWRITE opcode
5997
//-------------------------------------------------
5999
void drcbe_x86::op_fwrite(x86code *&dst, const instruction &inst)
6001
// validate instruction
6002
assert(inst.size() == 4 || inst.size() == 8);
6003
assert_no_condition(inst);
6004
assert_no_flags(inst);
6006
// normalize parameters
6007
be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
6008
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6009
const parameter &spacep = inst.param(2);
6010
assert(spacep.is_size_space());
6011
assert((1 << spacep.size()) == inst.size());
6013
// set up a call to the write dword/qword handler
6014
if (inst.size() == 4)
6015
emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
6016
else if (inst.size() == 8)
6017
emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
6018
emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
6019
emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacep.space()]); // mov [esp],space
6020
if (inst.size() == 4)
6021
emit_call(dst, (x86code *)m_accessors[spacep.space()].write_dword); // call write_dword
6022
else if (inst.size() == 8)
6023
emit_call(dst, (x86code *)m_accessors[spacep.space()].write_qword); // call write_qword
6027
//-------------------------------------------------
6028
// op_fmov - process a FMOV opcode
6029
//-------------------------------------------------
6031
void drcbe_x86::op_fmov(x86code *&dst, const instruction &inst)
6033
// validate instruction
6034
assert(inst.size() == 4 || inst.size() == 8);
6035
assert_any_condition(inst);
6036
assert_no_flags(inst);
6038
// normalize parameters
6039
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6040
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6042
// always start with a jmp
6472
6043
emit_link skip = { 0 };
6474
/* validate instruction */
6475
assert(inst->size == 4 || inst->size == 8);
6476
assert_any_condition(inst);
6477
assert_no_flags(inst);
6479
/* normalize parameters */
6480
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6482
/* always start with a jmp */
6483
if (inst->condition != DRCUML_COND_ALWAYS)
6484
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condition), &skip); // jcc skip
6487
emit_mov_r32_m32(&dst, REG_EAX, MABS(srcp.value)); // mov eax,[srcp]
6488
if (inst->size == 8)
6489
emit_mov_r32_m32(&dst, REG_EDX, MABS(srcp.value + 4)); // mov edx,[srcp + 4]
6490
emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
6491
if (inst->size == 8)
6492
emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp + 4],edx
6494
/* resolve the jump */
6044
if (inst.condition() != uml::COND_ALWAYS)
6045
emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
6048
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
6049
if (inst.size() == 8)
6050
emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp + 4]
6051
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
6052
if (inst.size() == 8)
6053
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp + 4],edx
6495
6056
if (skip.target != NULL)
6496
track_resolve_link(drcbe, &dst, &skip); // skip:
6501
/*-------------------------------------------------
6502
op_ftoint - process a FTOINT opcode
6503
-------------------------------------------------*/
6505
static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6507
drcuml_parameter dstp, srcp, sizep, roundp;
6509
/* validate instruction */
6510
assert(inst->size == 4 || inst->size == 8);
6511
assert_no_condition(inst);
6512
assert_no_flags(inst);
6514
/* normalize parameters */
6515
param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF, &sizep, PTYPE_I, &roundp, PTYPE_I);
6517
/* set rounding mode if necessary */
6518
if (roundp.value != DRCUML_FMOD_DEFAULT && (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC))
6520
emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
6521
emit_fldcw_m16(&dst, MABS(&fp_control[roundp.value])); // fldcw fpcontrol[roundp]
6525
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6527
/* 4-byte integer case */
6528
if (sizep.value == DRCUML_SIZE_DWORD)
6530
if (dstp.type == DRCUML_PTYPE_MEMORY)
6532
if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6533
emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
6535
emit_fisttp_m32(&dst, MABS(dstp.value)); // fisttp [dstp]
6537
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
6539
if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6540
emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
6542
emit_fisttp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
6543
emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
6547
/* 8-byte integer case */
6548
else if (sizep.value == DRCUML_SIZE_QWORD)
6550
if (dstp.type == DRCUML_PTYPE_MEMORY)
6552
if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6553
emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
6555
emit_fisttp_m64(&dst, MABS(dstp.value)); // fisttp [dstp]
6557
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
6559
if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6560
emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
6562
emit_fisttp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
6563
emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
6567
/* restore control word and proceed */
6568
if (roundp.value != DRCUML_FMOD_DEFAULT && (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC))
6569
emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
6575
/*-------------------------------------------------
6576
op_ffrint - process a FFRINT opcode
6577
-------------------------------------------------*/
6579
static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6581
drcuml_parameter dstp, srcp, sizep;
6583
/* validate instruction */
6584
assert(inst->size == 4 || inst->size == 8);
6585
assert_no_condition(inst);
6586
assert_no_flags(inst);
6588
/* normalize parameters */
6589
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
6591
/* 4-byte integer case */
6592
if (sizep.value == DRCUML_SIZE_DWORD)
6594
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
6596
emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
6597
emit_fild_m32(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
6599
else if (srcp.type == DRCUML_PTYPE_MEMORY)
6600
emit_fild_m32(&dst, MABS(srcp.value)); // fild [srcp]
6601
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
6603
emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
6604
emit_fild_m32(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
6608
/* 8-bit integer case */
6609
else if (sizep.value == DRCUML_SIZE_QWORD)
6611
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
6613
emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
6614
emit_mov_m32_imm(&dst, MABS((UINT8 *)&drcbe->fptemp + 4), srcp.value); // mov [fptemp+4],srcp
6615
emit_fild_m64(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
6617
else if (srcp.type == DRCUML_PTYPE_MEMORY)
6618
emit_fild_m64(&dst, MABS(srcp.value)); // fild [srcp]
6619
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
6621
emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
6622
emit_fild_m64(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
6626
/* store the result and be done */
6627
emit_fstp_p(&dst, inst->size, &dstp); // fstp [dstp]
6632
/*-------------------------------------------------
6633
op_ffrflt - process a FFRFLT opcode
6634
-------------------------------------------------*/
6636
static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6638
drcuml_parameter dstp, srcp, sizep;
6640
/* validate instruction */
6641
assert(inst->size == 4 || inst->size == 8);
6642
assert_no_condition(inst);
6643
assert_no_flags(inst);
6645
/* normalize parameters */
6646
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF, &sizep, PTYPE_I);
6649
if (sizep.value == DRCUML_SIZE_DWORD)
6650
emit_fld_m32(&dst, MABS(srcp.value)); // fld [srcp]
6651
else if (sizep.value == DRCUML_SIZE_QWORD)
6652
emit_fld_m64(&dst, MABS(srcp.value)); // fld [srcp]
6653
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6659
/*-------------------------------------------------
6660
op_frnds - process a FRNDS opcode
6661
-------------------------------------------------*/
6663
static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6665
drcuml_parameter dstp, srcp;
6667
/* validate instruction */
6668
assert(inst->size == 8);
6669
assert_no_condition(inst);
6670
assert_no_flags(inst);
6672
/* normalize parameters */
6673
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6676
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6677
emit_fstp_m32(&dst, MABS(&drcbe->fptemp)); // fstp [fptemp]
6678
emit_fld_m32(&dst, MABS(&drcbe->fptemp)); // fld [fptemp]
6679
emit_fstp_p(&dst, inst->size, &dstp); // fstp [dstp]
6684
/*-------------------------------------------------
6685
op_fadd - process a FADD opcode
6686
-------------------------------------------------*/
6688
static x86code *op_fadd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6690
drcuml_parameter dstp, src1p, src2p;
6692
/* validate instruction */
6693
assert(inst->size == 4 || inst->size == 8);
6694
assert_no_condition(inst);
6695
assert_no_flags(inst);
6697
/* normalize parameters */
6698
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6701
emit_fld_p(&dst, inst->size, &src1p); // fld src1p
6702
emit_fld_p(&dst, inst->size, &src2p); // fld src2p
6703
emit_faddp(&dst); // faddp
6704
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6710
/*-------------------------------------------------
6711
op_fsub - process a FSUB opcode
6712
-------------------------------------------------*/
6714
static x86code *op_fsub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6716
drcuml_parameter dstp, src1p, src2p;
6718
/* validate instruction */
6719
assert(inst->size == 4 || inst->size == 8);
6720
assert_no_condition(inst);
6721
assert_no_flags(inst);
6723
/* normalize parameters */
6724
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6727
emit_fld_p(&dst, inst->size, &src1p); // fld src1p
6728
emit_fld_p(&dst, inst->size, &src2p); // fld src2p
6729
emit_fsubp(&dst); // fsubp
6730
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6736
/*-------------------------------------------------
6737
op_fcmp - process a FCMP opcode
6738
-------------------------------------------------*/
6740
static x86code *op_fcmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6742
drcuml_parameter src1p, src2p;
6744
/* validate instruction */
6745
assert(inst->size == 4 || inst->size == 8);
6746
assert_no_condition(inst);
6747
assert_flags(inst, DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_U);
6749
/* normalize parameters */
6750
param_normalize_2(drcbe, inst, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6753
emit_fld_p(&dst, inst->size, &src2p); // fld src2p
6754
emit_fld_p(&dst, inst->size, &src1p); // fld src1p
6755
emit_fcompp(&dst); // fcompp
6756
emit_fstsw_ax(&dst); // fnstsw ax
6757
emit_sahf(&dst); // sahf
6763
/*-------------------------------------------------
6764
op_fmul - process a FMUL opcode
6765
-------------------------------------------------*/
6767
static x86code *op_fmul(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6769
drcuml_parameter dstp, src1p, src2p;
6771
/* validate instruction */
6772
assert(inst->size == 4 || inst->size == 8);
6773
assert_no_condition(inst);
6774
assert_no_flags(inst);
6776
/* normalize parameters */
6777
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6780
emit_fld_p(&dst, inst->size, &src1p); // fld src1p
6781
emit_fld_p(&dst, inst->size, &src2p); // fld src2p
6782
emit_fmulp(&dst); // fmulp
6783
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6789
/*-------------------------------------------------
6790
op_fdiv - process a FDIV opcode
6791
-------------------------------------------------*/
6793
static x86code *op_fdiv(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6795
drcuml_parameter dstp, src1p, src2p;
6797
/* validate instruction */
6798
assert(inst->size == 4 || inst->size == 8);
6799
assert_no_condition(inst);
6800
assert_no_flags(inst);
6802
/* normalize parameters */
6803
param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6806
emit_fld_p(&dst, inst->size, &src1p); // fld src1p
6807
emit_fld_p(&dst, inst->size, &src2p); // fld src2p
6808
emit_fdivp(&dst); // fdivp
6809
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6815
/*-------------------------------------------------
6816
op_fneg - process a FNEG opcode
6817
-------------------------------------------------*/
6819
static x86code *op_fneg(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6821
drcuml_parameter dstp, srcp;
6823
/* validate instruction */
6824
assert(inst->size == 4 || inst->size == 8);
6825
assert_no_condition(inst);
6826
assert_no_flags(inst);
6828
/* normalize parameters */
6829
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6832
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6833
emit_fchs(&dst); // fchs
6834
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6840
/*-------------------------------------------------
6841
op_fabs - process a FABS opcode
6842
-------------------------------------------------*/
6844
static x86code *op_fabs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6846
drcuml_parameter dstp, srcp;
6848
/* validate instruction */
6849
assert(inst->size == 4 || inst->size == 8);
6850
assert_no_condition(inst);
6851
assert_no_flags(inst);
6853
/* normalize parameters */
6854
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6857
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6858
emit_fabs(&dst); // fabs
6859
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6865
/*-------------------------------------------------
6866
op_fsqrt - process a FSQRT opcode
6867
-------------------------------------------------*/
6869
static x86code *op_fsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6871
drcuml_parameter dstp, srcp;
6873
/* validate instruction */
6874
assert(inst->size == 4 || inst->size == 8);
6875
assert_no_condition(inst);
6876
assert_no_flags(inst);
6878
/* normalize parameters */
6879
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6882
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6883
emit_fsqrt(&dst); // fsqrt
6884
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6890
/*-------------------------------------------------
6891
op_frecip - process a FRECIP opcode
6892
-------------------------------------------------*/
6894
static x86code *op_frecip(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6896
drcuml_parameter dstp, srcp;
6898
/* validate instruction */
6899
assert(inst->size == 4 || inst->size == 8);
6900
assert_no_condition(inst);
6901
assert_no_flags(inst);
6903
/* normalize parameters */
6904
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6907
emit_fld1(&dst); // fld1
6908
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6909
emit_fdivp(&dst); // fdivp
6910
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6916
/*-------------------------------------------------
6917
op_frsqrt - process a FRSQRT opcode
6918
-------------------------------------------------*/
6920
static x86code *op_frsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6922
drcuml_parameter dstp, srcp;
6924
/* validate instruction */
6925
assert(inst->size == 4 || inst->size == 8);
6926
assert_no_condition(inst);
6927
assert_no_flags(inst);
6929
/* normalize parameters */
6930
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6933
emit_fld1(&dst); // fld1
6934
emit_fld_p(&dst, inst->size, &srcp); // fld srcp
6935
emit_fsqrt(&dst); // fsqrt
6936
emit_fdivp(&dst); // fdivp
6937
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
6944
/***************************************************************************
6945
MISCELLAENOUS FUNCTIONS
6946
***************************************************************************/
6948
/*-------------------------------------------------
6949
dmulu - perform a double-wide unsigned multiply
6950
-------------------------------------------------*/
6952
static int dmulu(UINT64 *dstlo, UINT64 *dsthi, UINT64 src1, UINT64 src2, int flags)
6954
UINT64 lo, hi, prevlo;
6957
/* shortcut if we don't care about the high bits or the flags */
6958
if (dstlo == dsthi && flags == 0)
6960
*dstlo = src1 * src2;
6057
track_resolve_link(dst, skip); // skip:
6061
//-------------------------------------------------
6062
// op_ftoint - process a FTOINT opcode
6063
//-------------------------------------------------
6065
void drcbe_x86::op_ftoint(x86code *&dst, const instruction &inst)
6067
// validate instruction
6068
assert(inst.size() == 4 || inst.size() == 8);
6069
assert_no_condition(inst);
6070
assert_no_flags(inst);
6072
// normalize parameters
6073
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
6074
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6075
const parameter &sizep = inst.param(2);
6076
assert(sizep.is_size());
6077
const parameter &roundp = inst.param(3);
6078
assert(roundp.is_rounding());
6080
// set rounding mode if necessary
6081
if (roundp.rounding() != ROUND_DEFAULT && (!m_sse3 || roundp.rounding() != ROUND_TRUNC))
6083
emit_fstcw_m16(dst, MABS(&m_fmodesave)); // fstcw [fmodesave]
6084
emit_fldcw_m16(dst, MABS(&fp_control[roundp.rounding()])); // fldcw fpcontrol[roundp]
6088
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6090
// 4-byte integer case
6091
if (sizep.size() == SIZE_DWORD)
6093
if (dstp.is_memory())
6095
if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
6096
emit_fistp_m32(dst, MABS(dstp.memory())); // fistp [dstp]
6098
emit_fisttp_m32(dst, MABS(dstp.memory())); // fisttp [dstp]
6100
else if (dstp.is_int_register())
6102
if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
6103
emit_fistp_m32(dst, MABS(m_reglo[dstp.ireg()])); // fistp reglo[dstp]
6105
emit_fisttp_m32(dst, MABS(m_reglo[dstp.ireg()])); // fisttp reglo[dstp]
6106
emit_mov_r32_m32(dst, dstp.ireg(), MABS(m_reglo[dstp.ireg()])); // mov dstp,reglo[dstp]
6110
// 8-byte integer case
6111
else if (sizep.size() == SIZE_QWORD)
6113
if (dstp.is_memory())
6115
if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
6116
emit_fistp_m64(dst, MABS(dstp.memory())); // fistp [dstp]
6118
emit_fisttp_m64(dst, MABS(dstp.memory())); // fisttp [dstp]
6120
else if (dstp.is_int_register())
6122
if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
6123
emit_fistp_m64(dst, MABS(m_reglo[dstp.ireg()])); // fistp reglo[dstp]
6125
emit_fisttp_m64(dst, MABS(m_reglo[dstp.ireg()])); // fisttp reglo[dstp]
6126
emit_mov_r32_m32(dst, dstp.ireg(), MABS(m_reglo[dstp.ireg()])); // mov dstp,reglo[dstp]
6130
// restore control word and proceed
6131
if (roundp.rounding() != ROUND_DEFAULT && (!m_sse3 || roundp.rounding() != ROUND_TRUNC))
6132
emit_fldcw_m16(dst, MABS(&m_fmodesave)); // fldcw [fmodesave]
6136
//-------------------------------------------------
6137
// op_ffrint - process a FFRINT opcode
6138
//-------------------------------------------------
6140
void drcbe_x86::op_ffrint(x86code *&dst, const instruction &inst)
6142
// validate instruction
6143
assert(inst.size() == 4 || inst.size() == 8);
6144
assert_no_condition(inst);
6145
assert_no_flags(inst);
6147
// normalize parameters
6148
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6149
be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
6150
const parameter &sizep = inst.param(2);
6151
assert(sizep.is_size());
6153
// 4-byte integer case
6154
if (sizep.size() == SIZE_DWORD)
6156
if (srcp.is_immediate())
6158
emit_mov_m32_imm(dst, MABS(&m_fptemp), srcp.immediate()); // mov [fptemp],srcp
6159
emit_fild_m32(dst, MABS(&m_fptemp)); // fild [fptemp]
6161
else if (srcp.is_memory())
6162
emit_fild_m32(dst, MABS(srcp.memory())); // fild [srcp]
6163
else if (srcp.is_int_register())
6165
emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov reglo[srcp],srcp
6166
emit_fild_m32(dst, MABS(m_reglo[srcp.ireg()])); // fild reglo[srcp]
6170
// 8-bit integer case
6171
else if (sizep.size() == SIZE_QWORD)
6173
if (srcp.is_immediate())
6175
emit_mov_m32_imm(dst, MABS(&m_fptemp), srcp.immediate()); // mov [fptemp],srcp
6176
emit_mov_m32_imm(dst, MABS((UINT8 *)&m_fptemp + 4), srcp.immediate()); // mov [fptemp+4],srcp
6177
emit_fild_m64(dst, MABS(&m_fptemp)); // fild [fptemp]
6179
else if (srcp.is_memory())
6180
emit_fild_m64(dst, MABS(srcp.memory())); // fild [srcp]
6181
else if (srcp.is_int_register())
6183
emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov reglo[srcp],srcp
6184
emit_fild_m64(dst, MABS(m_reglo[srcp.ireg()])); // fild reglo[srcp]
6188
// store the result and be done
6189
emit_fstp_p(dst, inst.size(), dstp); // fstp [dstp]
6193
//-------------------------------------------------
6194
// op_ffrflt - process a FFRFLT opcode
6195
//-------------------------------------------------
6197
void drcbe_x86::op_ffrflt(x86code *&dst, const instruction &inst)
6199
// validate instruction
6200
assert(inst.size() == 4 || inst.size() == 8);
6201
assert_no_condition(inst);
6202
assert_no_flags(inst);
6204
// normalize parameters
6205
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6206
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6207
const parameter &sizep = inst.param(2);
6208
assert(sizep.is_size());
6211
if (sizep.size() == SIZE_DWORD)
6212
emit_fld_m32(dst, MABS(srcp.memory())); // fld [srcp]
6213
else if (sizep.size() == SIZE_QWORD)
6214
emit_fld_m64(dst, MABS(srcp.memory())); // fld [srcp]
6215
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6219
//-------------------------------------------------
6220
// op_frnds - process a FRNDS opcode
6221
//-------------------------------------------------
6223
void drcbe_x86::op_frnds(x86code *&dst, const instruction &inst)
6225
// validate instruction
6226
assert(inst.size() == 8);
6227
assert_no_condition(inst);
6228
assert_no_flags(inst);
6230
// normalize parameters
6231
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6232
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6235
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6236
emit_fstp_m32(dst, MABS(&m_fptemp)); // fstp [fptemp]
6237
emit_fld_m32(dst, MABS(&m_fptemp)); // fld [fptemp]
6238
emit_fstp_p(dst, inst.size(), dstp); // fstp [dstp]
6242
//-------------------------------------------------
6243
// op_fadd - process a FADD opcode
6244
//-------------------------------------------------
6246
void drcbe_x86::op_fadd(x86code *&dst, const instruction &inst)
6248
// validate instruction
6249
assert(inst.size() == 4 || inst.size() == 8);
6250
assert_no_condition(inst);
6251
assert_no_flags(inst);
6253
// normalize parameters
6254
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6255
be_parameter src1p(*this, inst.param(1), PTYPE_MF);
6256
be_parameter src2p(*this, inst.param(2), PTYPE_MF);
6257
normalize_commutative(src1p, src2p);
6260
emit_fld_p(dst, inst.size(), src1p); // fld src1p
6261
emit_fld_p(dst, inst.size(), src2p); // fld src2p
6262
emit_faddp(dst); // faddp
6263
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6267
//-------------------------------------------------
6268
// op_fsub - process a FSUB opcode
6269
//-------------------------------------------------
6271
void drcbe_x86::op_fsub(x86code *&dst, const instruction &inst)
6273
// validate instruction
6274
assert(inst.size() == 4 || inst.size() == 8);
6275
assert_no_condition(inst);
6276
assert_no_flags(inst);
6278
// normalize parameters
6279
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6280
be_parameter src1p(*this, inst.param(1), PTYPE_MF);
6281
be_parameter src2p(*this, inst.param(2), PTYPE_MF);
6284
emit_fld_p(dst, inst.size(), src1p); // fld src1p
6285
emit_fld_p(dst, inst.size(), src2p); // fld src2p
6286
emit_fsubp(dst); // fsubp
6287
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6291
//-------------------------------------------------
6292
// op_fcmp - process a FCMP opcode
6293
//-------------------------------------------------
6295
void drcbe_x86::op_fcmp(x86code *&dst, const instruction &inst)
6297
// validate instruction
6298
assert(inst.size() == 4 || inst.size() == 8);
6299
assert_no_condition(inst);
6300
assert_flags(inst, FLAG_C | FLAG_Z | FLAG_U);
6302
// normalize parameters
6303
be_parameter src1p(*this, inst.param(0), PTYPE_MF);
6304
be_parameter src2p(*this, inst.param(1), PTYPE_MF);
6307
emit_fld_p(dst, inst.size(), src2p); // fld src2p
6308
emit_fld_p(dst, inst.size(), src1p); // fld src1p
6309
emit_fcompp(dst); // fcompp
6310
emit_fstsw_ax(dst); // fnstsw ax
6311
emit_sahf(dst); // sahf
6315
//-------------------------------------------------
6316
// op_fmul - process a FMUL opcode
6317
//-------------------------------------------------
6319
void drcbe_x86::op_fmul(x86code *&dst, const instruction &inst)
6321
// validate instruction
6322
assert(inst.size() == 4 || inst.size() == 8);
6323
assert_no_condition(inst);
6324
assert_no_flags(inst);
6326
// normalize parameters
6327
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6328
be_parameter src1p(*this, inst.param(1), PTYPE_MF);
6329
be_parameter src2p(*this, inst.param(2), PTYPE_MF);
6330
normalize_commutative(src1p, src2p);
6333
emit_fld_p(dst, inst.size(), src1p); // fld src1p
6334
emit_fld_p(dst, inst.size(), src2p); // fld src2p
6335
emit_fmulp(dst); // fmulp
6336
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6340
//-------------------------------------------------
6341
// op_fdiv - process a FDIV opcode
6342
//-------------------------------------------------
6344
void drcbe_x86::op_fdiv(x86code *&dst, const instruction &inst)
6346
// validate instruction
6347
assert(inst.size() == 4 || inst.size() == 8);
6348
assert_no_condition(inst);
6349
assert_no_flags(inst);
6351
// normalize parameters
6352
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6353
be_parameter src1p(*this, inst.param(1), PTYPE_MF);
6354
be_parameter src2p(*this, inst.param(2), PTYPE_MF);
6357
emit_fld_p(dst, inst.size(), src1p); // fld src1p
6358
emit_fld_p(dst, inst.size(), src2p); // fld src2p
6359
emit_fdivp(dst); // fdivp
6360
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6364
//-------------------------------------------------
6365
// op_fneg - process a FNEG opcode
6366
//-------------------------------------------------
6368
void drcbe_x86::op_fneg(x86code *&dst, const instruction &inst)
6370
// validate instruction
6371
assert(inst.size() == 4 || inst.size() == 8);
6372
assert_no_condition(inst);
6373
assert_no_flags(inst);
6375
// normalize parameters
6376
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6377
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6380
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6381
emit_fchs(dst); // fchs
6382
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6386
//-------------------------------------------------
6387
// op_fabs - process a FABS opcode
6388
//-------------------------------------------------
6390
void drcbe_x86::op_fabs(x86code *&dst, const instruction &inst)
6392
// validate instruction
6393
assert(inst.size() == 4 || inst.size() == 8);
6394
assert_no_condition(inst);
6395
assert_no_flags(inst);
6397
// normalize parameters
6398
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6399
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6402
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6403
emit_fabs(dst); // fabs
6404
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6408
//-------------------------------------------------
6409
// op_fsqrt - process a FSQRT opcode
6410
//-------------------------------------------------
6412
void drcbe_x86::op_fsqrt(x86code *&dst, const instruction &inst)
6414
// validate instruction
6415
assert(inst.size() == 4 || inst.size() == 8);
6416
assert_no_condition(inst);
6417
assert_no_flags(inst);
6419
// normalize parameters
6420
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6421
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6424
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6425
emit_fsqrt(dst); // fsqrt
6426
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6430
//-------------------------------------------------
6431
// op_frecip - process a FRECIP opcode
6432
//-------------------------------------------------
6434
void drcbe_x86::op_frecip(x86code *&dst, const instruction &inst)
6436
// validate instruction
6437
assert(inst.size() == 4 || inst.size() == 8);
6438
assert_no_condition(inst);
6439
assert_no_flags(inst);
6441
// normalize parameters
6442
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6443
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6446
emit_fld1(dst); // fld1
6447
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6448
emit_fdivp(dst); // fdivp
6449
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6453
//-------------------------------------------------
6454
// op_frsqrt - process a FRSQRT opcode
6455
//-------------------------------------------------
6457
void drcbe_x86::op_frsqrt(x86code *&dst, const instruction &inst)
6459
// validate instruction
6460
assert(inst.size() == 4 || inst.size() == 8);
6461
assert_no_condition(inst);
6462
assert_no_flags(inst);
6464
// normalize parameters
6465
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
6466
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
6469
emit_fld1(dst); // fld1
6470
emit_fld_p(dst, inst.size(), srcp); // fld srcp
6471
emit_fsqrt(dst); // fsqrt
6472
emit_fdivp(dst); // fdivp
6473
emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
6478
//**************************************************************************
6479
// MISCELLAENOUS FUNCTIONS
6480
//**************************************************************************
6482
//-------------------------------------------------
6483
// dmulu - perform a double-wide unsigned multiply
6484
//-------------------------------------------------
6486
int drcbe_x86::dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags)
6488
// shortcut if we don't care about the high bits or the flags
6489
if (&dstlo == &dsthi && flags == 0)
6491
dstlo = src1 * src2;
6964
/* fetch source values */
6495
// fetch source values
6967
6498
if (a == 0 || b == 0)
6969
*dsthi = *dstlo = 0;
6970
return DRCUML_FLAG_Z;
6973
/* compute high and low parts first */
6974
lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
6975
hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
6504
// compute high and low parts first
6505
UINT64 lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
6506
UINT64 hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
6977
/* compute middle parts */
6979
temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
6508
// compute middle parts
6510
UINT64 temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
6980
6511
lo += temp << 32;
6981
6512
hi += (temp >> 32) + (lo < prevlo);