~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to src/emu/cpu/drcbex86.c

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Emmanuel Kasper, Félix Arreola Rodríguez, Jordi Mallach
  • Date: 2011-05-11 21:06:50 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110511210650-jizvh8a6x117y9hr
Tags: 0.142-1
[ Emmanuel Kasper ]
* New upstream release
* Set NOWERROR=1 to allow compiling with gcc-4.6
* Remove fix_powerpc_build.patch, as upstream has taken it in this release
* Add gnome-video-arcade front end as a suggested package

[ Félix Arreola Rodríguez ]
* Add kfreebsd-build.patch to quilt series, to fix build on kfreebsd

[ Jordi Mallach ]
* Remove unneeded and bogus addition of --with-quilt to the dh invocation.
* Add Cesare Falco (long time Ubuntu maintainer) to Uploaders, and wrap
  them into multiple lines.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 
5
5
    32-bit x86 back-end for the universal machine language.
6
6
 
 
7
****************************************************************************
 
8
 
7
9
    Copyright Aaron Giles
8
 
    Released for general non-commercial use under the MAME license
9
 
    Visit http://mamedev.org for licensing and usage restrictions.
 
10
    All rights reserved.
 
11
 
 
12
    Redistribution and use in source and binary forms, with or without
 
13
    modification, are permitted provided that the following conditions are
 
14
    met:
 
15
 
 
16
        * Redistributions of source code must retain the above copyright
 
17
          notice, this list of conditions and the following disclaimer.
 
18
        * Redistributions in binary form must reproduce the above copyright
 
19
          notice, this list of conditions and the following disclaimer in
 
20
          the documentation and/or other materials provided with the
 
21
          distribution.
 
22
        * Neither the name 'MAME' nor the names of its contributors may be
 
23
          used to endorse or promote products derived from this software
 
24
          without specific prior written permission.
 
25
 
 
26
    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
 
27
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
28
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
29
    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
 
30
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
31
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
32
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
33
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
34
    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
35
    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
36
    POSSIBILITY OF SUCH DAMAGE.
10
37
 
11
38
****************************************************************************
12
39
 
13
 
    Future improvements/changes:
 
40
   Future improvements/changes:
14
41
 
15
42
    * Optimize to avoid unnecessary reloads
16
43
        - especially EDX for 64-bit operations
82
109
        [esp+44]   - ret
83
110
        [esp+48]   - input parameter (entry handle)
84
111
 
85
 
***************************************************************************/
 
112
**************************************************************************/
86
113
 
87
114
#include "emu.h"
88
115
#include "debugger.h"
89
116
#include "drcuml.h"
90
 
#include "drcbeut.h"
91
 
#include "x86emit.h"
92
 
#include "x86log.h"
93
 
 
94
 
 
95
 
 
96
 
/***************************************************************************
97
 
    DEBUGGING
98
 
***************************************************************************/
 
117
#include "drcbex86.h"
 
118
 
 
119
using namespace uml;
 
120
using namespace x86emit;
 
121
 
 
122
 
 
123
//**************************************************************************
 
124
//  DEBUGGING
 
125
//**************************************************************************
99
126
 
100
127
#define LOG_HASHJMPS            (0)
101
128
 
102
129
 
103
130
 
104
 
/***************************************************************************
105
 
    CONSTANTS
106
 
***************************************************************************/
107
 
 
108
 
#define PTYPE_M                         (1 << DRCUML_PTYPE_MEMORY)
109
 
#define PTYPE_I                         (1 << DRCUML_PTYPE_IMMEDIATE)
110
 
#define PTYPE_R                         (1 << DRCUML_PTYPE_INT_REGISTER)
111
 
#define PTYPE_F                         (1 << DRCUML_PTYPE_FLOAT_REGISTER)
112
 
#define PTYPE_MI                        (PTYPE_M | PTYPE_I)
113
 
#define PTYPE_RI                        (PTYPE_R | PTYPE_I)
114
 
#define PTYPE_MR                        (PTYPE_M | PTYPE_R)
115
 
#define PTYPE_MRI                       (PTYPE_M | PTYPE_R | PTYPE_I)
116
 
#define PTYPE_MF                        (PTYPE_M | PTYPE_F)
117
 
 
118
 
 
119
 
 
120
 
/***************************************************************************
121
 
    MACROS
122
 
***************************************************************************/
123
 
 
124
 
#define X86_CONDITION(condition)                (condition_map[condition - DRCUML_COND_Z])
125
 
#define X86_NOT_CONDITION(condition)    (condition_map[condition - DRCUML_COND_Z] ^ 1)
126
 
 
127
 
#define assert_no_condition(inst)               assert((inst)->condition == DRCUML_COND_ALWAYS)
128
 
#define assert_any_condition(inst)              assert((inst)->condition == DRCUML_COND_ALWAYS || ((inst)->condition >= DRCUML_COND_Z && (inst)->condition < DRCUML_COND_MAX))
129
 
#define assert_no_flags(inst)                   assert((inst)->flags == 0)
130
 
#define assert_flags(inst, valid)               assert(((inst)->flags & ~(valid)) == 0)
131
 
 
132
 
 
133
 
 
134
 
/***************************************************************************
135
 
    TYPE DEFINITIONS
136
 
***************************************************************************/
137
 
 
138
 
/* entry point */
139
 
typedef UINT32 (*x86_entry_point_func)(x86code *entry);
140
 
 
141
 
/* opcode handler */
142
 
typedef x86code *(*opcode_generate_func)(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
143
 
 
144
 
 
145
 
/* opcode table entry */
146
 
typedef struct _opcode_table_entry opcode_table_entry;
147
 
struct _opcode_table_entry
148
 
{
149
 
        drcuml_opcode                   opcode;                                 /* opcode in question */
150
 
        opcode_generate_func    func;                                   /* function pointer to the work */
151
 
};
152
 
 
153
 
 
154
 
/* internal backend-specific state */
155
 
struct _drcbe_state
156
 
{
157
 
        device_t *      device;                                 /* CPU device we are associated with */
158
 
        drcuml_state *                  drcuml;                                 /* pointer back to our owner */
159
 
        drccache *                              cache;                                  /* pointer to the cache */
160
 
        drcuml_machine_state    state;                                  /* state of the machine */
161
 
        drchash_state *                 hash;                                   /* hash table state */
162
 
        drcmap_state *                  map;                                    /* code map */
163
 
        drclabel_list *                 labels;                 /* label list */
164
 
 
165
 
        x86_entry_point_func    entry;                                  /* entry point */
166
 
        x86code *                               exit;                                   /* exit point */
167
 
        x86code *                               nocode;                                 /* nocode handler */
168
 
        x86code *                               save;                                   /* save handler */
169
 
        x86code *                               restore;                                /* restore handler */
170
 
 
171
 
        UINT32 *                                reglo[REG_MAX];                 /* pointer to low part of data for each register */
172
 
        UINT32 *                                reghi[REG_MAX];                 /* pointer to high part of data for each register */
173
 
        UINT8                                   last_lower_reg;                 /* last register we stored a lower from */
174
 
        x86code *                               last_lower_pc;                  /* PC after instruction where we last stored a lower register */
175
 
        UINT32 *                                last_lower_addr;                /* address where we last stored an lower register */
176
 
        UINT8                                   last_upper_reg;                 /* last register we stored an upper from */
177
 
        x86code *                               last_upper_pc;                  /* PC after instruction where we last stored an upper register */
178
 
        UINT32 *                                last_upper_addr;                /* address where we last stored an upper register */
179
 
        double                                  fptemp;                                 /* temporary storage for floating point */
180
 
 
181
 
        data_accessors                  accessors[ADDRESS_SPACES];      /* memory accessors */
182
 
        address_space * space[ADDRESS_SPACES];  /* address spaces */
183
 
 
184
 
        UINT8                                   sse3;                                   /* do we have SSE3 support? */
185
 
        UINT16                                  fpumode;                                /* saved FPU mode */
186
 
        UINT16                                  fmodesave;                              /* temporary location for saving */
187
 
 
188
 
        void *                                  stacksave;                              /* saved stack pointer */
189
 
        void *                                  hashstacksave;                  /* saved stack pointer for hashjmp */
190
 
        UINT64                                  reslo;                                  /* extended low result */
191
 
        UINT64                                  reshi;                                  /* extended high result */
192
 
 
193
 
        x86log_context *                log;                                    /* logging */
194
 
        UINT8                                   logged_common;                  /* logged common code already? */
195
 
};
196
 
 
197
 
 
198
 
 
199
 
/***************************************************************************
200
 
    FUNCTION PROTOTYPES
201
 
***************************************************************************/
202
 
 
203
 
/* primary back-end callbacks */
204
 
static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits);
205
 
static void drcbex86_free(drcbe_state *drcbe);
206
 
static void drcbex86_reset(drcbe_state *drcbe);
207
 
static int drcbex86_execute(drcbe_state *drcbe, drcuml_codehandle *entry);
208
 
static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drcuml_instruction *instlist, UINT32 numinst);
209
 
static int drcbex86_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc);
210
 
static void drcbex86_get_info(drcbe_state *state, drcbe_info *info);
211
 
 
212
 
/* private helper functions */
213
 
static void fixup_label(void *parameter, drccodeptr labelcodeptr);
214
 
 
215
 
/* miscellaneous functions */
216
 
static int dmulu(UINT64 *dstlo, UINT64 *dsthi, UINT64 src1, UINT64 src2, int flags);
217
 
static int dmuls(UINT64 *dstlo, UINT64 *dsthi, INT64 src1, INT64 src2, int flags);
218
 
static int ddivu(UINT64 *dstlo, UINT64 *dsthi, UINT64 src1, UINT64 src2);
219
 
static int ddivs(UINT64 *dstlo, UINT64 *dsthi, INT64 src1, INT64 src2);
220
 
 
221
 
 
222
 
 
223
 
/***************************************************************************
224
 
    GLOBAL VARIABLES
225
 
***************************************************************************/
226
 
 
227
 
/* globally-accessible interface to the backend */
228
 
extern const drcbe_interface drcbe_x86_be_interface =
229
 
{
230
 
        drcbex86_alloc,
231
 
        drcbex86_free,
232
 
        drcbex86_reset,
233
 
        drcbex86_execute,
234
 
        drcbex86_generate,
235
 
        drcbex86_hash_exists,
236
 
        drcbex86_get_info
237
 
};
238
 
 
239
 
/* opcode table */
240
 
static opcode_generate_func opcode_table[DRCUML_OP_MAX];
241
 
 
242
 
/* size-to-mask table */
 
131
//**************************************************************************
 
132
//  CONSTANTS
 
133
//**************************************************************************
 
134
 
 
135
const UINT32 PTYPE_M    = 1 << parameter::PTYPE_MEMORY;
 
136
const UINT32 PTYPE_I    = 1 << parameter::PTYPE_IMMEDIATE;
 
137
const UINT32 PTYPE_R    = 1 << parameter::PTYPE_INT_REGISTER;
 
138
const UINT32 PTYPE_F    = 1 << parameter::PTYPE_FLOAT_REGISTER;
 
139
const UINT32 PTYPE_MI   = PTYPE_M | PTYPE_I;
 
140
const UINT32 PTYPE_RI   = PTYPE_R | PTYPE_I;
 
141
const UINT32 PTYPE_MR   = PTYPE_M | PTYPE_R;
 
142
const UINT32 PTYPE_MRI  = PTYPE_M | PTYPE_R | PTYPE_I;
 
143
const UINT32 PTYPE_MF   = PTYPE_M | PTYPE_F;
 
144
 
 
145
 
 
146
 
 
147
//**************************************************************************
 
148
//  MACROS
 
149
//**************************************************************************
 
150
 
 
151
#define X86_CONDITION(condition)                (condition_map[condition - uml::COND_Z])
 
152
#define X86_NOT_CONDITION(condition)    (condition_map[condition - uml::COND_Z] ^ 1)
 
153
 
 
154
#define assert_no_condition(inst)               assert((inst).condition() == uml::COND_ALWAYS)
 
155
#define assert_any_condition(inst)              assert((inst).condition() == uml::COND_ALWAYS || ((inst).condition() >= uml::COND_Z && (inst).condition() < uml::COND_MAX))
 
156
#define assert_no_flags(inst)                   assert((inst).flags() == 0)
 
157
#define assert_flags(inst, valid)               assert(((inst).flags() & ~(valid)) == 0)
 
158
 
 
159
 
 
160
 
 
161
//**************************************************************************
 
162
//  GLOBAL VARIABLES
 
163
//**************************************************************************
 
164
 
 
165
drcbe_x86::opcode_generate_func drcbe_x86::s_opcode_table[OP_MAX];
 
166
 
 
167
// size-to-mask table
243
168
static const UINT64 size_to_mask[] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0, U64(0xffffffffffffffff) };
244
169
 
245
 
/* register mapping tables */
246
 
static const UINT8 int_register_map[DRCUML_REG_I_END - DRCUML_REG_I0] =
 
170
// register mapping tables
 
171
static const UINT8 int_register_map[REG_I_COUNT] =
247
172
{
248
173
        REG_EBX, REG_ESI, REG_EDI, REG_EBP
249
174
};
250
175
 
251
 
/* flags mapping tables */
 
176
// flags mapping tables
252
177
static UINT8 flags_map[0x1000];
253
178
static UINT32 flags_unmap[0x20];
254
179
 
255
 
/* condition mapping table */
256
 
static const UINT8 condition_map[DRCUML_COND_MAX - DRCUML_COND_Z] =
 
180
// condition mapping table
 
181
static const UINT8 condition_map[uml::COND_MAX - uml::COND_Z] =
257
182
{
258
 
        COND_Z,         /* DRCUML_COND_Z = 0x80,    requires Z */
259
 
        COND_NZ,        /* DRCUML_COND_NZ,          requires Z */
260
 
        COND_S,         /* DRCUML_COND_S,           requires S */
261
 
        COND_NS,        /* DRCUML_COND_NS,          requires S */
262
 
        COND_C,         /* DRCUML_COND_C,           requires C */
263
 
        COND_NC,        /* DRCUML_COND_NC,          requires C */
264
 
        COND_O,         /* DRCUML_COND_V,           requires V */
265
 
        COND_NO,        /* DRCUML_COND_NV,          requires V */
266
 
        COND_P,         /* DRCUML_COND_U,           requires U */
267
 
        COND_NP,        /* DRCUML_COND_NU,          requires U */
268
 
        COND_A,         /* DRCUML_COND_A,           requires CZ */
269
 
        COND_BE,        /* DRCUML_COND_BE,          requires CZ */
270
 
        COND_G,         /* DRCUML_COND_G,           requires SVZ */
271
 
        COND_LE,        /* DRCUML_COND_LE,          requires SVZ */
272
 
        COND_L,         /* DRCUML_COND_L,           requires SV */
273
 
        COND_GE,        /* DRCUML_COND_GE,          requires SV */
 
183
        x86emit::COND_Z,        // COND_Z = 0x80,    requires Z
 
184
        x86emit::COND_NZ,       // COND_NZ,          requires Z
 
185
        x86emit::COND_S,        // COND_S,           requires S
 
186
        x86emit::COND_NS,       // COND_NS,          requires S
 
187
        x86emit::COND_C,        // COND_C,           requires C
 
188
        x86emit::COND_NC,       // COND_NC,          requires C
 
189
        x86emit::COND_O,        // COND_V,           requires V
 
190
        x86emit::COND_NO,       // COND_NV,          requires V
 
191
        x86emit::COND_P,        // COND_U,           requires U
 
192
        x86emit::COND_NP,       // COND_NU,          requires U
 
193
        x86emit::COND_A,        // COND_A,           requires CZ
 
194
        x86emit::COND_BE,       // COND_BE,          requires CZ
 
195
        x86emit::COND_G,        // COND_G,           requires SVZ
 
196
        x86emit::COND_LE,       // COND_LE,          requires SVZ
 
197
        x86emit::COND_L,        // COND_L,           requires SV
 
198
        x86emit::COND_GE,       // COND_GE,          requires SV
274
199
};
275
200
 
276
 
/* FPU control register mapping */
 
201
// FPU control register mapping
277
202
static const UINT16 fp_control[4] =
278
203
{
279
 
        0x0e3f,         /* DRCUML_FMOD_TRUNC */
280
 
        0x023f,         /* DRCUML_FMOD_ROUND */
281
 
        0x0a3f,         /* DRCUML_FMOD_CEIL */
282
 
        0x063f          /* DRCUML_FMOD_FLOOR */
283
 
};
284
 
 
285
 
 
286
 
 
287
 
/***************************************************************************
288
 
    TABLES
289
 
***************************************************************************/
290
 
 
291
 
static x86code *op_handle(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
292
 
static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
293
 
static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
294
 
static x86code *op_comment(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
295
 
static x86code *op_mapvar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
296
 
 
297
 
static x86code *op_nop(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
298
 
static x86code *op_debug(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
299
 
static x86code *op_exit(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
300
 
static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
301
 
static x86code *op_jmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
302
 
static x86code *op_exh(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
303
 
static x86code *op_callh(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
304
 
static x86code *op_ret(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
305
 
static x86code *op_callc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
306
 
static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
307
 
 
308
 
static x86code *op_setfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
309
 
static x86code *op_getfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
310
 
static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
311
 
static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
312
 
static x86code *op_save(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
313
 
static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
314
 
 
315
 
static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
316
 
static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
317
 
static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
318
 
static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
319
 
static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
320
 
static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
321
 
static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
322
 
static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
323
 
static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
324
 
static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
325
 
static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
326
 
static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
327
 
static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
328
 
static x86code *op_add(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
329
 
static x86code *op_addc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
330
 
static x86code *op_sub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
331
 
static x86code *op_subc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
332
 
static x86code *op_cmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
333
 
static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
334
 
static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
335
 
static x86code *op_divu(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
336
 
static x86code *op_divs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
337
 
static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
338
 
static x86code *op_test(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
339
 
static x86code *op_or(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
340
 
static x86code *op_xor(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
341
 
static x86code *op_lzcnt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
342
 
static x86code *op_bswap(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
343
 
static x86code *op_shl(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
344
 
static x86code *op_shr(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
345
 
static x86code *op_sar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
346
 
static x86code *op_ror(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
347
 
static x86code *op_rol(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
348
 
static x86code *op_rorc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
349
 
static x86code *op_rolc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
350
 
 
351
 
static x86code *op_fload(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
352
 
static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
353
 
static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
354
 
static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
355
 
static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
356
 
static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
357
 
static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
358
 
static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
359
 
static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
360
 
static x86code *op_fadd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
361
 
static x86code *op_fsub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
362
 
static x86code *op_fcmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
363
 
static x86code *op_fmul(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
364
 
static x86code *op_fdiv(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
365
 
static x86code *op_fneg(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
366
 
static x86code *op_fabs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
367
 
static x86code *op_fsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
368
 
static x86code *op_frecip(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
369
 
static x86code *op_frsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
370
 
 
371
 
static const opcode_table_entry opcode_table_source[] =
372
 
{
373
 
        /* Compile-time opcodes */
374
 
        { DRCUML_OP_HANDLE,      op_handle },   /* HANDLE  handle                 */
375
 
        { DRCUML_OP_HASH,    op_hash },         /* HASH    mode,pc                */
376
 
        { DRCUML_OP_LABEL,   op_label },        /* LABEL   imm                    */
377
 
        { DRCUML_OP_COMMENT, op_comment },      /* COMMENT string                 */
378
 
        { DRCUML_OP_MAPVAR,  op_mapvar },       /* MAPVAR  mapvar,value           */
379
 
 
380
 
        /* Control Flow Operations */
381
 
        { DRCUML_OP_NOP,     op_nop },          /* NOP                            */
382
 
        { DRCUML_OP_DEBUG,   op_debug },        /* DEBUG   pc                     */
383
 
        { DRCUML_OP_EXIT,    op_exit },         /* EXIT    src1[,c]               */
384
 
        { DRCUML_OP_HASHJMP, op_hashjmp },      /* HASHJMP mode,pc,handle         */
385
 
        { DRCUML_OP_JMP,     op_jmp },          /* JMP     imm[,c]                */
386
 
        { DRCUML_OP_EXH,     op_exh },          /* EXH     handle,param[,c]       */
387
 
        { DRCUML_OP_CALLH,   op_callh },        /* CALLH   handle[,c]             */
388
 
        { DRCUML_OP_RET,     op_ret },          /* RET     [c]                    */
389
 
        { DRCUML_OP_CALLC,   op_callc },        /* CALLC   func,ptr[,c]           */
390
 
        { DRCUML_OP_RECOVER, op_recover },      /* RECOVER dst,mapvar             */
391
 
 
392
 
        /* Internal Register Operations */
393
 
        { DRCUML_OP_SETFMOD, op_setfmod },      /* SETFMOD src                    */
394
 
        { DRCUML_OP_GETFMOD, op_getfmod },      /* GETFMOD dst                    */
395
 
        { DRCUML_OP_GETEXP,  op_getexp },       /* GETEXP  dst                    */
396
 
        { DRCUML_OP_GETFLGS, op_getflgs },      /* GETFLGS dst,mask               */
397
 
        { DRCUML_OP_SAVE,    op_save },         /* SAVE    dst                    */
398
 
        { DRCUML_OP_RESTORE, op_restore },      /* RESTORE dst                    */
399
 
 
400
 
        /* Integer Operations */
401
 
        { DRCUML_OP_LOAD,    op_load },         /* LOAD    dst,base,index,size    */
402
 
        { DRCUML_OP_LOADS,   op_loads },        /* LOADS   dst,base,index,size    */
403
 
        { DRCUML_OP_STORE,   op_store },        /* STORE   base,index,src,size    */
404
 
        { DRCUML_OP_READ,    op_read },         /* READ    dst,src1,spacesize     */
405
 
        { DRCUML_OP_READM,   op_readm },        /* READM   dst,src1,mask,spacesize */
406
 
        { DRCUML_OP_WRITE,   op_write },        /* WRITE   dst,src1,spacesize     */
407
 
        { DRCUML_OP_WRITEM,  op_writem },       /* WRITEM  dst,src1,spacesize     */
408
 
        { DRCUML_OP_CARRY,   op_carry },        /* CARRY   src,bitnum             */
409
 
        { DRCUML_OP_SET,     op_set },          /* SET     dst,c                  */
410
 
        { DRCUML_OP_MOV,     op_mov },          /* MOV     dst,src[,c]            */
411
 
        { DRCUML_OP_SEXT,    op_sext },         /* SEXT    dst,src                */
412
 
        { DRCUML_OP_ROLAND,  op_roland },       /* ROLAND  dst,src1,src2,src3     */
413
 
        { DRCUML_OP_ROLINS,  op_rolins },       /* ROLINS  dst,src1,src2,src3     */
414
 
        { DRCUML_OP_ADD,     op_add },          /* ADD     dst,src1,src2[,f]      */
415
 
        { DRCUML_OP_ADDC,    op_addc },         /* ADDC    dst,src1,src2[,f]      */
416
 
        { DRCUML_OP_SUB,     op_sub },          /* SUB     dst,src1,src2[,f]      */
417
 
        { DRCUML_OP_SUBB,    op_subc },         /* SUBB    dst,src1,src2[,f]      */
418
 
        { DRCUML_OP_CMP,     op_cmp },          /* CMP     src1,src2[,f]          */
419
 
        { DRCUML_OP_MULU,    op_mulu },         /* MULU    dst,edst,src1,src2[,f] */
420
 
        { DRCUML_OP_MULS,    op_muls },         /* MULS    dst,edst,src1,src2[,f] */
421
 
        { DRCUML_OP_DIVU,    op_divu },         /* DIVU    dst,edst,src1,src2[,f] */
422
 
        { DRCUML_OP_DIVS,    op_divs },         /* DIVS    dst,edst,src1,src2[,f] */
423
 
        { DRCUML_OP_AND,     op_and },          /* AND     dst,src1,src2[,f]      */
424
 
        { DRCUML_OP_TEST,    op_test },         /* TEST    src1,src2[,f]          */
425
 
        { DRCUML_OP_OR,      op_or },           /* OR      dst,src1,src2[,f]      */
426
 
        { DRCUML_OP_XOR,     op_xor },          /* XOR     dst,src1,src2[,f]      */
427
 
        { DRCUML_OP_LZCNT,   op_lzcnt },        /* LZCNT   dst,src                */
428
 
        { DRCUML_OP_BSWAP,   op_bswap },        /* BSWAP   dst,src                */
429
 
        { DRCUML_OP_SHL,     op_shl },          /* SHL     dst,src,count[,f]      */
430
 
        { DRCUML_OP_SHR,     op_shr },          /* SHR     dst,src,count[,f]      */
431
 
        { DRCUML_OP_SAR,     op_sar },          /* SAR     dst,src,count[,f]      */
432
 
        { DRCUML_OP_ROL,     op_rol },          /* ROL     dst,src,count[,f]      */
433
 
        { DRCUML_OP_ROLC,    op_rolc },         /* ROLC    dst,src,count[,f]      */
434
 
        { DRCUML_OP_ROR,     op_ror },          /* ROR     dst,src,count[,f]      */
435
 
        { DRCUML_OP_RORC,    op_rorc },         /* RORC    dst,src,count[,f]      */
436
 
 
437
 
        /* Floating Point Operations */
438
 
        { DRCUML_OP_FLOAD,   op_fload },        /* FLOAD   dst,base,index         */
439
 
        { DRCUML_OP_FSTORE,  op_fstore },       /* FSTORE  base,index,src         */
440
 
        { DRCUML_OP_FREAD,   op_fread },        /* FREAD   dst,src1,space         */
441
 
        { DRCUML_OP_FWRITE,  op_fwrite },       /* FWRITE  dst,src1,space         */
442
 
        { DRCUML_OP_FMOV,    op_fmov },         /* FMOV    dst,src1[,c]           */
443
 
        { DRCUML_OP_FTOINT,  op_ftoint },       /* FTOINT  dst,src1,size,round    */
444
 
        { DRCUML_OP_FFRINT,  op_ffrint },       /* FFRINT  dst,src1,size          */
445
 
        { DRCUML_OP_FFRFLT,  op_ffrflt },       /* FFRFLT  dst,src1,size          */
446
 
        { DRCUML_OP_FRNDS,   op_frnds },        /* FRNDS   dst,src1               */
447
 
        { DRCUML_OP_FADD,    op_fadd },         /* FADD    dst,src1,src2          */
448
 
        { DRCUML_OP_FSUB,    op_fsub },         /* FSUB    dst,src1,src2          */
449
 
        { DRCUML_OP_FCMP,    op_fcmp },         /* FCMP    src1,src2              */
450
 
        { DRCUML_OP_FMUL,    op_fmul },         /* FMUL    dst,src1,src2          */
451
 
        { DRCUML_OP_FDIV,    op_fdiv },         /* FDIV    dst,src1,src2          */
452
 
        { DRCUML_OP_FNEG,    op_fneg },         /* FNEG    dst,src1               */
453
 
        { DRCUML_OP_FABS,    op_fabs },         /* FABS    dst,src1               */
454
 
        { DRCUML_OP_FSQRT,   op_fsqrt },        /* FSQRT   dst,src1               */
455
 
        { DRCUML_OP_FRECIP,  op_frecip },       /* FRECIP  dst,src1               */
456
 
        { DRCUML_OP_FRSQRT,  op_frsqrt }        /* FRSQRT  dst,src1               */
457
 
};
458
 
 
459
 
 
460
 
 
461
 
/***************************************************************************
462
 
    INLINE FUNCTIONS
463
 
***************************************************************************/
464
 
 
465
 
/*-------------------------------------------------
466
 
    param_select_register - select a register
467
 
    to use, avoiding conflicts with the optional
468
 
    checkparam
469
 
-------------------------------------------------*/
470
 
 
471
 
INLINE int param_select_register(int defreg, const drcuml_parameter *param, const drcuml_parameter *checkparam)
472
 
{
473
 
        if (param->type == DRCUML_PTYPE_INT_REGISTER && (checkparam == NULL || param->type != checkparam->type || param->value != checkparam->value))
474
 
                return param->value;
475
 
        return defreg;
476
 
}
477
 
 
478
 
 
479
 
/*-------------------------------------------------
480
 
    param_select_register2 - select a register
481
 
    to use, avoiding conflicts with the optional
482
 
    checkparam
483
 
-------------------------------------------------*/
484
 
 
485
 
INLINE int param_select_register2(int defreg, const drcuml_parameter *param, const drcuml_parameter *checkparam1, const drcuml_parameter *checkparam2)
486
 
{
487
 
        if (param->type == DRCUML_PTYPE_INT_REGISTER && (param->type != checkparam1->type || param->value != checkparam1->value) && (param->type != checkparam2->type || param->value != checkparam2->value))
488
 
                return param->value;
489
 
        return defreg;
490
 
}
491
 
 
492
 
 
493
 
/*-------------------------------------------------
494
 
    emit_combine_z_flags - combine the Z flag from
495
 
    two 32-bit operations
496
 
-------------------------------------------------*/
497
 
 
498
 
INLINE void emit_combine_z_flags(x86code **dst)
499
 
{
500
 
        /* this assumes that the flags from the low 32-bit op are on the stack */
501
 
        /* and the flags from the high 32-bit op are live */
 
204
        0x0e3f,         // ROUND_TRUNC
 
205
        0x023f,         // ROUND_ROUND
 
206
        0x0a3f,         // ROUND_CEIL
 
207
        0x063f          // ROUND_FLOOR
 
208
};
 
209
 
 
210
 
 
211
 
 
212
//**************************************************************************
 
213
//  TABLES
 
214
//**************************************************************************
 
215
 
 
216
const drcbe_x86::opcode_table_entry drcbe_x86::s_opcode_table_source[] =
 
217
{
 
218
        // Compile-time opcodes
 
219
        { uml::OP_HANDLE,  &drcbe_x86::op_handle },             // HANDLE  handle
 
220
        { uml::OP_HASH,    &drcbe_x86::op_hash },               // HASH    mode,pc
 
221
        { uml::OP_LABEL,   &drcbe_x86::op_label },              // LABEL   imm
 
222
        { uml::OP_COMMENT, &drcbe_x86::op_comment },    // COMMENT string
 
223
        { uml::OP_MAPVAR,  &drcbe_x86::op_mapvar },             // MAPVAR  mapvar,value
 
224
 
 
225
        // Control Flow Operations
 
226
        { uml::OP_NOP,     &drcbe_x86::op_nop },                // NOP
 
227
        { uml::OP_DEBUG,   &drcbe_x86::op_debug },              // DEBUG   pc
 
228
        { uml::OP_EXIT,    &drcbe_x86::op_exit },               // EXIT    src1[,c]
 
229
        { uml::OP_HASHJMP, &drcbe_x86::op_hashjmp },    // HASHJMP mode,pc,handle
 
230
        { uml::OP_JMP,     &drcbe_x86::op_jmp },                // JMP     imm[,c]
 
231
        { uml::OP_EXH,     &drcbe_x86::op_exh },                // EXH     handle,param[,c]
 
232
        { uml::OP_CALLH,   &drcbe_x86::op_callh },              // CALLH   handle[,c]
 
233
        { uml::OP_RET,     &drcbe_x86::op_ret },                // RET     [c]
 
234
        { uml::OP_CALLC,   &drcbe_x86::op_callc },              // CALLC   func,ptr[,c]
 
235
        { uml::OP_RECOVER, &drcbe_x86::op_recover },    // RECOVER dst,mapvar
 
236
 
 
237
        // Internal Register Operations
 
238
        { uml::OP_SETFMOD, &drcbe_x86::op_setfmod },    // SETFMOD src
 
239
        { uml::OP_GETFMOD, &drcbe_x86::op_getfmod },    // GETFMOD dst
 
240
        { uml::OP_GETEXP,  &drcbe_x86::op_getexp },             // GETEXP  dst
 
241
        { uml::OP_GETFLGS, &drcbe_x86::op_getflgs },    // GETFLGS dst[,f]
 
242
        { uml::OP_SAVE,    &drcbe_x86::op_save },               // SAVE    dst
 
243
        { uml::OP_RESTORE, &drcbe_x86::op_restore },    // RESTORE dst
 
244
 
 
245
        // Integer Operations
 
246
        { uml::OP_LOAD,    &drcbe_x86::op_load },               // LOAD    dst,base,index,size
 
247
        { uml::OP_LOADS,   &drcbe_x86::op_loads },              // LOADS   dst,base,index,size
 
248
        { uml::OP_STORE,   &drcbe_x86::op_store },              // STORE   base,index,src,size
 
249
        { uml::OP_READ,    &drcbe_x86::op_read },               // READ    dst,src1,spacesize
 
250
        { uml::OP_READM,   &drcbe_x86::op_readm },              // READM   dst,src1,mask,spacesize
 
251
        { uml::OP_WRITE,   &drcbe_x86::op_write },              // WRITE   dst,src1,spacesize
 
252
        { uml::OP_WRITEM,  &drcbe_x86::op_writem },             // WRITEM  dst,src1,spacesize
 
253
        { uml::OP_CARRY,   &drcbe_x86::op_carry },              // CARRY   src,bitnum
 
254
        { uml::OP_SET,     &drcbe_x86::op_set },                // SET     dst,c
 
255
        { uml::OP_MOV,     &drcbe_x86::op_mov },                // MOV     dst,src[,c]
 
256
        { uml::OP_SEXT,    &drcbe_x86::op_sext },               // SEXT    dst,src
 
257
        { uml::OP_ROLAND,  &drcbe_x86::op_roland },             // ROLAND  dst,src1,src2,src3
 
258
        { uml::OP_ROLINS,  &drcbe_x86::op_rolins },             // ROLINS  dst,src1,src2,src3
 
259
        { uml::OP_ADD,     &drcbe_x86::op_add },                // ADD     dst,src1,src2[,f]
 
260
        { uml::OP_ADDC,    &drcbe_x86::op_addc },               // ADDC    dst,src1,src2[,f]
 
261
        { uml::OP_SUB,     &drcbe_x86::op_sub },                // SUB     dst,src1,src2[,f]
 
262
        { uml::OP_SUBB,    &drcbe_x86::op_subc },               // SUBB    dst,src1,src2[,f]
 
263
        { uml::OP_CMP,     &drcbe_x86::op_cmp },                // CMP     src1,src2[,f]
 
264
        { uml::OP_MULU,    &drcbe_x86::op_mulu },               // MULU    dst,edst,src1,src2[,f]
 
265
        { uml::OP_MULS,    &drcbe_x86::op_muls },               // MULS    dst,edst,src1,src2[,f]
 
266
        { uml::OP_DIVU,    &drcbe_x86::op_divu },               // DIVU    dst,edst,src1,src2[,f]
 
267
        { uml::OP_DIVS,    &drcbe_x86::op_divs },               // DIVS    dst,edst,src1,src2[,f]
 
268
        { uml::OP_AND,     &drcbe_x86::op_and },                // AND     dst,src1,src2[,f]
 
269
        { uml::OP_TEST,    &drcbe_x86::op_test },               // TEST    src1,src2[,f]
 
270
        { uml::OP_OR,      &drcbe_x86::op_or },                 // OR      dst,src1,src2[,f]
 
271
        { uml::OP_XOR,     &drcbe_x86::op_xor },                // XOR     dst,src1,src2[,f]
 
272
        { uml::OP_LZCNT,   &drcbe_x86::op_lzcnt },              // LZCNT   dst,src[,f]
 
273
        { uml::OP_BSWAP,   &drcbe_x86::op_bswap },              // BSWAP   dst,src
 
274
        { uml::OP_SHL,     &drcbe_x86::op_shl },                // SHL     dst,src,count[,f]
 
275
        { uml::OP_SHR,     &drcbe_x86::op_shr },                // SHR     dst,src,count[,f]
 
276
        { uml::OP_SAR,     &drcbe_x86::op_sar },                // SAR     dst,src,count[,f]
 
277
        { uml::OP_ROL,     &drcbe_x86::op_rol },                // ROL     dst,src,count[,f]
 
278
        { uml::OP_ROLC,    &drcbe_x86::op_rolc },               // ROLC    dst,src,count[,f]
 
279
        { uml::OP_ROR,     &drcbe_x86::op_ror },                // ROR     dst,src,count[,f]
 
280
        { uml::OP_RORC,    &drcbe_x86::op_rorc },               // RORC    dst,src,count[,f]
 
281
 
 
282
        // Floating Point Operations
 
283
        { uml::OP_FLOAD,   &drcbe_x86::op_fload },              // FLOAD   dst,base,index
 
284
        { uml::OP_FSTORE,  &drcbe_x86::op_fstore },             // FSTORE  base,index,src
 
285
        { uml::OP_FREAD,   &drcbe_x86::op_fread },              // FREAD   dst,space,src1
 
286
        { uml::OP_FWRITE,  &drcbe_x86::op_fwrite },             // FWRITE  space,dst,src1
 
287
        { uml::OP_FMOV,    &drcbe_x86::op_fmov },               // FMOV    dst,src1[,c]
 
288
        { uml::OP_FTOINT,  &drcbe_x86::op_ftoint },             // FTOINT  dst,src1,size,round
 
289
        { uml::OP_FFRINT,  &drcbe_x86::op_ffrint },             // FFRINT  dst,src1,size
 
290
        { uml::OP_FFRFLT,  &drcbe_x86::op_ffrflt },             // FFRFLT  dst,src1,size
 
291
        { uml::OP_FRNDS,   &drcbe_x86::op_frnds },              // FRNDS   dst,src1
 
292
        { uml::OP_FADD,    &drcbe_x86::op_fadd },               // FADD    dst,src1,src2
 
293
        { uml::OP_FSUB,    &drcbe_x86::op_fsub },               // FSUB    dst,src1,src2
 
294
        { uml::OP_FCMP,    &drcbe_x86::op_fcmp },               // FCMP    src1,src2
 
295
        { uml::OP_FMUL,    &drcbe_x86::op_fmul },               // FMUL    dst,src1,src2
 
296
        { uml::OP_FDIV,    &drcbe_x86::op_fdiv },               // FDIV    dst,src1,src2
 
297
        { uml::OP_FNEG,    &drcbe_x86::op_fneg },               // FNEG    dst,src1
 
298
        { uml::OP_FABS,    &drcbe_x86::op_fabs },               // FABS    dst,src1
 
299
        { uml::OP_FSQRT,   &drcbe_x86::op_fsqrt },              // FSQRT   dst,src1
 
300
        { uml::OP_FRECIP,  &drcbe_x86::op_frecip },             // FRECIP  dst,src1
 
301
        { uml::OP_FRSQRT,  &drcbe_x86::op_frsqrt }              // FRSQRT  dst,src1
 
302
};
 
303
 
 
304
 
 
305
 
 
306
//**************************************************************************
 
307
//  INLINE FUNCTIONS
 
308
//**************************************************************************
 
309
 
 
310
//-------------------------------------------------
 
311
//  param_normalize - convert a full parameter
 
312
//  into a reduced set
 
313
//-------------------------------------------------
 
314
 
 
315
drcbe_x86::be_parameter::be_parameter(drcbe_x86 &drcbe, const parameter &param, UINT32 allowed)
 
316
{
 
317
        int regnum;
 
318
 
 
319
        switch (param.type())
 
320
        {
 
321
                // immediates pass through
 
322
                case parameter::PTYPE_IMMEDIATE:
 
323
                        assert(allowed & PTYPE_I);
 
324
                        *this = param.immediate();
 
325
                        break;
 
326
 
 
327
                // memory passes through
 
328
                case parameter::PTYPE_MEMORY:
 
329
                        assert(allowed & PTYPE_M);
 
330
                        *this = make_memory(param.memory());
 
331
                        break;
 
332
 
 
333
                // if a register maps to a register, keep it as a register; otherwise map it to memory
 
334
                case parameter::PTYPE_INT_REGISTER:
 
335
                        assert(allowed & PTYPE_R);
 
336
                        assert(allowed & PTYPE_M);
 
337
                        regnum = int_register_map[param.ireg() - REG_I0];
 
338
                        if (regnum != 0)
 
339
                                *this = make_ireg(regnum);
 
340
                        else
 
341
                                *this = make_memory(&drcbe.m_state.r[param.ireg() - REG_I0]);
 
342
                        break;
 
343
 
 
344
                // if a register maps to a register, keep it as a register; otherwise map it to memory
 
345
                case parameter::PTYPE_FLOAT_REGISTER:
 
346
                        assert(allowed & PTYPE_F);
 
347
                        assert(allowed & PTYPE_M);
 
348
                        *this = make_memory(&drcbe.m_state.f[param.freg() - REG_F0]);
 
349
                        break;
 
350
 
 
351
                // everything else is unexpected
 
352
                default:
 
353
                        fatalerror("Unexpected parameter type");
 
354
                        break;
 
355
        }
 
356
}
 
357
 
 
358
 
 
359
//-------------------------------------------------
 
360
//  select_register - select a register to use,
 
361
//  avoiding conflicts with the optional
 
362
//  checkparam
 
363
//-------------------------------------------------
 
364
 
 
365
inline int drcbe_x86::be_parameter::select_register(int defreg) const
 
366
{
 
367
        if (m_type == PTYPE_INT_REGISTER || m_type == PTYPE_FLOAT_REGISTER || m_type == PTYPE_VECTOR_REGISTER)
 
368
                return m_value;
 
369
        return defreg;
 
370
}
 
371
 
 
372
inline int drcbe_x86::be_parameter::select_register(int defreg, const be_parameter &checkparam) const
 
373
{
 
374
        if (*this == checkparam)
 
375
                return defreg;
 
376
        return select_register(defreg);
 
377
}
 
378
 
 
379
inline int drcbe_x86::be_parameter::select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const
 
380
{
 
381
        if (*this == checkparam || *this == checkparam2)
 
382
                return defreg;
 
383
        return select_register(defreg);
 
384
}
 
385
 
 
386
 
 
387
//-------------------------------------------------
 
388
//  select_register - select a register to use,
 
389
//  avoiding conflicts with the optional
 
390
//  checkparam
 
391
//-------------------------------------------------
 
392
 
 
393
inline void drcbe_x86::normalize_commutative(be_parameter &inner, be_parameter &outer)
 
394
{
 
395
        // if the inner parameter is a memory operand, push it to the outer
 
396
        if (inner.is_memory())
 
397
        {
 
398
                be_parameter temp = inner;
 
399
                inner = outer;
 
400
                outer = temp;
 
401
        }
 
402
 
 
403
        // if the inner parameter is an immediate, push it to the outer
 
404
        if (inner.is_immediate())
 
405
        {
 
406
                be_parameter temp = inner;
 
407
                inner = outer;
 
408
                outer = temp;
 
409
        }
 
410
}
 
411
 
 
412
 
 
413
//-------------------------------------------------
 
414
//  emit_combine_z_flags - combine the Z flag from
 
415
//  two 32-bit operations
 
416
//-------------------------------------------------
 
417
 
 
418
inline void drcbe_x86::emit_combine_z_flags(x86code *&dst)
 
419
{
 
420
        // this assumes that the flags from the low 32-bit op are on the stack
 
421
        // and the flags from the high 32-bit op are live
502
422
        emit_pushf(dst);                                                                                                                                        // pushf
503
423
        emit_mov_r32_m32(dst, REG_ECX, MBD(REG_ESP, 4));                                                                        // mov   ecx,[esp+4]
504
424
        emit_or_r32_imm(dst, REG_ECX, ~0x40);                                                                                           // or    ecx,~0x40
508
428
}
509
429
 
510
430
 
511
 
/*-------------------------------------------------
512
 
    emit_combine_z_shl_flags - combine the Z
513
 
    flags from two 32-bit shift left operations
514
 
-------------------------------------------------*/
 
431
//-------------------------------------------------
 
432
//  emit_combine_z_shl_flags - combine the Z
 
433
//  flags from two 32-bit shift left operations
 
434
//-------------------------------------------------
515
435
 
516
 
INLINE void emit_combine_z_shl_flags(x86code **dst)
 
436
inline void drcbe_x86::emit_combine_z_shl_flags(x86code *&dst)
517
437
{
518
 
        /* this assumes that the flags from the high 32-bit op are on the stack */
519
 
        /* and the flags from the low 32-bit op are live */
 
438
        // this assumes that the flags from the high 32-bit op are on the stack
 
439
        // and the flags from the low 32-bit op are live
520
440
        emit_pushf(dst);                                                                                                                                        // pushf
521
441
        emit_pop_r32(dst, REG_ECX);                                                                                                                     // pop   ecx
522
442
        emit_or_r32_imm(dst, REG_ECX, ~0x40);                                                                                           // or    ecx,~0x40
525
445
}
526
446
 
527
447
 
528
 
/*-------------------------------------------------
529
 
    reset_last_upper_lower_reg - reset the last
530
 
    upper/lower register state
531
 
-------------------------------------------------*/
 
448
//-------------------------------------------------
 
449
//  reset_last_upper_lower_reg - reset the last
 
450
//  upper/lower register state
 
451
//-------------------------------------------------
532
452
 
533
 
INLINE void reset_last_upper_lower_reg(drcbe_state *drcbe)
 
453
inline void drcbe_x86::reset_last_upper_lower_reg()
534
454
{
535
 
        drcbe->last_lower_reg = REG_NONE;
536
 
        drcbe->last_upper_reg = REG_NONE;
 
455
        m_last_lower_reg = REG_NONE;
 
456
        m_last_upper_reg = REG_NONE;
537
457
}
538
458
 
539
459
 
540
 
/*-------------------------------------------------
541
 
    set_last_lower_reg - note that we have just
542
 
    loaded a lower register
543
 
-------------------------------------------------*/
 
460
//-------------------------------------------------
 
461
//  set_last_lower_reg - note that we have just
 
462
//  loaded a lower register
 
463
//-------------------------------------------------
544
464
 
545
 
INLINE void set_last_lower_reg(drcbe_state *drcbe, x86code *dst, const drcuml_parameter *param, UINT8 reglo)
 
465
inline void drcbe_x86::set_last_lower_reg(x86code *&dst, const be_parameter &param, UINT8 reglo)
546
466
{
547
 
        if (param->type == DRCUML_PTYPE_MEMORY)
 
467
        if (param.is_memory())
548
468
        {
549
 
                drcbe->last_lower_reg = reglo;
550
 
                drcbe->last_lower_addr = (UINT32 *)((FPTR)param->value);
551
 
                drcbe->last_lower_pc = dst;
 
469
                m_last_lower_reg = reglo;
 
470
                m_last_lower_addr = (UINT32 *)((FPTR)param.memory());
 
471
                m_last_lower_pc = dst;
552
472
        }
553
473
}
554
474
 
555
475
 
556
 
/*-------------------------------------------------
557
 
    set_last_upper_reg - note that we have just
558
 
    loaded an upper register
559
 
-------------------------------------------------*/
560
 
 
561
 
INLINE void set_last_upper_reg(drcbe_state *drcbe, x86code *dst, const drcuml_parameter *param, UINT8 reghi)
562
 
{
563
 
        drcbe->last_upper_reg = reghi;
564
 
        drcbe->last_upper_addr = (param->type == DRCUML_PTYPE_INT_REGISTER) ? drcbe->reghi[param->value] : (UINT32 *)((FPTR)param->value + 4);
565
 
        drcbe->last_upper_pc = dst;
566
 
}
567
 
 
568
 
 
569
 
/*-------------------------------------------------
570
 
    can_skip_lower_load - return TRUE if we can
571
 
    skip re-loading a lower half of a register
572
 
-------------------------------------------------*/
573
 
 
574
 
INLINE int can_skip_lower_load(drcbe_state *drcbe, x86code *dst, UINT32 *memptr, UINT8 reglo)
575
 
{
576
 
//  return FALSE;
577
 
        return (dst == drcbe->last_lower_pc && memptr == drcbe->last_lower_addr && reglo == drcbe->last_lower_reg);
578
 
}
579
 
 
580
 
 
581
 
/*-------------------------------------------------
582
 
    can_skip_upper_load - return TRUE if we can
583
 
    skip re-loading an upper half of a register
584
 
-------------------------------------------------*/
585
 
 
586
 
INLINE int can_skip_upper_load(drcbe_state *drcbe, x86code *dst, UINT32 *memptr, UINT8 reghi)
587
 
{
588
 
//  return FALSE;
589
 
        return (dst == drcbe->last_upper_pc && memptr == drcbe->last_upper_addr && reghi == drcbe->last_upper_reg);
590
 
}
591
 
 
592
 
 
593
 
/*-------------------------------------------------
594
 
    track_resolve_link - wrapper for resolve_link
595
 
    that resets all register tracking info
596
 
-------------------------------------------------*/
597
 
 
598
 
INLINE void track_resolve_link(drcbe_state *drcbe, x86code **destptr, const emit_link *linkinfo)
599
 
{
600
 
        reset_last_upper_lower_reg(drcbe);
 
476
//-------------------------------------------------
 
477
//  set_last_upper_reg - note that we have just
 
478
//  loaded an upper register
 
479
//-------------------------------------------------
 
480
 
 
481
inline void drcbe_x86::set_last_upper_reg(x86code *&dst, const be_parameter &param, UINT8 reghi)
 
482
{
 
483
        m_last_upper_reg = reghi;
 
484
        m_last_upper_addr = (param.is_int_register()) ? m_reghi[param.ireg()] : (UINT32 *)((FPTR)param.memory(4));
 
485
        m_last_upper_pc = dst;
 
486
}
 
487
 
 
488
 
 
489
//-------------------------------------------------
 
490
//  can_skip_lower_load - return true if we can
 
491
//  skip re-loading a lower half of a register
 
492
//-------------------------------------------------
 
493
 
 
494
inline bool drcbe_x86::can_skip_lower_load(x86code *&dst, UINT32 *memref, UINT8 reglo)
 
495
{
 
496
        return (dst == m_last_lower_pc && memref == m_last_lower_addr && reglo == m_last_lower_reg);
 
497
}
 
498
 
 
499
 
 
500
//-------------------------------------------------
 
501
//  can_skip_upper_load - return true if we can
 
502
//  skip re-loading an upper half of a register
 
503
//-------------------------------------------------
 
504
 
 
505
inline bool drcbe_x86::can_skip_upper_load(x86code *&dst, UINT32 *memref, UINT8 reghi)
 
506
{
 
507
        return (dst == m_last_upper_pc && memref == m_last_upper_addr && reghi == m_last_upper_reg);
 
508
}
 
509
 
 
510
 
 
511
//-------------------------------------------------
 
512
//  track_resolve_link - wrapper for resolve_link
 
513
//  that resets all register tracking info
 
514
//-------------------------------------------------
 
515
 
 
516
inline void drcbe_x86::track_resolve_link(x86code *&destptr, const emit_link &linkinfo)
 
517
{
 
518
        reset_last_upper_lower_reg();
601
519
        resolve_link(destptr, linkinfo);
602
520
}
603
521
 
605
523
 
606
524
 
607
525
 
608
 
/***************************************************************************
609
 
    BACKEND CALLBACKS
610
 
***************************************************************************/
611
 
 
612
 
/*-------------------------------------------------
613
 
    drcbex86_alloc - allocate back-end-specific
614
 
    state
615
 
-------------------------------------------------*/
616
 
 
617
 
static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits)
 
526
//**************************************************************************
 
527
//  BACKEND CALLBACKS
 
528
//**************************************************************************
 
529
 
 
530
//-------------------------------------------------
 
531
//  drcbe_x86 - constructor
 
532
//-------------------------------------------------
 
533
 
 
534
drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits)
 
535
        : drcbe_interface(drcuml, cache, device),
 
536
          m_hash(cache, modes, addrbits, ignorebits),
 
537
          m_map(cache, 0),
 
538
          m_labels(cache),
 
539
          m_log(NULL),
 
540
          m_logged_common(false),
 
541
          m_sse3(false),
 
542
          m_entry(NULL),
 
543
          m_exit(NULL),
 
544
          m_nocode(NULL),
 
545
          m_save(NULL),
 
546
          m_restore(NULL),
 
547
          m_last_lower_reg(REG_NONE),
 
548
          m_last_lower_pc(NULL),
 
549
          m_last_lower_addr(NULL),
 
550
          m_last_upper_reg(REG_NONE),
 
551
          m_last_upper_pc(NULL),
 
552
          m_last_upper_addr(NULL),
 
553
          m_fptemp(0),
 
554
          m_fpumode(0),
 
555
          m_fmodesave(0),
 
556
          m_stacksave(0),
 
557
          m_hashstacksave(0),
 
558
          m_reslo(0),
 
559
          m_reshi(0)
618
560
{
619
 
        int opnum, regnum, entry, spacenum;
620
 
        drcbe_state *drcbe;
621
 
 
622
 
        /* allocate space in the cache for our state */
623
 
        drcbe = (drcbe_state *)drccache_memory_alloc(cache, sizeof(*drcbe));
624
 
        if (drcbe == NULL)
625
 
                return NULL;
626
 
        memset(drcbe, 0, sizeof(*drcbe));
627
 
 
628
 
        /* remember our pointers */
629
 
        drcbe->device = device;
630
 
        drcbe->drcuml = drcuml;
631
 
        drcbe->cache = cache;
632
 
 
633
 
        /* get address spaces and accessors */
634
 
        for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++)
635
 
        {
636
 
                drcbe->space[spacenum] = downcast<cpu_device *>(device)->space(spacenum);
637
 
                if (drcbe->space[spacenum] != NULL)
638
 
                        drcbe->space[spacenum]->accessors(drcbe->accessors[spacenum]);
639
 
        }
640
 
 
641
 
        /* allocate hash tables */
642
 
        drcbe->hash = drchash_alloc(cache, modes, addrbits, ignorebits);
643
 
        if (drcbe->hash == NULL)
644
 
                return NULL;
645
 
 
646
 
        /* allocate code map */
647
 
        drcbe->map = drcmap_alloc(cache, 0);
648
 
        if (drcbe->map == NULL)
649
 
                return NULL;
650
 
 
651
 
        /* allocate a label tracker */
652
 
        drcbe->labels = drclabel_list_alloc(cache);
653
 
        if (drcbe->labels == NULL)
654
 
                return NULL;
655
 
 
656
 
        /* build the opcode table (static but it doesn't hurt to regenerate it) */
657
 
        for (opnum = 0; opnum < ARRAY_LENGTH(opcode_table_source); opnum++)
658
 
                opcode_table[opcode_table_source[opnum].opcode] = opcode_table_source[opnum].func;
659
 
 
660
 
        /* build the flags map (static but it doesn't hurt to regenerate it) */
661
 
        for (entry = 0; entry < ARRAY_LENGTH(flags_map); entry++)
 
561
        // compute hi pointers for each register
 
562
        for (int regnum = 0; regnum < ARRAY_LENGTH(int_register_map); regnum++)
 
563
                if (int_register_map[regnum] != 0)
 
564
                {
 
565
                        m_reglo[int_register_map[regnum]] = &m_state.r[regnum].w.l;
 
566
                        m_reghi[int_register_map[regnum]] = &m_state.r[regnum].w.h;
 
567
                }
 
568
 
 
569
        // build the flags map (static but it doesn't hurt to regenerate it)
 
570
        for (int entry = 0; entry < ARRAY_LENGTH(flags_map); entry++)
662
571
        {
663
572
                UINT8 flags = 0;
664
 
                if (entry & 0x001) flags |= DRCUML_FLAG_C;
665
 
                if (entry & 0x004) flags |= DRCUML_FLAG_U;
666
 
                if (entry & 0x040) flags |= DRCUML_FLAG_Z;
667
 
                if (entry & 0x080) flags |= DRCUML_FLAG_S;
668
 
                if (entry & 0x800) flags |= DRCUML_FLAG_V;
 
573
                if (entry & 0x001) flags |= FLAG_C;
 
574
                if (entry & 0x004) flags |= FLAG_U;
 
575
                if (entry & 0x040) flags |= FLAG_Z;
 
576
                if (entry & 0x080) flags |= FLAG_S;
 
577
                if (entry & 0x800) flags |= FLAG_V;
669
578
                flags_map[entry] = flags;
670
579
        }
671
 
        for (entry = 0; entry < ARRAY_LENGTH(flags_unmap); entry++)
 
580
        for (int entry = 0; entry < ARRAY_LENGTH(flags_unmap); entry++)
672
581
        {
673
582
                UINT32 flags = 0;
674
 
                if (entry & DRCUML_FLAG_C) flags |= 0x001;
675
 
                if (entry & DRCUML_FLAG_U) flags |= 0x004;
676
 
                if (entry & DRCUML_FLAG_Z) flags |= 0x040;
677
 
                if (entry & DRCUML_FLAG_S) flags |= 0x080;
678
 
                if (entry & DRCUML_FLAG_V) flags |= 0x800;
 
583
                if (entry & FLAG_C) flags |= 0x001;
 
584
                if (entry & FLAG_U) flags |= 0x004;
 
585
                if (entry & FLAG_Z) flags |= 0x040;
 
586
                if (entry & FLAG_S) flags |= 0x080;
 
587
                if (entry & FLAG_V) flags |= 0x800;
679
588
                flags_unmap[entry] = flags;
680
589
        }
681
590
 
682
 
        /* compute hi pointers for each register */
683
 
        for (regnum = 0; regnum < ARRAY_LENGTH(int_register_map); regnum++)
684
 
                if (int_register_map[regnum] != 0)
685
 
                {
686
 
                        drcbe->reglo[int_register_map[regnum]] = &drcbe->state.r[regnum].w.l;
687
 
                        drcbe->reghi[int_register_map[regnum]] = &drcbe->state.r[regnum].w.h;
688
 
                }
 
591
        // build the opcode table (static but it doesn't hurt to regenerate it)
 
592
        for (int opnum = 0; opnum < ARRAY_LENGTH(s_opcode_table_source); opnum++)
 
593
                s_opcode_table[s_opcode_table_source[opnum].opcode] = s_opcode_table_source[opnum].func;
689
594
 
690
 
        /* create the log */
 
595
        // create the log
691
596
        if (flags & DRCUML_OPTION_LOG_NATIVE)
692
 
                drcbe->log = x86log_create_context("drcbex86.asm");
693
 
 
694
 
        return drcbe;
695
 
}
696
 
 
697
 
 
698
 
/*-------------------------------------------------
699
 
    drcbex86_free - free back-end specific state
700
 
-------------------------------------------------*/
701
 
 
702
 
static void drcbex86_free(drcbe_state *drcbe)
703
 
{
704
 
        /* free the log context */
705
 
        if (drcbe->log != NULL)
706
 
                x86log_free_context(drcbe->log);
707
 
}
708
 
 
709
 
 
710
 
/*-------------------------------------------------
711
 
    drcbex86_reset - reset back-end specific state
712
 
-------------------------------------------------*/
713
 
 
714
 
static void drcbex86_reset(drcbe_state *drcbe)
715
 
{
716
 
        UINT32 (*cpuid_ecx_stub)(void);
717
 
        x86code **dst;
718
 
        int regnum;
719
 
 
720
 
        /* output a note to the log */
721
 
        if (drcbe->log != NULL)
722
 
                x86log_printf(drcbe->log, "\n\n===========\nCACHE RESET\n===========\n\n");
723
 
 
724
 
        /* generate a little bit of glue code to set up the environment */
725
 
        dst = (x86code **)drccache_begin_codegen(drcbe->cache, 500);
726
 
        if (dst == NULL)
 
597
                m_log = x86log_create_context("drcbex86.asm");
 
598
}
 
599
 
 
600
 
 
601
//-------------------------------------------------
 
602
//  ~drcbe_x86 - destructor
 
603
//-------------------------------------------------
 
604
 
 
605
drcbe_x86::~drcbe_x86()
 
606
{
 
607
        // free the log context
 
608
        if (m_log != NULL)
 
609
                x86log_free_context(m_log);
 
610
}
 
611
 
 
612
 
 
613
//-------------------------------------------------
 
614
//  reset - reset back-end specific state
 
615
//-------------------------------------------------
 
616
 
 
617
void drcbe_x86::reset()
 
618
{
 
619
        // output a note to the log
 
620
        if (m_log != NULL)
 
621
                x86log_printf(m_log, "\n\n===========\nCACHE RESET\n===========\n\n");
 
622
 
 
623
        // generate a little bit of glue code to set up the environment
 
624
        drccodeptr *cachetop = m_cache.begin_codegen(500);
 
625
        if (cachetop == NULL)
727
626
                fatalerror("Out of cache space after a reset!");
728
627
 
729
 
        /* generate a simple CPUID stub */
730
 
        cpuid_ecx_stub = (UINT32 (*)(void))*dst;
 
628
        x86code *dst = (x86code *)*cachetop;
 
629
 
 
630
        // generate a simple CPUID stub
 
631
        UINT32 (*cpuid_ecx_stub)(void) = (UINT32 (*)(void))dst;
731
632
        emit_push_r32(dst, REG_EBX);                                                                                                            // push  ebx
732
633
        emit_mov_r32_imm(dst, REG_EAX, 1);                                                                                                      // mov   eax,1
733
634
        emit_cpuid(dst);                                                                                                                                        // cpuid
735
636
        emit_pop_r32(dst, REG_EBX);                                                                                                                     // pop   ebx
736
637
        emit_ret(dst);                                                                                                                                          // ret
737
638
 
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);
740
641
 
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);
756
657
 
757
 
        /* generate an exit point */
758
 
        drcbe->exit = *dst;
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
 
659
        m_exit = dst;
 
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);
769
670
 
770
 
        /* generate a no code point */
771
 
        drcbe->nocode = *dst;
 
671
        // generate a no code point
 
672
        m_nocode = dst;
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);
775
676
 
776
 
        /* generate a save subroutine */
777
 
        drcbe->save = *dst;
 
677
        // generate a save subroutine
 
678
        m_save = dst;
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++)
788
689
        {
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]);
793
694
                else
794
695
                {
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);
797
698
                }
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);
800
701
        }
801
 
        for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.f); regnum++)
 
702
        for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
802
703
        {
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);
809
710
        }
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);
813
714
 
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
 
716
        m_restore = dst;
 
717
        for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
817
718
        {
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));
822
723
                else
823
724
                {
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);
826
727
                }
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);
829
730
        }
830
 
        for (regnum = 0; regnum < ARRAY_LENGTH(drcbe->state.f); regnum++)
 
731
        for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
831
732
        {
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);
838
739
        }
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);
851
 
 
852
 
        /* finish up codegen */
853
 
        drccache_end_codegen(drcbe->cache);
854
 
        drcbe->logged_common = TRUE;
855
 
 
856
 
        /* reset our hash tables */
857
 
        drchash_reset(drcbe->hash);
858
 
        drchash_set_default_codeptr(drcbe->hash, drcbe->nocode);
859
 
}
860
 
 
861
 
 
862
 
/*-------------------------------------------------
863
 
    drcbex86_execute - execute a block of code
864
 
    referenced by the given handle
865
 
-------------------------------------------------*/
866
 
 
867
 
static int drcbex86_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
868
 
{
869
 
        /* call our entry point which will jump to the destination */
870
 
        return (*drcbe->entry)((x86code *)drcuml_handle_codeptr(entry));
871
 
}
872
 
 
873
 
 
874
 
/*-------------------------------------------------
875
 
    drcbex86_generate - generate code
876
 
-------------------------------------------------*/
877
 
 
878
 
static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drcuml_instruction *instlist, UINT32 numinst)
879
 
{
 
750
        if (m_log != NULL && !m_logged_common)
 
751
                x86log_disasm_code_range(m_log, "restore", m_restore, dst);
 
752
 
 
753
        // finish up codegen
 
754
        *cachetop = dst;
 
755
        m_cache.end_codegen();
 
756
        m_logged_common = true;
 
757
 
 
758
        // reset our hash tables
 
759
        m_hash.reset();
 
760
        m_hash.set_default_codeptr(m_nocode);
 
761
}
 
762
 
 
763
 
 
764
//-------------------------------------------------
 
765
//  drcbex86_execute - execute a block of code
 
766
//  referenced by the given handle
 
767
//-------------------------------------------------
 
768
 
 
769
int drcbe_x86::execute(code_handle &entry)
 
770
{
 
771
        // call our entry point which will jump to the destination
 
772
        return (*m_entry)((x86code *)entry.codeptr());
 
773
}
 
774
 
 
775
 
 
776
//-------------------------------------------------
 
777
//  drcbex86_generate - generate code
 
778
//-------------------------------------------------
 
779
 
 
780
void drcbe_x86::generate(drcuml_block &block, const instruction *instlist, UINT32 numinst)
 
781
{
 
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);
 
786
 
 
787
        // begin codegen; fail if we can't
 
788
        drccodeptr *cachetop = m_cache.begin_codegen(numinst * 8 * 4);
 
789
        if (cachetop == NULL)
 
790
                block.abort();
 
791
 
 
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);
 
794
        x86code *dst = base;
 
795
 
 
796
        // generate code
 
797
        astring tempstring;
880
798
        const char *blockname = NULL;
881
 
        char blockbuffer[100];
882
 
        drccodeptr *cachetop;
883
 
        x86code *base;
884
 
        x86code *dst;
885
 
        int inum;
886
 
 
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);
891
 
 
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);
896
 
 
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);
899
 
        dst = base;
900
 
 
901
 
        /* generate code */
902
 
        for (inum = 0; inum < numinst; inum++)
 
799
        for (int inum = 0; inum < numinst; inum++)
903
800
        {
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));
906
803
 
907
 
                /* add a comment */
908
 
                if (drcbe->log != NULL)
 
804
                // add a comment
 
805
                if (m_log != NULL)
909
806
                {
910
 
                        char dasm[256];
911
 
                        drcuml_disasm(inst, dasm, drcbe->drcuml);
912
 
                        x86log_add_comment(drcbe->log, dst, "%s", dasm);
 
807
                        astring dasm;
 
808
                        inst.disasm(dasm, &m_drcuml);
 
809
                        x86log_add_comment(m_log, dst, "%s", dasm.cstr());
913
810
                }
914
811
 
915
 
                /* extract a blockname */
 
812
                // extract a blockname
916
813
                if (blockname == NULL)
917
814
                {
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)
921
 
                        {
922
 
                                sprintf(blockbuffer, "Code: mode=%d PC=%08X", (UINT32)inst->param[0].value, (offs_t)inst->param[1].value);
923
 
                                blockname = blockbuffer;
924
 
                        }
 
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());
925
819
                }
926
820
 
927
 
                /* generate code */
928
 
                dst = (*opcode_table[inst->opcode])(drcbe, dst, inst);
 
821
                // generate code
 
822
                (this->*s_opcode_table[inst.opcode()])(dst, inst);
929
823
        }
930
824
 
931
 
        /* complete codegen */
 
825
        // complete codegen
932
826
        *cachetop = (drccodeptr)dst;
933
 
        drccache_end_codegen(drcbe->cache);
934
 
 
935
 
        /* log it */
936
 
        if (drcbe->log != NULL)
937
 
                x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drccache_top(drcbe->cache));
938
 
 
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);
943
 
}
944
 
 
945
 
 
946
 
/*-------------------------------------------------
947
 
    drcbex86_hash_exists - return true if the
948
 
    given mode/pc exists in the hash table
949
 
-------------------------------------------------*/
950
 
 
951
 
static int drcbex86_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
952
 
{
953
 
        return drchash_code_exists(drcbe->hash, mode, pc);
954
 
}
955
 
 
956
 
 
957
 
/*-------------------------------------------------
958
 
    drcbex86_get_info - return information about
959
 
    the back-end implementation
960
 
-------------------------------------------------*/
961
 
 
962
 
static void drcbex86_get_info(drcbe_state *state, drcbe_info *info)
963
 
{
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)
966
 
                        break;
967
 
        info->direct_fregs = 0;
968
 
}
969
 
 
970
 
 
971
 
 
972
 
/***************************************************************************
973
 
    COMPILE HELPERS
974
 
***************************************************************************/
975
 
 
976
 
/*-------------------------------------------------
977
 
    param_normalize - convert a full parameter
978
 
    into a reduced set
979
 
-------------------------------------------------*/
980
 
 
981
 
static void param_normalize(drcbe_state *drcbe, const drcuml_parameter *src, drcuml_parameter *dest, UINT32 allowed)
982
 
{
983
 
        int regnum;
984
 
 
985
 
        switch (src->type)
986
 
        {
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;
992
 
                        break;
993
 
 
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;
999
 
                        break;
1000
 
 
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];
1006
 
                        if (regnum != 0)
1007
 
                        {
1008
 
                                dest->type = DRCUML_PTYPE_INT_REGISTER;
1009
 
                                dest->value = regnum;
1010
 
                        }
1011
 
                        else
1012
 
                        {
1013
 
                                dest->type = DRCUML_PTYPE_MEMORY;
1014
 
                                dest->value = (FPTR)&drcbe->state.r[src->value - DRCUML_REG_I0];
1015
 
                        }
1016
 
                        break;
1017
 
 
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];
1024
 
                        break;
1025
 
 
1026
 
                /* everything else is unexpected */
1027
 
                default:
1028
 
                        fatalerror("Unexpected parameter type");
1029
 
                        break;
1030
 
        }
1031
 
}
1032
 
 
1033
 
 
1034
 
/*-------------------------------------------------
1035
 
    param_normalize_1 - normalize a single
1036
 
    parameter instruction
1037
 
-------------------------------------------------*/
1038
 
 
1039
 
static void param_normalize_1(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0)
1040
 
{
1041
 
        assert(inst->numparams == 1);
1042
 
        param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1043
 
}
1044
 
 
1045
 
 
1046
 
/*-------------------------------------------------
1047
 
    param_normalize_2 - normalize a 2
1048
 
    parameter instruction
1049
 
-------------------------------------------------*/
1050
 
 
1051
 
static void param_normalize_2(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1)
1052
 
{
1053
 
        assert(inst->numparams == 2);
1054
 
        param_normalize(drcbe, &inst->param[0], dest0, allowed0);
1055
 
        param_normalize(drcbe, &inst->param[1], dest1, allowed1);
1056
 
}
1057
 
 
1058
 
 
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
 
-------------------------------------------------*/
1065
 
 
1066
 
static void param_normalize_2_commutative(drcbe_state *drcbe, const drcuml_instruction *inst, drcuml_parameter *dest0, UINT32 allowed0, drcuml_parameter *dest1, UINT32 allowed1)
1067
 
{
1068
 
        param_normalize_2(drcbe, inst, dest0, allowed0, dest1, allowed1);
1069
 
 
1070
 
        /* if the inner parameter is a memory operand, push it to the outer */
1071
 
        if (dest0->type == DRCUML_PTYPE_MEMORY)
1072
 
        {
1073
 
                drcuml_parameter temp = *dest0;
1074
 
                *dest0 = *dest1;
1075
 
                *dest1 = temp;
1076
 
        }
1077
 
 
1078
 
        /* if the inner parameter is an immediate, push it to the outer */
1079
 
        if (dest0->type == DRCUML_PTYPE_IMMEDIATE)
1080
 
        {
1081
 
                drcuml_parameter temp = *dest0;
1082
 
                *dest0 = *dest1;
1083
 
                *dest1 = temp;
1084
 
        }
1085
 
}
1086
 
 
1087
 
 
1088
 
/*-------------------------------------------------
1089
 
    param_normalize_3 - normalize a 3
1090
 
    parameter instruction
1091
 
-------------------------------------------------*/
1092
 
 
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)
1094
 
{
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);
1099
 
}
1100
 
 
1101
 
 
1102
 
/*-------------------------------------------------
1103
 
    param_normalize_3_commutative - normalize a 3
1104
 
    parameter instruction, shuffling the
1105
 
    parameters on the assumption that the last
1106
 
    2 can be swapped
1107
 
-------------------------------------------------*/
1108
 
 
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)
1110
 
{
1111
 
        param_normalize_3(drcbe, inst, dest0, allowed0, dest1, allowed1, dest2, allowed2);
1112
 
 
1113
 
        /* if the inner parameter is a memory operand, push it to the outer */
1114
 
        if (dest1->type == DRCUML_PTYPE_MEMORY)
1115
 
        {
1116
 
                drcuml_parameter temp = *dest1;
1117
 
                *dest1 = *dest2;
1118
 
                *dest2 = temp;
1119
 
        }
1120
 
 
1121
 
        /* if the inner parameter is an immediate, push it to the outer */
1122
 
        if (dest1->type == DRCUML_PTYPE_IMMEDIATE)
1123
 
        {
1124
 
                drcuml_parameter temp = *dest1;
1125
 
                *dest1 = *dest2;
1126
 
                *dest2 = temp;
1127
 
        }
1128
 
 
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)
1131
 
        {
1132
 
                drcuml_parameter temp = *dest1;
1133
 
                *dest1 = *dest2;
1134
 
                *dest2 = temp;
1135
 
        }
1136
 
}
1137
 
 
1138
 
 
1139
 
/*-------------------------------------------------
1140
 
    param_normalize_4 - normalize a 4
1141
 
    parameter instruction
1142
 
-------------------------------------------------*/
1143
 
 
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)
1145
 
{
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);
1151
 
}
1152
 
 
1153
 
 
1154
 
/*-------------------------------------------------
1155
 
    param_normalize_4_commutative - normalize a 4
1156
 
    parameter instruction, shuffling the
1157
 
    parameters on the assumption that the last
1158
 
    2 can be swapped
1159
 
-------------------------------------------------*/
1160
 
 
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)
1162
 
{
1163
 
        param_normalize_4(drcbe, inst, dest0, allowed0, dest1, allowed1, dest2, allowed2, dest3, allowed3);
1164
 
 
1165
 
        /* if the inner parameter is a memory operand, push it to the outer */
1166
 
        if (dest2->type == DRCUML_PTYPE_MEMORY)
1167
 
        {
1168
 
                drcuml_parameter temp = *dest2;
1169
 
                *dest2 = *dest3;
1170
 
                *dest3 = temp;
1171
 
        }
1172
 
 
1173
 
        /* if the inner parameter is an immediate, push it to the outer */
1174
 
        if (dest2->type == DRCUML_PTYPE_IMMEDIATE)
1175
 
        {
1176
 
                drcuml_parameter temp = *dest2;
1177
 
                *dest2 = *dest3;
1178
 
                *dest3 = temp;
1179
 
        }
1180
 
 
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)
1183
 
        {
1184
 
                drcuml_parameter temp = *dest2;
1185
 
                *dest2 = *dest3;
1186
 
                *dest3 = temp;
1187
 
        }
1188
 
}
1189
 
 
1190
 
 
1191
 
 
1192
 
/***************************************************************************
1193
 
    EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
1194
 
***************************************************************************/
1195
 
 
1196
 
/*-------------------------------------------------
1197
 
    emit_mov_r32_p32 - move a 32-bit parameter
1198
 
    into a register
1199
 
-------------------------------------------------*/
1200
 
 
1201
 
static void emit_mov_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param)
1202
 
{
1203
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1204
 
        {
1205
 
                if (param->value == 0)
1206
 
                        emit_xor_r32_r32(dst, reg, reg);                                                                                        // xor   reg,reg
1207
 
                else
1208
 
                        emit_mov_r32_imm(dst, reg, param->value);                                                                       // mov   reg,param
1209
 
        }
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)
1213
 
        {
1214
 
                if (reg != param->value)
1215
 
                        emit_mov_r32_r32(dst, reg, param->value);                                                                       // mov   reg,param
1216
 
        }
1217
 
}
1218
 
 
1219
 
 
1220
 
/*-------------------------------------------------
1221
 
    emit_mov_r32_p32_keepflags - move a 32-bit
1222
 
    parameter into a register without affecting
1223
 
    any flags
1224
 
-------------------------------------------------*/
1225
 
 
1226
 
static void emit_mov_r32_p32_keepflags(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param)
1227
 
{
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)
1231
 
        {
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]
1234
 
        }
1235
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1236
 
        {
1237
 
                if (reg != param->value)
1238
 
                        emit_mov_r32_r32(dst, reg, param->value);                                                                       // mov   reg,param
1239
 
        }
1240
 
}
1241
 
 
1242
 
 
1243
 
/*-------------------------------------------------
1244
 
    emit_mov_m32_p32 - move a 32-bit parameter
1245
 
    into a memory location
1246
 
-------------------------------------------------*/
1247
 
 
1248
 
static void emit_mov_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param)
1249
 
{
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)
1253
 
        {
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
1257
 
        }
1258
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1259
 
                emit_mov_m32_r32(dst, MEMPARAMS, param->value);                                                                 // mov   [mem],param
1260
 
}
1261
 
 
1262
 
 
1263
 
/*-------------------------------------------------
1264
 
    emit_mov_p32_r32 - move a register into a
1265
 
    32-bit parameter
1266
 
-------------------------------------------------*/
1267
 
 
1268
 
static void emit_mov_p32_r32(drcbe_state *drcbe, x86code **dst, const drcuml_parameter *param, UINT8 reg)
1269
 
{
1270
 
        assert(param->type != DRCUML_PTYPE_IMMEDIATE);
1271
 
        if (param->type == DRCUML_PTYPE_MEMORY)
1272
 
        {
1273
 
                emit_mov_m32_r32(dst, MABS(param->value), reg);                                                                 // mov   [param],reg
1274
 
                set_last_lower_reg(drcbe, *dst, param, reg);
1275
 
        }
1276
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1277
 
        {
1278
 
                if (reg != param->value)
1279
 
                        emit_mov_r32_r32(dst, param->value, reg);                                                                       // mov   param,reg
1280
 
        }
1281
 
}
1282
 
 
1283
 
 
1284
 
/*-------------------------------------------------
1285
 
    emit_add_r32_p32 - add operation to a 32-bit
1286
 
    register from a 32-bit parameter
1287
 
-------------------------------------------------*/
1288
 
 
1289
 
static void emit_add_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1290
 
{
1291
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1292
 
        {
1293
 
                if (inst->flags != 0 || param->value != 0)
1294
 
                        emit_add_r32_imm(dst, reg, param->value);                                                                       // add   reg,param
1295
 
        }
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
1300
 
}
1301
 
 
1302
 
 
1303
 
/*-------------------------------------------------
1304
 
    emit_add_m32_p32 - add operation to a 32-bit
1305
 
    memory location from a 32-bit parameter
1306
 
-------------------------------------------------*/
1307
 
 
1308
 
static void emit_add_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1309
 
{
1310
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1311
 
        {
1312
 
                if (inst->flags != 0 || param->value != 0)
1313
 
                        emit_add_m32_imm(dst, MEMPARAMS, param->value);                                                         // add   [dest],param
1314
 
        }
1315
 
        else
1316
 
        {
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
1320
 
        }
1321
 
}
1322
 
 
1323
 
 
1324
 
/*-------------------------------------------------
1325
 
    emit_adc_r32_p32 - adc operation to a 32-bit
1326
 
    register from a 32-bit parameter
1327
 
-------------------------------------------------*/
1328
 
 
1329
 
static void emit_adc_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1330
 
{
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
1337
 
}
1338
 
 
1339
 
 
1340
 
/*-------------------------------------------------
1341
 
    emit_adc_m32_p32 - adc operation to a 32-bit
1342
 
    memory location from a 32-bit parameter
1343
 
-------------------------------------------------*/
1344
 
 
1345
 
static void emit_adc_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1346
 
{
1347
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1348
 
                emit_adc_m32_imm(dst, MEMPARAMS, param->value);                                                                 // adc   [dest],param
1349
 
        else
1350
 
        {
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
1354
 
        }
1355
 
}
1356
 
 
1357
 
 
1358
 
/*-------------------------------------------------
1359
 
    emit_sub_r32_p32 - sub operation to a 32-bit
1360
 
    register from a 32-bit parameter
1361
 
-------------------------------------------------*/
1362
 
 
1363
 
static void emit_sub_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1364
 
{
1365
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1366
 
        {
1367
 
                if (inst->flags != 0 || param->value != 0)
1368
 
                        emit_sub_r32_imm(dst, reg, param->value);                                                                       // sub   reg,param
1369
 
        }
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
1374
 
}
1375
 
 
1376
 
 
1377
 
/*-------------------------------------------------
1378
 
    emit_sub_m32_p32 - sub operation to a 32-bit
1379
 
    memory location from a 32-bit parameter
1380
 
-------------------------------------------------*/
1381
 
 
1382
 
static void emit_sub_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1383
 
{
1384
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1385
 
        {
1386
 
                if (inst->flags != 0 || param->value != 0)
1387
 
                        emit_sub_m32_imm(dst, MEMPARAMS, param->value);                                                         // sub   [dest],param
1388
 
        }
1389
 
        else
1390
 
        {
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
1394
 
        }
1395
 
}
1396
 
 
1397
 
 
1398
 
/*-------------------------------------------------
1399
 
    emit_sbb_r32_p32 - sbb operation to a 32-bit
1400
 
    register from a 32-bit parameter
1401
 
-------------------------------------------------*/
1402
 
 
1403
 
static void emit_sbb_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1404
 
{
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
1411
 
}
1412
 
 
1413
 
 
1414
 
/*-------------------------------------------------
1415
 
    emit_sbb_m32_p32 - sbb operation to a 32-bit
1416
 
    memory location from a 32-bit parameter
1417
 
-------------------------------------------------*/
1418
 
 
1419
 
static void emit_sbb_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1420
 
{
1421
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1422
 
                emit_sbb_m32_imm(dst, MEMPARAMS, param->value);                                                                 // sbb   [dest],param
1423
 
        else
1424
 
        {
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
1428
 
        }
1429
 
}
1430
 
 
1431
 
 
1432
 
/*-------------------------------------------------
1433
 
    emit_cmp_r32_p32 - cmp operation to a 32-bit
1434
 
    register from a 32-bit parameter
1435
 
-------------------------------------------------*/
1436
 
 
1437
 
static void emit_cmp_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1438
 
{
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
1445
 
}
1446
 
 
1447
 
 
1448
 
/*-------------------------------------------------
1449
 
    emit_cmp_m32_p32 - cmp operation to a 32-bit
1450
 
    memory location from a 32-bit parameter
1451
 
-------------------------------------------------*/
1452
 
 
1453
 
static void emit_cmp_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1454
 
{
1455
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1456
 
                emit_cmp_m32_imm(dst, MEMPARAMS, param->value);                                                                 // cmp   [dest],param
1457
 
        else
1458
 
        {
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
1462
 
        }
1463
 
}
1464
 
 
1465
 
 
1466
 
/*-------------------------------------------------
1467
 
    emit_and_r32_p32 - and operation to a 32-bit
1468
 
    register from a 32-bit parameter
1469
 
-------------------------------------------------*/
1470
 
 
1471
 
static void emit_and_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1472
 
{
1473
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1474
 
        {
1475
 
                if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1476
 
                        /* skip */;
1477
 
                else if (inst->flags == 0 && (UINT32)param->value == 0)
1478
 
                        emit_xor_r32_r32(dst, reg, reg);                                                                                        // xor   reg,reg
1479
 
                else
1480
 
                        emit_and_r32_imm(dst, reg, param->value);                                                                       // and   reg,param
1481
 
        }
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
1486
 
}
1487
 
 
1488
 
 
1489
 
/*-------------------------------------------------
1490
 
    emit_and_m32_p32 - and operation to a 32-bit
1491
 
    memory location from a 32-bit parameter
1492
 
-------------------------------------------------*/
1493
 
 
1494
 
static void emit_and_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1495
 
{
1496
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1497
 
        {
1498
 
                if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1499
 
                        /* skip */;
1500
 
                else if (inst->flags == 0 && (UINT32)param->value == 0)
1501
 
                        emit_mov_m32_imm(dst, MEMPARAMS, 0);                                                                            // mov   [dest],0
1502
 
                else
1503
 
                        emit_and_m32_imm(dst, MEMPARAMS, param->value);                                                         // and   [dest],param
1504
 
        }
1505
 
        else
1506
 
        {
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
1510
 
        }
1511
 
}
1512
 
 
1513
 
 
1514
 
/*-------------------------------------------------
1515
 
    emit_test_r32_p32 - test operation to a 32-bit
1516
 
    register from a 32-bit parameter
1517
 
-------------------------------------------------*/
1518
 
 
1519
 
static void emit_test_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1520
 
{
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
1527
 
}
1528
 
 
1529
 
 
1530
 
/*-------------------------------------------------
1531
 
    emit_test_m32_p32 - test operation to a 32-bit
1532
 
    memory location from a 32-bit parameter
1533
 
-------------------------------------------------*/
1534
 
 
1535
 
static void emit_test_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1536
 
{
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)
1540
 
        {
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
1543
 
        }
1544
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
1545
 
                emit_test_m32_r32(dst, MEMPARAMS, param->value);                                                                // test  [dest],param
1546
 
}
1547
 
 
1548
 
 
1549
 
/*-------------------------------------------------
1550
 
    emit_or_r32_p32 - or operation to a 32-bit
1551
 
    register from a 32-bit parameter
1552
 
-------------------------------------------------*/
1553
 
 
1554
 
static void emit_or_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1555
 
{
1556
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1557
 
        {
1558
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1559
 
                        /* skip */;
1560
 
                else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
 
827
        m_cache.end_codegen();
 
828
 
 
829
        // log it
 
830
        if (m_log != NULL)
 
831
                x86log_disasm_code_range(m_log, (blockname == NULL) ? "Unknown block" : blockname, base, m_cache.top());
 
832
 
 
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);
 
837
}
 
838
 
 
839
 
 
840
//-------------------------------------------------
 
841
//  drcbex86_hash_exists - return true if the
 
842
//  given mode/pc exists in the hash table
 
843
//-------------------------------------------------
 
844
 
 
845
bool drcbe_x86::hash_exists(UINT32 mode, UINT32 pc)
 
846
{
 
847
        return m_hash.code_exists(mode, pc);
 
848
}
 
849
 
 
850
 
 
851
//-------------------------------------------------
 
852
//  drcbex86_get_info - return information about
 
853
//  the back-end implementation
 
854
//-------------------------------------------------
 
855
 
 
856
void drcbe_x86::get_info(drcbe_info &info)
 
857
{
 
858
        for (info.direct_iregs = 0; info.direct_iregs < REG_I_COUNT; info.direct_iregs++)
 
859
                if (int_register_map[info.direct_iregs] == 0)
 
860
                        break;
 
861
        info.direct_fregs = 0;
 
862
}
 
863
 
 
864
 
 
865
 
 
866
//**************************************************************************
 
867
//  EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
 
868
//**************************************************************************
 
869
 
 
870
//-------------------------------------------------
 
871
//  emit_mov_r32_p32 - move a 32-bit parameter
 
872
//  into a register
 
873
//-------------------------------------------------
 
874
 
 
875
void drcbe_x86::emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param)
 
876
{
 
877
        if (param.is_immediate())
 
878
        {
 
879
                if (param.immediate() == 0)
 
880
                        emit_xor_r32_r32(dst, reg, reg);                                                                                        // xor   reg,reg
 
881
                else
 
882
                        emit_mov_r32_imm(dst, reg, param.immediate());                                                                  // mov   reg,param
 
883
        }
 
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())
 
887
        {
 
888
                if (reg != param.ireg())
 
889
                        emit_mov_r32_r32(dst, reg, param.ireg());                                                                       // mov   reg,param
 
890
        }
 
891
}
 
892
 
 
893
 
 
894
//-------------------------------------------------
 
895
//  emit_mov_r32_p32_keepflags - move a 32-bit
 
896
//  parameter into a register without affecting
 
897
//  any flags
 
898
//-------------------------------------------------
 
899
 
 
900
void drcbe_x86::emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param)
 
901
{
 
902
        if (param.is_immediate())
 
903
                emit_mov_r32_imm(dst, reg, param.immediate());                                                                          // mov   reg,param
 
904
        else if (param.is_memory())
 
905
        {
 
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]
 
908
        }
 
909
        else if (param.is_int_register())
 
910
        {
 
911
                if (reg != param.ireg())
 
912
                        emit_mov_r32_r32(dst, reg, param.ireg());                                                                       // mov   reg,param
 
913
        }
 
914
}
 
915
 
 
916
 
 
917
//-------------------------------------------------
 
918
//  emit_mov_m32_p32 - move a 32-bit parameter
 
919
//  into a memory location
 
920
//-------------------------------------------------
 
921
 
 
922
void drcbe_x86::emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param)
 
923
{
 
924
        if (param.is_immediate())
 
925
                emit_mov_m32_imm(dst, memref, param.immediate());                                                                       // mov   [mem],param
 
926
        else if (param.is_memory())
 
927
        {
 
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
 
931
        }
 
932
        else if (param.is_int_register())
 
933
                emit_mov_m32_r32(dst, memref, param.ireg());                                                                    // mov   [mem],param
 
934
}
 
935
 
 
936
 
 
937
//-------------------------------------------------
 
938
//  emit_mov_p32_r32 - move a register into a
 
939
//  32-bit parameter
 
940
//-------------------------------------------------
 
941
 
 
942
void drcbe_x86::emit_mov_p32_r32(x86code *&dst, const be_parameter &param, UINT8 reg)
 
943
{
 
944
        assert(!param.is_immediate());
 
945
        if (param.is_memory())
 
946
        {
 
947
                emit_mov_m32_r32(dst, MABS(param.memory()), reg);                                                                       // mov   [param],reg
 
948
                set_last_lower_reg(dst, param, reg);
 
949
        }
 
950
        else if (param.is_int_register())
 
951
        {
 
952
                if (reg != param.ireg())
 
953
                        emit_mov_r32_r32(dst, param.ireg(), reg);                                                                       // mov   param,reg
 
954
        }
 
955
}
 
956
 
 
957
 
 
958
//-------------------------------------------------
 
959
//  emit_add_r32_p32 - add operation to a 32-bit
 
960
//  register from a 32-bit parameter
 
961
//-------------------------------------------------
 
962
 
 
963
void drcbe_x86::emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
964
{
 
965
        if (param.is_immediate())
 
966
        {
 
967
                if (inst.flags() != 0 || param.immediate() != 0)
 
968
                        emit_add_r32_imm(dst, reg, param.immediate());                                                                  // add   reg,param
 
969
        }
 
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
 
974
}
 
975
 
 
976
 
 
977
//-------------------------------------------------
 
978
//  emit_add_m32_p32 - add operation to a 32-bit
 
979
//  memory location from a 32-bit parameter
 
980
//-------------------------------------------------
 
981
 
 
982
void drcbe_x86::emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
983
{
 
984
        if (param.is_immediate())
 
985
        {
 
986
                if (inst.flags() != 0 || param.immediate() != 0)
 
987
                        emit_add_m32_imm(dst, memref, param.immediate());                                                               // add   [dest],param
 
988
        }
 
989
        else
 
990
        {
 
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
 
994
        }
 
995
}
 
996
 
 
997
 
 
998
//-------------------------------------------------
 
999
//  emit_adc_r32_p32 - adc operation to a 32-bit
 
1000
//  register from a 32-bit parameter
 
1001
//-------------------------------------------------
 
1002
 
 
1003
void drcbe_x86::emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1004
{
 
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
 
1011
}
 
1012
 
 
1013
 
 
1014
//-------------------------------------------------
 
1015
//  emit_adc_m32_p32 - adc operation to a 32-bit
 
1016
//  memory location from a 32-bit parameter
 
1017
//-------------------------------------------------
 
1018
 
 
1019
void drcbe_x86::emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1020
{
 
1021
        if (param.is_immediate())
 
1022
                emit_adc_m32_imm(dst, memref, param.immediate());                                                                       // adc   [dest],param
 
1023
        else
 
1024
        {
 
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
 
1028
        }
 
1029
}
 
1030
 
 
1031
 
 
1032
//-------------------------------------------------
 
1033
//  emit_sub_r32_p32 - sub operation to a 32-bit
 
1034
//  register from a 32-bit parameter
 
1035
//-------------------------------------------------
 
1036
 
 
1037
void drcbe_x86::emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1038
{
 
1039
        if (param.is_immediate())
 
1040
        {
 
1041
                if (inst.flags() != 0 || param.immediate() != 0)
 
1042
                        emit_sub_r32_imm(dst, reg, param.immediate());                                                                  // sub   reg,param
 
1043
        }
 
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
 
1048
}
 
1049
 
 
1050
 
 
1051
//-------------------------------------------------
 
1052
//  emit_sub_m32_p32 - sub operation to a 32-bit
 
1053
//  memory location from a 32-bit parameter
 
1054
//-------------------------------------------------
 
1055
 
 
1056
void drcbe_x86::emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1057
{
 
1058
        if (param.is_immediate())
 
1059
        {
 
1060
                if (inst.flags() != 0 || param.immediate() != 0)
 
1061
                        emit_sub_m32_imm(dst, memref, param.immediate());                                                               // sub   [dest],param
 
1062
        }
 
1063
        else
 
1064
        {
 
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
 
1068
        }
 
1069
}
 
1070
 
 
1071
 
 
1072
//-------------------------------------------------
 
1073
//  emit_sbb_r32_p32 - sbb operation to a 32-bit
 
1074
//  register from a 32-bit parameter
 
1075
//-------------------------------------------------
 
1076
 
 
1077
void drcbe_x86::emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1078
{
 
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
 
1085
}
 
1086
 
 
1087
 
 
1088
//-------------------------------------------------
 
1089
//  emit_sbb_m32_p32 - sbb operation to a 32-bit
 
1090
//  memory location from a 32-bit parameter
 
1091
//-------------------------------------------------
 
1092
 
 
1093
void drcbe_x86::emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1094
{
 
1095
        if (param.is_immediate())
 
1096
                emit_sbb_m32_imm(dst, memref, param.immediate());                                                                       // sbb   [dest],param
 
1097
        else
 
1098
        {
 
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
 
1102
        }
 
1103
}
 
1104
 
 
1105
 
 
1106
//-------------------------------------------------
 
1107
//  emit_cmp_r32_p32 - cmp operation to a 32-bit
 
1108
//  register from a 32-bit parameter
 
1109
//-------------------------------------------------
 
1110
 
 
1111
void drcbe_x86::emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1112
{
 
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
 
1119
}
 
1120
 
 
1121
 
 
1122
//-------------------------------------------------
 
1123
//  emit_cmp_m32_p32 - cmp operation to a 32-bit
 
1124
//  memory location from a 32-bit parameter
 
1125
//-------------------------------------------------
 
1126
 
 
1127
void drcbe_x86::emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1128
{
 
1129
        if (param.is_immediate())
 
1130
                emit_cmp_m32_imm(dst, memref, param.immediate());                                                                       // cmp   [dest],param
 
1131
        else
 
1132
        {
 
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
 
1136
        }
 
1137
}
 
1138
 
 
1139
 
 
1140
//-------------------------------------------------
 
1141
//  emit_and_r32_p32 - and operation to a 32-bit
 
1142
//  register from a 32-bit parameter
 
1143
//-------------------------------------------------
 
1144
 
 
1145
void drcbe_x86::emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1146
{
 
1147
        if (param.is_immediate())
 
1148
        {
 
1149
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
1150
                        ;// skip
 
1151
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1152
                        emit_xor_r32_r32(dst, reg, reg);                                                                                        // xor   reg,reg
 
1153
                else
 
1154
                        emit_and_r32_imm(dst, reg, param.immediate());                                                                  // and   reg,param
 
1155
        }
 
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
 
1160
}
 
1161
 
 
1162
 
 
1163
//-------------------------------------------------
 
1164
//  emit_and_m32_p32 - and operation to a 32-bit
 
1165
//  memory location from a 32-bit parameter
 
1166
//-------------------------------------------------
 
1167
 
 
1168
void drcbe_x86::emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1169
{
 
1170
        if (param.is_immediate())
 
1171
        {
 
1172
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
1173
                        ;// skip
 
1174
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1175
                        emit_mov_m32_imm(dst, memref, 0);                                                                               // mov   [dest],0
 
1176
                else
 
1177
                        emit_and_m32_imm(dst, memref, param.immediate());                                                               // and   [dest],param
 
1178
        }
 
1179
        else
 
1180
        {
 
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
 
1184
        }
 
1185
}
 
1186
 
 
1187
 
 
1188
//-------------------------------------------------
 
1189
//  emit_test_r32_p32 - test operation to a 32-bit
 
1190
//  register from a 32-bit parameter
 
1191
//-------------------------------------------------
 
1192
 
 
1193
void drcbe_x86::emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1194
{
 
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
 
1201
}
 
1202
 
 
1203
 
 
1204
//-------------------------------------------------
 
1205
//  emit_test_m32_p32 - test operation to a 32-bit
 
1206
//  memory location from a 32-bit parameter
 
1207
//-------------------------------------------------
 
1208
 
 
1209
void drcbe_x86::emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1210
{
 
1211
        if (param.is_immediate())
 
1212
                emit_test_m32_imm(dst, memref, param.immediate());                                                              // test  [dest],param
 
1213
        else if (param.is_memory())
 
1214
        {
 
1215
                emit_mov_r32_p32(dst, REG_EAX, param);                                                                  // mov   reg,param
 
1216
                emit_test_m32_r32(dst, memref, REG_EAX);                                                                                // test  [dest],reg
 
1217
        }
 
1218
        else if (param.is_int_register())
 
1219
                emit_test_m32_r32(dst, memref, param.ireg());                                                           // test  [dest],param
 
1220
}
 
1221
 
 
1222
 
 
1223
//-------------------------------------------------
 
1224
//  emit_or_r32_p32 - or operation to a 32-bit
 
1225
//  register from a 32-bit parameter
 
1226
//-------------------------------------------------
 
1227
 
 
1228
void drcbe_x86::emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1229
{
 
1230
        if (param.is_immediate())
 
1231
        {
 
1232
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1233
                        ;// skip
 
1234
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1561
1235
                        emit_mov_r32_imm(dst, reg, ~0);                                                                                         // mov  reg,-1
1562
1236
                else
1563
 
                        emit_or_r32_imm(dst, reg, param->value);                                                                        // or   reg,param
 
1237
                        emit_or_r32_imm(dst, reg, param.immediate());                                                                   // or   reg,param
1564
1238
        }
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
1569
1243
}
1570
1244
 
1571
1245
 
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
//-------------------------------------------------
1576
1250
 
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 &param, const instruction &inst)
1578
1252
{
1579
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1253
        if (param.is_immediate())
1580
1254
        {
1581
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1582
 
                        /* skip */;
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)
 
1256
                        ;// skip
 
1257
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
1258
                        emit_mov_m32_imm(dst, memref, ~0);                                                                              // mov   [dest],-1
1585
1259
                else
1586
 
                        emit_or_m32_imm(dst, MEMPARAMS, param->value);                                                          // or   [dest],param
 
1260
                        emit_or_m32_imm(dst, memref, param.immediate());                                                                // or   [dest],param
1587
1261
        }
1588
1262
        else
1589
1263
        {
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
1593
1267
        }
1594
1268
}
1595
1269
 
1596
1270
 
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
//-------------------------------------------------
1601
1275
 
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 &param, const instruction &inst)
1603
1277
{
1604
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1278
        if (param.is_immediate())
1605
1279
        {
1606
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1607
 
                        /* skip */;
1608
 
                else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
 
1280
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1281
                        ;// skip
 
1282
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
1609
1283
                        emit_not_r32(dst, reg);                                                                                                         // not   reg
1610
1284
                else
1611
 
                        emit_xor_r32_imm(dst, reg, param->value);                                                                       // xor   reg,param
1612
 
        }
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
1617
 
}
1618
 
 
1619
 
 
1620
 
/*-------------------------------------------------
1621
 
    emit_xor_m32_p32 - xor operation to a 32-bit
1622
 
    memory location from a 32-bit parameter
1623
 
-------------------------------------------------*/
1624
 
 
1625
 
static void emit_xor_m32_p32(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
1626
 
{
1627
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1628
 
        {
1629
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1630
 
                        /* skip */;
1631
 
                else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
1632
 
                        emit_not_m32(dst, MEMPARAMS);                                                                                           // not   [dest]
1633
 
                else
1634
 
                        emit_xor_m32_imm(dst, MEMPARAMS, param->value);                                                         // xor   [dest],param
1635
 
        }
1636
 
        else
1637
 
        {
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
1641
 
        }
1642
 
}
1643
 
 
1644
 
 
1645
 
/*-------------------------------------------------
1646
 
    emit_shl_r32_p32 - shl operation to a 32-bit
1647
 
    register from a 32-bit parameter
1648
 
-------------------------------------------------*/
1649
 
 
1650
 
static void emit_shl_r32_p32(drcbe_state *drcbe, x86code **dst, UINT8 reg, const drcuml_parameter *param, const drcuml_instruction *inst)
1651
 
{
1652
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
1653
 
        {
1654
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1655
 
                        /* skip */;
1656
 
                else
1657
 
                        emit_shl_r32_imm(dst, reg, param->value);                                                                       // shl   reg,param
1658
 
        }
1659
 
        else
1660
 
        {
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
 
1286
        }
 
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
 
1291
}
 
1292
 
 
1293
 
 
1294
//-------------------------------------------------
 
1295
//  emit_xor_m32_p32 - xor operation to a 32-bit
 
1296
//  memory location from a 32-bit parameter
 
1297
//-------------------------------------------------
 
1298
 
 
1299
void drcbe_x86::emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1300
{
 
1301
        if (param.is_immediate())
 
1302
        {
 
1303
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1304
                        ;// skip
 
1305
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
1306
                        emit_not_m32(dst, memref);                                                                                              // not   [dest]
 
1307
                else
 
1308
                        emit_xor_m32_imm(dst, memref, param.immediate());                                                               // xor   [dest],param
 
1309
        }
 
1310
        else
 
1311
        {
 
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
 
1315
        }
 
1316
}
 
1317
 
 
1318
 
 
1319
//-------------------------------------------------
 
1320
//  emit_shl_r32_p32 - shl operation to a 32-bit
 
1321
//  register from a 32-bit parameter
 
1322
//-------------------------------------------------
 
1323
 
 
1324
void drcbe_x86::emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
 
1325
{
 
1326
        if (param.is_immediate())
 
1327
        {
 
1328
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1329
                        ;// skip
 
1330
                else
 
1331
                        emit_shl_r32_imm(dst, reg, param.immediate());                                                                  // shl   reg,param
 
1332
        }
 
1333
        else
 
1334
        {
 
1335
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
1662
1336
                emit_shl_r32_cl(dst, reg);                                                                                                              // shl   reg,cl
1663
1337
        }
1664
1338
}
1665
1339
 
1666
1340
 
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
//-------------------------------------------------
1671
1345
 
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 &param, const instruction &inst)
1673
1347
{
1674
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1348
        if (param.is_immediate())
1675
1349
        {
1676
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1677
 
                        /* skip */;
 
1350
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1351
                        ;// skip
1678
1352
                else
1679
 
                        emit_shl_m32_imm(dst, MEMPARAMS, param->value);                                                         // shl   [dest],param
 
1353
                        emit_shl_m32_imm(dst, memref, param.immediate());                                                               // shl   [dest],param
1680
1354
        }
1681
1355
        else
1682
1356
        {
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
1685
1359
        }
1686
1360
}
1687
1361
 
1688
1362
 
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
//-------------------------------------------------
1693
1367
 
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 &param, const instruction &inst)
1695
1369
{
1696
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1370
        if (param.is_immediate())
1697
1371
        {
1698
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1699
 
                        /* skip */;
 
1372
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1373
                        ;// skip
1700
1374
                else
1701
 
                        emit_shr_r32_imm(dst, reg, param->value);                                                                       // shr   reg,param
 
1375
                        emit_shr_r32_imm(dst, reg, param.immediate());                                                                  // shr   reg,param
1702
1376
        }
1703
1377
        else
1704
1378
        {
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
1707
1381
        }
1708
1382
}
1709
1383
 
1710
1384
 
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
//-------------------------------------------------
1715
1389
 
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 &param, const instruction &inst)
1717
1391
{
1718
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1392
        if (param.is_immediate())
1719
1393
        {
1720
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1721
 
                        /* skip */;
 
1394
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1395
                        ;// skip
1722
1396
                else
1723
 
                        emit_shr_m32_imm(dst, MEMPARAMS, param->value);                                                         // shr   [dest],param
 
1397
                        emit_shr_m32_imm(dst, memref, param.immediate());                                                               // shr   [dest],param
1724
1398
        }
1725
1399
        else
1726
1400
        {
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
1729
1403
        }
1730
1404
}
1731
1405
 
1732
1406
 
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
//-------------------------------------------------
1737
1411
 
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 &param, const instruction &inst)
1739
1413
{
1740
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1414
        if (param.is_immediate())
1741
1415
        {
1742
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1743
 
                        /* skip */;
 
1416
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1417
                        ;// skip
1744
1418
                else
1745
 
                        emit_sar_r32_imm(dst, reg, param->value);                                                                       // sar   reg,param
 
1419
                        emit_sar_r32_imm(dst, reg, param.immediate());                                                                  // sar   reg,param
1746
1420
        }
1747
1421
        else
1748
1422
        {
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
1751
1425
        }
1752
1426
}
1753
1427
 
1754
1428
 
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
//-------------------------------------------------
1759
1433
 
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 &param, const instruction &inst)
1761
1435
{
1762
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1436
        if (param.is_immediate())
1763
1437
        {
1764
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1765
 
                        /* skip */;
 
1438
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1439
                        ;// skip
1766
1440
                else
1767
 
                        emit_sar_m32_imm(dst, MEMPARAMS, param->value);                                                         // sar   [dest],param
 
1441
                        emit_sar_m32_imm(dst, memref, param.immediate());                                                               // sar   [dest],param
1768
1442
        }
1769
1443
        else
1770
1444
        {
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
1773
1447
        }
1774
1448
}
1775
1449
 
1776
1450
 
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
//-------------------------------------------------
1781
1455
 
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 &param, const instruction &inst)
1783
1457
{
1784
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1458
        if (param.is_immediate())
1785
1459
        {
1786
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1787
 
                        /* skip */;
 
1460
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1461
                        ;// skip
1788
1462
                else
1789
 
                        emit_rol_r32_imm(dst, reg, param->value);                                                                       // rol   reg,param
 
1463
                        emit_rol_r32_imm(dst, reg, param.immediate());                                                                  // rol   reg,param
1790
1464
        }
1791
1465
        else
1792
1466
        {
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
1795
1469
        }
1796
1470
}
1797
1471
 
1798
1472
 
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
//-------------------------------------------------
1803
1477
 
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 &param, const instruction &inst)
1805
1479
{
1806
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1480
        if (param.is_immediate())
1807
1481
        {
1808
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1809
 
                        /* skip */;
 
1482
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1483
                        ;// skip
1810
1484
                else
1811
 
                        emit_rol_m32_imm(dst, MEMPARAMS, param->value);                                                         // rol   [dest],param
 
1485
                        emit_rol_m32_imm(dst, memref, param.immediate());                                                               // rol   [dest],param
1812
1486
        }
1813
1487
        else
1814
1488
        {
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
1817
1491
        }
1818
1492
}
1819
1493
 
1820
1494
 
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
//-------------------------------------------------
1825
1499
 
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 &param, const instruction &inst)
1827
1501
{
1828
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1502
        if (param.is_immediate())
1829
1503
        {
1830
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1831
 
                        /* skip */;
 
1504
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1505
                        ;// skip
1832
1506
                else
1833
 
                        emit_ror_r32_imm(dst, reg, param->value);                                                                       // ror   reg,param
 
1507
                        emit_ror_r32_imm(dst, reg, param.immediate());                                                                  // ror   reg,param
1834
1508
        }
1835
1509
        else
1836
1510
        {
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
1839
1513
        }
1840
1514
}
1841
1515
 
1842
1516
 
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
//-------------------------------------------------
1847
1521
 
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 &param, const instruction &inst)
1849
1523
{
1850
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1524
        if (param.is_immediate())
1851
1525
        {
1852
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1853
 
                        /* skip */;
 
1526
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1527
                        ;// skip
1854
1528
                else
1855
 
                        emit_ror_m32_imm(dst, MEMPARAMS, param->value);                                                         // ror   [dest],param
 
1529
                        emit_ror_m32_imm(dst, memref, param.immediate());                                                               // ror   [dest],param
1856
1530
        }
1857
1531
        else
1858
1532
        {
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
1861
1535
        }
1862
1536
}
1863
1537
 
1864
1538
 
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
//-------------------------------------------------
1869
1543
 
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 &param, const instruction &inst)
1871
1545
{
1872
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1546
        if (param.is_immediate())
1873
1547
        {
1874
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1875
 
                        /* skip */;
 
1548
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1549
                        ;// skip
1876
1550
                else
1877
 
                        emit_rcl_r32_imm(dst, reg, param->value);                                                                       // rcl   reg,param
 
1551
                        emit_rcl_r32_imm(dst, reg, param.immediate());                                                                  // rcl   reg,param
1878
1552
        }
1879
1553
        else
1880
1554
        {
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
1883
1557
        }
1884
1558
}
1885
1559
 
1886
1560
 
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
//-------------------------------------------------
1891
1565
 
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 &param, const instruction &inst)
1893
1567
{
1894
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1568
        if (param.is_immediate())
1895
1569
        {
1896
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1897
 
                        /* skip */;
 
1570
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1571
                        ;// skip
1898
1572
                else
1899
 
                        emit_rcl_m32_imm(dst, MEMPARAMS, param->value);                                                         // rcl   [dest],param
 
1573
                        emit_rcl_m32_imm(dst, memref, param.immediate());                                                               // rcl   [dest],param
1900
1574
        }
1901
1575
        else
1902
1576
        {
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
1905
1579
        }
1906
1580
}
1907
1581
 
1908
1582
 
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
//-------------------------------------------------
1913
1587
 
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 &param, const instruction &inst)
1915
1589
{
1916
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1590
        if (param.is_immediate())
1917
1591
        {
1918
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1919
 
                        /* skip */;
 
1592
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1593
                        ;// skip
1920
1594
                else
1921
 
                        emit_rcr_r32_imm(dst, reg, param->value);                                                                       // rcr   reg,param
 
1595
                        emit_rcr_r32_imm(dst, reg, param.immediate());                                                                  // rcr   reg,param
1922
1596
        }
1923
1597
        else
1924
1598
        {
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
1927
1601
        }
1928
1602
}
1929
1603
 
1930
1604
 
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
//-------------------------------------------------
1935
1609
 
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 &param, const instruction &inst)
1937
1611
{
1938
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1612
        if (param.is_immediate())
1939
1613
        {
1940
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
1941
 
                        /* skip */;
 
1614
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
1615
                        ;// skip
1942
1616
                else
1943
 
                        emit_rcr_m32_imm(dst, MEMPARAMS, param->value);                                                         // rcr   [dest],param
 
1617
                        emit_rcr_m32_imm(dst, memref, param.immediate());                                                               // rcr   [dest],param
1944
1618
        }
1945
1619
        else
1946
1620
        {
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
1949
1623
        }
1950
1624
}
1951
1625
 
1952
1626
 
1953
1627
 
1954
 
/***************************************************************************
1955
 
    EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS
1956
 
***************************************************************************/
1957
 
 
1958
 
/*-------------------------------------------------
1959
 
    emit_mov_r64_p64 - move a 64-bit parameter
1960
 
    into a pair of registers
1961
 
-------------------------------------------------*/
1962
 
 
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
//**************************************************************************
 
1631
 
 
1632
//-------------------------------------------------
 
1633
//  emit_mov_r64_p64 - move a 64-bit parameter
 
1634
//  into a pair of registers
 
1635
//-------------------------------------------------
 
1636
 
 
1637
void drcbe_x86::emit_mov_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param)
1964
1638
{
1965
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1639
        if (param.is_immediate())
1966
1640
        {
1967
1641
                if (reglo == REG_NONE)
1968
1642
                        ;
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
1971
1645
                else
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)
1974
1648
                        ;
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
1977
1651
                else
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
1979
1653
        }
1980
 
        else if (param->type == DRCUML_PTYPE_MEMORY)
 
1654
        else if (param.is_memory())
1981
1655
        {
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]
1988
1662
        }
1989
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
 
1663
        else if (param.is_int_register())
1990
1664
        {
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]
1996
1670
        }
1997
1671
}
1998
1672
 
1999
1673
 
2000
 
/*-------------------------------------------------
2001
 
    emit_mov_r64_p64_keepflags - move a 64-bit
2002
 
    parameter into a pair of registers without
2003
 
    affecting any flags
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
//-------------------------------------------------
2005
1679
 
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 &param)
2007
1681
{
2008
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1682
        if (param.is_immediate())
2009
1683
        {
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
2014
1688
        }
2015
 
        else if (param->type == DRCUML_PTYPE_MEMORY)
 
1689
        else if (param.is_memory())
2016
1690
        {
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]
2023
1697
        }
2024
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
 
1698
        else if (param.is_int_register())
2025
1699
        {
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]
2031
1705
        }
2032
1706
}
2033
1707
 
2034
1708
 
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
//-------------------------------------------------
2039
1713
 
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 &param)
2041
1715
{
2042
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
1716
        if (param.is_immediate())
2043
1717
        {
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
2046
1720
        }
2047
 
        else if (param->type == DRCUML_PTYPE_MEMORY)
 
1721
        else if (param.is_memory())
2048
1722
        {
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
2055
 
        }
2056
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2057
 
        {
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
2061
 
        }
2062
 
}
2063
 
 
2064
 
 
2065
 
/*-------------------------------------------------
2066
 
    emit_mov_p64_r64 - move a pair of registers
2067
 
    into a 64-bit parameter
2068
 
-------------------------------------------------*/
2069
 
 
2070
 
static void emit_mov_p64_r64(drcbe_state *drcbe, x86code **dst, const drcuml_parameter *param, UINT8 reglo, UINT8 reghi)
2071
 
{
2072
 
        assert(param->type != DRCUML_PTYPE_IMMEDIATE);
2073
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2074
 
        {
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
2077
 
        }
2078
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2079
 
        {
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
2083
 
        }
2084
 
        set_last_lower_reg(drcbe, *dst, param, reglo);
2085
 
        set_last_upper_reg(drcbe, *dst, param, reghi);
2086
 
}
2087
 
 
2088
 
 
2089
 
/*-------------------------------------------------
2090
 
    emit_add_r64_p64 - add operation to a 64-bit
2091
 
    pair of registers from a 64-bit parameter
2092
 
-------------------------------------------------*/
2093
 
 
2094
 
static void emit_add_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2095
 
{
2096
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2097
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2098
 
        {
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]
2102
 
        }
2103
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2104
 
        {
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
2108
 
        }
2109
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2110
 
        {
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]
2114
 
        }
2115
 
        if (saveflags)
2116
 
                emit_combine_z_flags(dst);
2117
 
}
2118
 
 
2119
 
 
2120
 
/*-------------------------------------------------
2121
 
    emit_add_m64_p64 - add operation to a 64-bit
2122
 
    memory location from a 64-bit parameter
2123
 
-------------------------------------------------*/
2124
 
 
2125
 
static void emit_add_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2126
 
{
2127
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2128
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2129
 
        {
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
2133
 
        }
2134
 
        else
2135
 
        {
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
2141
 
        }
2142
 
        if (saveflags)
2143
 
                emit_combine_z_flags(dst);
2144
 
}
2145
 
 
2146
 
 
2147
 
/*-------------------------------------------------
2148
 
    emit_adc_r64_p64 - adc operation to a 64-bit
2149
 
    pair of registers from a 64-bit parameter
2150
 
-------------------------------------------------*/
2151
 
 
2152
 
static void emit_adc_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2153
 
{
2154
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2155
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2156
 
        {
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]
2160
 
        }
2161
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2162
 
        {
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
2166
 
        }
2167
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2168
 
        {
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]
2172
 
        }
2173
 
        if (saveflags)
2174
 
                emit_combine_z_flags(dst);
2175
 
}
2176
 
 
2177
 
 
2178
 
/*-------------------------------------------------
2179
 
    emit_adc_m64_p64 - adc operation to a 64-bit
2180
 
    memory location from a 64-bit parameter
2181
 
-------------------------------------------------*/
2182
 
 
2183
 
static void emit_adc_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2184
 
{
2185
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2186
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2187
 
        {
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
2191
 
        }
2192
 
        else
2193
 
        {
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
2199
 
        }
2200
 
        if (saveflags)
2201
 
                emit_combine_z_flags(dst);
2202
 
}
2203
 
 
2204
 
 
2205
 
/*-------------------------------------------------
2206
 
    emit_sub_r64_p64 - sub operation to a 64-bit
2207
 
    pair of registers from a 64-bit parameter
2208
 
-------------------------------------------------*/
2209
 
 
2210
 
static void emit_sub_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2211
 
{
2212
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2213
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2214
 
        {
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]
2218
 
        }
2219
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2220
 
        {
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
2224
 
        }
2225
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2226
 
        {
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]
2230
 
        }
2231
 
        if (saveflags)
2232
 
                emit_combine_z_flags(dst);
2233
 
}
2234
 
 
2235
 
 
2236
 
/*-------------------------------------------------
2237
 
    emit_sub_m64_p64 - sub operation to a 64-bit
2238
 
    memory location from a 64-bit parameter
2239
 
-------------------------------------------------*/
2240
 
 
2241
 
static void emit_sub_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2242
 
{
2243
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2244
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2245
 
        {
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
2249
 
        }
2250
 
        else
2251
 
        {
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
2257
 
        }
2258
 
        if (saveflags)
2259
 
                emit_combine_z_flags(dst);
2260
 
}
2261
 
 
2262
 
 
2263
 
/*-------------------------------------------------
2264
 
    emit_sbb_r64_p64 - sbb operation to a 64-bit
2265
 
    pair of registers from a 64-bit parameter
2266
 
-------------------------------------------------*/
2267
 
 
2268
 
static void emit_sbb_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2269
 
{
2270
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2271
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2272
 
        {
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]
2276
 
        }
2277
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2278
 
        {
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
2282
 
        }
2283
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2284
 
        {
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]
2288
 
        }
2289
 
        if (saveflags)
2290
 
                emit_combine_z_flags(dst);
2291
 
}
2292
 
 
2293
 
 
2294
 
/*-------------------------------------------------
2295
 
    emit_sbb_m64_p64 - sbb operation to a 64-bit
2296
 
    memory location from a 64-bit parameter
2297
 
-------------------------------------------------*/
2298
 
 
2299
 
static void emit_sbb_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2300
 
{
2301
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2302
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2303
 
        {
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
2307
 
        }
2308
 
        else
2309
 
        {
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
2315
 
        }
2316
 
        if (saveflags)
2317
 
                emit_combine_z_flags(dst);
2318
 
}
2319
 
 
2320
 
 
2321
 
/*-------------------------------------------------
2322
 
    emit_cmp_r64_p64 - sub operation to a 64-bit
2323
 
    pair of registers from a 64-bit parameter
2324
 
-------------------------------------------------*/
2325
 
 
2326
 
static void emit_cmp_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2327
 
{
2328
 
        int saveflags = (inst->flags != DRCUML_FLAG_Z && (inst->flags & DRCUML_FLAG_Z) != 0);
2329
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2330
 
        {
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]
2334
 
        }
2335
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2336
 
        {
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
2340
 
        }
2341
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2342
 
        {
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]
2346
 
        }
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
 
1729
        }
 
1730
        else if (param.is_int_register())
 
1731
        {
 
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
 
1735
        }
 
1736
}
 
1737
 
 
1738
 
 
1739
//-------------------------------------------------
 
1740
//  emit_mov_p64_r64 - move a pair of registers
 
1741
//  into a 64-bit parameter
 
1742
//-------------------------------------------------
 
1743
 
 
1744
void drcbe_x86::emit_mov_p64_r64(x86code *&dst, const be_parameter &param, UINT8 reglo, UINT8 reghi)
 
1745
{
 
1746
        assert(!param.is_immediate());
 
1747
        if (param.is_memory())
 
1748
        {
 
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
 
1751
        }
 
1752
        else if (param.is_int_register())
 
1753
        {
 
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
 
1757
        }
 
1758
        set_last_lower_reg(dst, param, reglo);
 
1759
        set_last_upper_reg(dst, param, reghi);
 
1760
}
 
1761
 
 
1762
 
 
1763
//-------------------------------------------------
 
1764
//  emit_add_r64_p64 - add operation to a 64-bit
 
1765
//  pair of registers from a 64-bit parameter
 
1766
//-------------------------------------------------
 
1767
 
 
1768
void drcbe_x86::emit_add_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
1769
{
 
1770
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1771
        if (param.is_memory())
 
1772
        {
 
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]
 
1776
        }
 
1777
        else if (param.is_immediate())
 
1778
        {
 
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
 
1782
        }
 
1783
        else if (param.is_int_register())
 
1784
        {
 
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]
 
1788
        }
 
1789
        if (saveflags)
 
1790
                emit_combine_z_flags(dst);
 
1791
}
 
1792
 
 
1793
 
 
1794
//-------------------------------------------------
 
1795
//  emit_add_m64_p64 - add operation to a 64-bit
 
1796
//  memory location from a 64-bit parameter
 
1797
//-------------------------------------------------
 
1798
 
 
1799
void drcbe_x86::emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1800
{
 
1801
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1802
        if (param.is_immediate())
 
1803
        {
 
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
 
1807
        }
 
1808
        else
 
1809
        {
 
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
 
1815
        }
 
1816
        if (saveflags)
 
1817
                emit_combine_z_flags(dst);
 
1818
}
 
1819
 
 
1820
 
 
1821
//-------------------------------------------------
 
1822
//  emit_adc_r64_p64 - adc operation to a 64-bit
 
1823
//  pair of registers from a 64-bit parameter
 
1824
//-------------------------------------------------
 
1825
 
 
1826
void drcbe_x86::emit_adc_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
1827
{
 
1828
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1829
        if (param.is_memory())
 
1830
        {
 
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]
 
1834
        }
 
1835
        else if (param.is_immediate())
 
1836
        {
 
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
 
1840
        }
 
1841
        else if (param.is_int_register())
 
1842
        {
 
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]
 
1846
        }
 
1847
        if (saveflags)
 
1848
                emit_combine_z_flags(dst);
 
1849
}
 
1850
 
 
1851
 
 
1852
//-------------------------------------------------
 
1853
//  emit_adc_m64_p64 - adc operation to a 64-bit
 
1854
//  memory location from a 64-bit parameter
 
1855
//-------------------------------------------------
 
1856
 
 
1857
void drcbe_x86::emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1858
{
 
1859
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1860
        if (param.is_immediate())
 
1861
        {
 
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
 
1865
        }
 
1866
        else
 
1867
        {
 
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
 
1873
        }
 
1874
        if (saveflags)
 
1875
                emit_combine_z_flags(dst);
 
1876
}
 
1877
 
 
1878
 
 
1879
//-------------------------------------------------
 
1880
//  emit_sub_r64_p64 - sub operation to a 64-bit
 
1881
//  pair of registers from a 64-bit parameter
 
1882
//-------------------------------------------------
 
1883
 
 
1884
void drcbe_x86::emit_sub_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
1885
{
 
1886
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1887
        if (param.is_memory())
 
1888
        {
 
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]
 
1892
        }
 
1893
        else if (param.is_immediate())
 
1894
        {
 
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
 
1898
        }
 
1899
        else if (param.is_int_register())
 
1900
        {
 
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]
 
1904
        }
 
1905
        if (saveflags)
 
1906
                emit_combine_z_flags(dst);
 
1907
}
 
1908
 
 
1909
 
 
1910
//-------------------------------------------------
 
1911
//  emit_sub_m64_p64 - sub operation to a 64-bit
 
1912
//  memory location from a 64-bit parameter
 
1913
//-------------------------------------------------
 
1914
 
 
1915
void drcbe_x86::emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1916
{
 
1917
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1918
        if (param.is_immediate())
 
1919
        {
 
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
 
1923
        }
 
1924
        else
 
1925
        {
 
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
 
1931
        }
 
1932
        if (saveflags)
 
1933
                emit_combine_z_flags(dst);
 
1934
}
 
1935
 
 
1936
 
 
1937
//-------------------------------------------------
 
1938
//  emit_sbb_r64_p64 - sbb operation to a 64-bit
 
1939
//  pair of registers from a 64-bit parameter
 
1940
//-------------------------------------------------
 
1941
 
 
1942
void drcbe_x86::emit_sbb_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
1943
{
 
1944
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1945
        if (param.is_memory())
 
1946
        {
 
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]
 
1950
        }
 
1951
        else if (param.is_immediate())
 
1952
        {
 
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
 
1956
        }
 
1957
        else if (param.is_int_register())
 
1958
        {
 
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]
 
1962
        }
 
1963
        if (saveflags)
 
1964
                emit_combine_z_flags(dst);
 
1965
}
 
1966
 
 
1967
 
 
1968
//-------------------------------------------------
 
1969
//  emit_sbb_m64_p64 - sbb operation to a 64-bit
 
1970
//  memory location from a 64-bit parameter
 
1971
//-------------------------------------------------
 
1972
 
 
1973
void drcbe_x86::emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
1974
{
 
1975
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
1976
        if (param.is_immediate())
 
1977
        {
 
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
 
1981
        }
 
1982
        else
 
1983
        {
 
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
 
1989
        }
 
1990
        if (saveflags)
 
1991
                emit_combine_z_flags(dst);
 
1992
}
 
1993
 
 
1994
 
 
1995
//-------------------------------------------------
 
1996
//  emit_cmp_r64_p64 - sub operation to a 64-bit
 
1997
//  pair of registers from a 64-bit parameter
 
1998
//-------------------------------------------------
 
1999
 
 
2000
void drcbe_x86::emit_cmp_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
2001
{
 
2002
        int saveflags = (inst.flags() != FLAG_Z && (inst.flags() & FLAG_Z) != 0);
 
2003
        if (param.is_memory())
 
2004
        {
 
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]
 
2008
        }
 
2009
        else if (param.is_immediate())
 
2010
        {
 
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
 
2014
        }
 
2015
        else if (param.is_int_register())
 
2016
        {
 
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]
 
2020
        }
 
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);
2351
2025
}
2352
2026
 
2353
2027
 
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
//-------------------------------------------------
2358
2032
 
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 &param, const instruction &inst)
2360
2034
{
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())
2363
2037
        {
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]
2367
2041
        }
2368
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2042
        else if (param.is_immediate())
2369
2043
        {
2370
 
                if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2371
 
                        /* skip */;
2372
 
                else if (inst->flags == 0 && (UINT32)param->value == 0)
 
2044
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
2045
                        ;// skip
 
2046
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
2373
2047
                        emit_xor_r32_r32(dst, reglo, reglo);                                                                            // xor   reglo,reglo
2374
2048
                else
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)
2378
 
                        /* skip */;
2379
 
                else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
 
2051
                if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
 
2052
                        ;// skip
 
2053
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
2380
2054
                        emit_xor_r32_r32(dst, reghi, reghi);                                                                            // xor   reghi,reghi
2381
2055
                else
2382
 
                        emit_and_r32_imm(dst, reghi, param->value >> 32);                                                       // and   reghi,param >> 32
2383
 
        }
2384
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2385
 
        {
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]
2389
 
        }
2390
 
        if (saveflags)
2391
 
                emit_combine_z_flags(dst);
2392
 
}
2393
 
 
2394
 
 
2395
 
/*-------------------------------------------------
2396
 
    emit_and_m64_p64 - and operation to a 64-bit
2397
 
    memory location from a 64-bit parameter
2398
 
-------------------------------------------------*/
2399
 
 
2400
 
static void emit_and_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2401
 
{
2402
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2403
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2404
 
        {
2405
 
                if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
2406
 
                        /* skip */;
2407
 
                else if (inst->flags == 0 && (UINT32)param->value == 0)
2408
 
                        emit_mov_m32_imm(dst, MEMPARAMS, 0);                                                                            // mov   [dest],0
2409
 
                else
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)
2413
 
                        /* skip */;
2414
 
                else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0)
2415
 
                        emit_mov_m32_imm(dst, MEMPARAMS + 4, 0);                                                                        // mov   [dest+4],0
2416
 
                else
2417
 
                        emit_and_m32_imm(dst, MEMPARAMS + 4, param->value >> 32);                                       // and   [dest+4],param >> 32
2418
 
        }
2419
 
        else
2420
 
        {
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
2426
 
        }
2427
 
        if (saveflags)
2428
 
                emit_combine_z_flags(dst);
2429
 
}
2430
 
 
2431
 
 
2432
 
/*-------------------------------------------------
2433
 
    emit_test_r64_p64 - test operation to a 64-bit
2434
 
    pair of registers from a 64-bit parameter
2435
 
-------------------------------------------------*/
2436
 
 
2437
 
static void emit_test_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2438
 
{
2439
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2440
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2441
 
        {
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
2445
 
        }
2446
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2447
 
        {
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
2451
 
        }
2452
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
2453
 
        {
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
2457
 
        }
2458
 
        if (saveflags)
2459
 
                emit_combine_z_flags(dst);
2460
 
}
2461
 
 
2462
 
 
2463
 
/*-------------------------------------------------
2464
 
    emit_test_m64_p64 - test operation to a 64-bit
2465
 
    memory location from a 64-bit parameter
2466
 
-------------------------------------------------*/
2467
 
 
2468
 
static void emit_test_m64_p64(drcbe_state *drcbe, x86code **dst, DECLARE_MEMPARAMS, const drcuml_parameter *param, const drcuml_instruction *inst)
2469
 
{
2470
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2471
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
2472
 
        {
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
2476
 
        }
2477
 
        else
2478
 
        {
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
2484
 
        }
2485
 
        if (saveflags)
2486
 
                emit_combine_z_flags(dst);
2487
 
}
2488
 
 
2489
 
 
2490
 
/*-------------------------------------------------
2491
 
    emit_or_r64_p64 - or operation to a 64-bit
2492
 
    pair of registers from a 64-bit parameter
2493
 
-------------------------------------------------*/
2494
 
 
2495
 
static void emit_or_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
2496
 
{
2497
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2498
 
        if (param->type == DRCUML_PTYPE_MEMORY)
2499
 
        {
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]
2503
 
        }
2504
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
2505
 
        {
2506
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
2507
 
                        /* skip */;
2508
 
                else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
 
2056
                        emit_and_r32_imm(dst, reghi, param.immediate() >> 32);                                                  // and   reghi,param >> 32
 
2057
        }
 
2058
        else if (param.is_int_register())
 
2059
        {
 
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]
 
2063
        }
 
2064
        if (saveflags)
 
2065
                emit_combine_z_flags(dst);
 
2066
}
 
2067
 
 
2068
 
 
2069
//-------------------------------------------------
 
2070
//  emit_and_m64_p64 - and operation to a 64-bit
 
2071
//  memory location from a 64-bit parameter
 
2072
//-------------------------------------------------
 
2073
 
 
2074
void drcbe_x86::emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
2075
{
 
2076
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2077
        if (param.is_immediate())
 
2078
        {
 
2079
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
2080
                        ;// skip
 
2081
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
2082
                        emit_mov_m32_imm(dst, memref, 0);                                                                               // mov   [dest],0
 
2083
                else
 
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)
 
2087
                        ;// skip
 
2088
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
 
2089
                        emit_mov_m32_imm(dst, memref + 4, 0);                                                                   // mov   [dest+4],0
 
2090
                else
 
2091
                        emit_and_m32_imm(dst, memref + 4, param.immediate() >> 32);                                     // and   [dest+4],param >> 32
 
2092
        }
 
2093
        else
 
2094
        {
 
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
 
2100
        }
 
2101
        if (saveflags)
 
2102
                emit_combine_z_flags(dst);
 
2103
}
 
2104
 
 
2105
 
 
2106
//-------------------------------------------------
 
2107
//  emit_test_r64_p64 - test operation to a 64-bit
 
2108
//  pair of registers from a 64-bit parameter
 
2109
//-------------------------------------------------
 
2110
 
 
2111
void drcbe_x86::emit_test_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
2112
{
 
2113
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2114
        if (param.is_memory())
 
2115
        {
 
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
 
2119
        }
 
2120
        else if (param.is_immediate())
 
2121
        {
 
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
 
2125
        }
 
2126
        else if (param.is_int_register())
 
2127
        {
 
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
 
2131
        }
 
2132
        if (saveflags)
 
2133
                emit_combine_z_flags(dst);
 
2134
}
 
2135
 
 
2136
 
 
2137
//-------------------------------------------------
 
2138
//  emit_test_m64_p64 - test operation to a 64-bit
 
2139
//  memory location from a 64-bit parameter
 
2140
//-------------------------------------------------
 
2141
 
 
2142
void drcbe_x86::emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
 
2143
{
 
2144
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2145
        if (param.is_immediate())
 
2146
        {
 
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
 
2150
        }
 
2151
        else
 
2152
        {
 
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
 
2158
        }
 
2159
        if (saveflags)
 
2160
                emit_combine_z_flags(dst);
 
2161
}
 
2162
 
 
2163
 
 
2164
//-------------------------------------------------
 
2165
//  emit_or_r64_p64 - or operation to a 64-bit
 
2166
//  pair of registers from a 64-bit parameter
 
2167
//-------------------------------------------------
 
2168
 
 
2169
void drcbe_x86::emit_or_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
 
2170
{
 
2171
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2172
        if (param.is_memory())
 
2173
        {
 
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]
 
2177
        }
 
2178
        else if (param.is_immediate())
 
2179
        {
 
2180
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
2181
                        ;// skip
 
2182
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2509
2183
                        emit_mov_r32_imm(dst, reglo, ~0);                                                                                       // mov   reglo,-1
2510
2184
                else
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)
2514
 
                        /* skip */;
2515
 
                else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
 
2187
                if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
 
2188
                        ;// skip
 
2189
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2516
2190
                        emit_mov_r32_imm(dst, reghi, ~0);                                                                                       // mov   reghi,-1
2517
2191
                else
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
2519
2193
        }
2520
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
 
2194
        else if (param.is_int_register())
2521
2195
        {
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]
2525
2199
        }
2526
2200
        if (saveflags)
2527
2201
                emit_combine_z_flags(dst);
2528
2202
}
2529
2203
 
2530
2204
 
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
//-------------------------------------------------
2535
2209
 
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 &param, const instruction &inst)
2537
2211
{
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())
2540
2214
        {
2541
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
2542
 
                        /* skip */;
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)
 
2216
                        ;// skip
 
2217
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
2218
                        emit_mov_m32_imm(dst, memref, ~0);                                                                              // mov   [dest],-1
2545
2219
                else
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)
2549
 
                        /* skip */;
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)
 
2223
                        ;// skip
 
2224
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
 
2225
                        emit_mov_m32_imm(dst, memref + 4, ~0);                                                                  // mov   [dest+4],-1
2552
2226
                else
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
2554
2228
        }
2555
2229
        else
2556
2230
        {
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
2562
2236
        }
2563
2237
        if (saveflags)
2564
2238
                emit_combine_z_flags(dst);
2565
2239
}
2566
2240
 
2567
2241
 
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
//-------------------------------------------------
2572
2246
 
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 &param, const instruction &inst)
2574
2248
{
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())
2577
2251
        {
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]
2581
2255
        }
2582
 
        else if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2256
        else if (param.is_immediate())
2583
2257
        {
2584
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
2585
 
                        /* skip */;
2586
 
                else if (inst->flags == 0 && (UINT32)param->value == 0xffffffff)
 
2258
                if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
 
2259
                        ;// skip
 
2260
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
2587
2261
                        emit_not_r32(dst, reglo);                                                                                                       // not   reglo
2588
2262
                else
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)
2592
 
                        /* skip */;
2593
 
                else if (inst->flags == 0 && (UINT32)(param->value >> 32) == 0xffffffff)
 
2265
                if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
 
2266
                        ;// skip
 
2267
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
2594
2268
                        emit_not_r32(dst, reghi);                                                                                                       // not   reghi
2595
2269
                else
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
2597
2271
        }
2598
 
        else if (param->type == DRCUML_PTYPE_INT_REGISTER)
 
2272
        else if (param.is_int_register())
2599
2273
        {
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]
2603
2277
        }
2604
2278
        if (saveflags)
2605
2279
                emit_combine_z_flags(dst);
2606
2280
}
2607
2281
 
2608
2282
 
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
//-------------------------------------------------
2613
2287
 
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 &param, const instruction &inst)
2615
2289
{
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())
2618
2292
        {
2619
 
                if (inst->flags == 0 && (UINT32)param->value == 0)
2620
 
                        /* skip */;
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)
 
2294
                        ;// skip
 
2295
                else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
 
2296
                        emit_not_m32(dst, memref);                                                                                              // not   [dest]
2623
2297
                else
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)
2627
 
                        /* skip */;
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)
 
2301
                        ;// skip
 
2302
                else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
 
2303
                        emit_not_m32(dst, memref + 4);                                                                                  // not   [dest+4]
2630
2304
                else
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
2632
2306
        }
2633
2307
        else
2634
2308
        {
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
2640
2314
        }
2641
2315
        if (saveflags)
2642
2316
                emit_combine_z_flags(dst);
2643
2317
}
2644
2318
 
2645
2319
 
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
//-------------------------------------------------
2650
2324
 
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 &param, const instruction &inst)
2652
2326
{
2653
 
        int saveflags = (inst->flags != 0);
2654
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2327
        int saveflags = (inst.flags() != 0);
 
2328
        if (param.is_immediate())
2655
2329
        {
2656
 
                int count = param->value & 63;
2657
 
                if (inst->flags == 0 && count == 0)
2658
 
                        /* skip */;
 
2330
                int count = param.immediate() & 63;
 
2331
                if (inst.flags() == 0 && count == 0)
 
2332
                        ;// skip
2659
2333
                else
2660
2334
                {
2661
2335
                        while (count >= 32)
2662
2336
                        {
2663
 
                                if (inst->flags != 0)
 
2337
                                if (inst.flags() != 0)
2664
2338
                                {
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
2673
2347
                                        count -= 32;
2674
2348
                                }
2675
2349
                        }
2676
 
                        if (inst->flags != 0 || count > 0)
 
2350
                        if (inst.flags() != 0 || count > 0)
2677
2351
                        {
2678
2352
                                emit_shld_r32_r32_imm(dst, reghi, reglo, count);                                                // shld  reghi,reglo,count
2679
2353
                                if (saveflags) emit_pushf(dst);                                                                                 // pushf
2684
2358
        else
2685
2359
        {
2686
2360
                emit_link skip1, skip2;
2687
 
                emit_mov_r32_p32(drcbe, dst, REG_ECX, param);                                                                   // mov   ecx,param
 
2361
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
2688
2362
                emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                                  // test  ecx,0x20
2689
 
                emit_jcc_short_link(dst, COND_Z, &skip1);                                                                               // jz    skip1
2690
 
                if (inst->flags != 0)
 
2363
                emit_jcc_short_link(dst, x86emit::COND_Z, skip1);                                                               // jz    skip1
 
2364
                if (inst.flags() != 0)
2691
2365
                {
2692
2366
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2693
2367
                        emit_shld_r32_r32_imm(dst, reghi, reglo, 31);                                                           // shld  reghi,reglo,31
2694
2368
                        emit_shl_r32_imm(dst, reglo, 31);                                                                                       // shl   reglo,31
2695
2369
                        emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                          // test  ecx,0x20
2696
 
                        emit_jcc_short_link(dst, COND_Z, &skip2);                                                                       // jz    skip2
 
2370
                        emit_jcc_short_link(dst, x86emit::COND_Z, skip2);                                                       // jz    skip2
2697
2371
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2698
2372
                        emit_shld_r32_r32_imm(dst, reghi, reglo, 31);                                                           // shld  reghi,reglo,31
2699
2373
                        emit_shl_r32_imm(dst, reglo, 31);                                                                                       // shl   reglo,31
2700
 
                        track_resolve_link(drcbe, dst, &skip2);                                                                 // skip2:
 
2374
                        track_resolve_link(dst, skip2);                                                                                 // skip2:
2701
2375
                }
2702
2376
                else
2703
2377
                {
2704
2378
                        emit_mov_r32_r32(dst, reghi, reglo);                                                                            // mov   reghi,reglo
2705
2379
                        emit_xor_r32_r32(dst, reglo, reglo);                                                                            // xor   reglo,reglo
2706
2380
                }
2707
 
                track_resolve_link(drcbe, dst, &skip1);                                                                         // skip1:
 
2381
                track_resolve_link(dst, skip1);                                                                                         // skip1:
2708
2382
                emit_shld_r32_r32_cl(dst, reghi, reglo);                                                                                // shld  reghi,reglo,cl
2709
2383
                if (saveflags) emit_pushf(dst);                                                                                                 // pushf
2710
2384
                emit_shl_r32_cl(dst, reglo);                                                                                                    // shl   reglo,cl
2714
2388
}
2715
2389
 
2716
2390
 
2717
 
/*-------------------------------------------------
2718
 
    emit_shr_r64_p64 - shr operation to a 64-bit
2719
 
    pair of registers from a 64-bit parameter
2720
 
-------------------------------------------------*/
 
2391
//-------------------------------------------------
 
2392
//  emit_shr_r64_p64 - shr operation to a 64-bit
 
2393
//  pair of registers from a 64-bit parameter
 
2394
//-------------------------------------------------
2721
2395
 
2722
 
static void emit_shr_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2396
void drcbe_x86::emit_shr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
2723
2397
{
2724
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2725
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2398
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2399
        if (param.is_immediate())
2726
2400
        {
2727
 
                int count = param->value & 63;
2728
 
                if (inst->flags == 0 && count == 0)
2729
 
                        /* skip */;
 
2401
                int count = param.immediate() & 63;
 
2402
                if (inst.flags() == 0 && count == 0)
 
2403
                        ;// skip
2730
2404
                else
2731
2405
                {
2732
2406
                        while (count >= 32)
2733
2407
                        {
2734
 
                                if (inst->flags != 0)
 
2408
                                if (inst.flags() != 0)
2735
2409
                                {
2736
2410
                                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                           // shrd  reglo,reghi,31
2737
2411
                                        emit_shr_r32_imm(dst, reghi, 31);                                                                       // shr   reghi,31
2744
2418
                                        count -= 32;
2745
2419
                                }
2746
2420
                        }
2747
 
                        if (inst->flags != 0 || count > 0)
 
2421
                        if (inst.flags() != 0 || count > 0)
2748
2422
                        {
2749
2423
                                emit_shrd_r32_r32_imm(dst, reglo, reghi, count);                                                // shrd  reglo,reghi,count
2750
2424
                                if (saveflags) emit_pushf(dst);                                                                                 // pushf
2755
2429
        else
2756
2430
        {
2757
2431
                emit_link skip1, skip2;
2758
 
                emit_mov_r32_p32(drcbe, dst, REG_ECX, param);                                                                   // mov   ecx,param
 
2432
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
2759
2433
                emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                                  // test  ecx,0x20
2760
 
                emit_jcc_short_link(dst, COND_Z, &skip1);                                                                               // jz    skip1
2761
 
                if (inst->flags != 0)
 
2434
                emit_jcc_short_link(dst, x86emit::COND_Z, skip1);                                                               // jz    skip1
 
2435
                if (inst.flags() != 0)
2762
2436
                {
2763
2437
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2764
2438
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2765
2439
                        emit_shr_r32_imm(dst, reghi, 31);                                                                                       // shr   reghi,31
2766
2440
                        emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                          // test  ecx,0x20
2767
 
                        emit_jcc_short_link(dst, COND_Z, &skip2);                                                                       // jz    skip2
 
2441
                        emit_jcc_short_link(dst, x86emit::COND_Z, skip2);                                                       // jz    skip2
2768
2442
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2769
2443
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2770
2444
                        emit_shr_r32_imm(dst, reghi, 31);                                                                                       // shr   reghi,31
2771
 
                        track_resolve_link(drcbe, dst, &skip2);                                                                 // skip2:
 
2445
                        track_resolve_link(dst, skip2);                                                                                 // skip2:
2772
2446
                }
2773
2447
                else
2774
2448
                {
2775
2449
                        emit_mov_r32_r32(dst, reglo, reghi);                                                                            // mov   reglo,reghi
2776
2450
                        emit_xor_r32_r32(dst, reghi, reghi);                                                                            // xor   reghi,reghi
2777
2451
                }
2778
 
                track_resolve_link(drcbe, dst, &skip1);                                                                         // skip1:
 
2452
                track_resolve_link(dst, skip1);                                                                                         // skip1:
2779
2453
                emit_shrd_r32_r32_cl(dst, reglo, reghi);                                                                                // shrd  reglo,reghi,cl
2780
2454
                if (saveflags) emit_pushf(dst);                                                                                                 // pushf
2781
2455
                emit_shr_r32_cl(dst, reghi);                                                                                                    // shr   reghi,cl
2785
2459
}
2786
2460
 
2787
2461
 
2788
 
/*-------------------------------------------------
2789
 
    emit_sar_r64_p64 - sar operation to a 64-bit
2790
 
    pair of registers from a 64-bit parameter
2791
 
-------------------------------------------------*/
 
2462
//-------------------------------------------------
 
2463
//  emit_sar_r64_p64 - sar operation to a 64-bit
 
2464
//  pair of registers from a 64-bit parameter
 
2465
//-------------------------------------------------
2792
2466
 
2793
 
static void emit_sar_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2467
void drcbe_x86::emit_sar_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
2794
2468
{
2795
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2796
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2469
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2470
        if (param.is_immediate())
2797
2471
        {
2798
 
                int count = param->value & 63;
2799
 
                if (inst->flags == 0 && count == 0)
2800
 
                        /* skip */;
 
2472
                int count = param.immediate() & 63;
 
2473
                if (inst.flags() == 0 && count == 0)
 
2474
                        ;// skip
2801
2475
                else
2802
2476
                {
2803
2477
                        while (count >= 32)
2804
2478
                        {
2805
 
                                if (inst->flags != 0)
 
2479
                                if (inst.flags() != 0)
2806
2480
                                {
2807
2481
                                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                           // shrd  reglo,reghi,31
2808
2482
                                        emit_sar_r32_imm(dst, reghi, 31);                                                                       // sar   reghi,31
2815
2489
                                        count -= 32;
2816
2490
                                }
2817
2491
                        }
2818
 
                        if (inst->flags != 0 || count > 0)
 
2492
                        if (inst.flags() != 0 || count > 0)
2819
2493
                        {
2820
2494
                                emit_shrd_r32_r32_imm(dst, reglo, reghi, count);                                                // shrd  reglo,reghi,count
2821
2495
                                if (saveflags) emit_pushf(dst);                                                                                 // pushf
2826
2500
        else
2827
2501
        {
2828
2502
                emit_link skip1, skip2;
2829
 
                emit_mov_r32_p32(drcbe, dst, REG_ECX, param);                                                                   // mov   ecx,param
 
2503
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
2830
2504
                emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                                  // test  ecx,0x20
2831
 
                emit_jcc_short_link(dst, COND_Z, &skip1);                                                                               // jz    skip1
2832
 
                if (inst->flags != 0)
 
2505
                emit_jcc_short_link(dst, x86emit::COND_Z, skip1);                                                               // jz    skip1
 
2506
                if (inst.flags() != 0)
2833
2507
                {
2834
2508
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2835
2509
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2836
2510
                        emit_sar_r32_imm(dst, reghi, 31);                                                                                       // sar   reghi,31
2837
2511
                        emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                          // test  ecx,0x20
2838
 
                        emit_jcc_short_link(dst, COND_Z, &skip2);                                                                       // jz    skip
 
2512
                        emit_jcc_short_link(dst, x86emit::COND_Z, skip2);                                                       // jz    skip
2839
2513
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2840
2514
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2841
2515
                        emit_sar_r32_imm(dst, reghi, 31);                                                                                       // sar   reghi,31
2842
 
                        track_resolve_link(drcbe, dst, &skip2);                                                                 // skip2:
 
2516
                        track_resolve_link(dst, skip2);                                                                                 // skip2:
2843
2517
                }
2844
2518
                else
2845
2519
                {
2846
2520
                        emit_mov_r32_r32(dst, reglo, reghi);                                                                            // mov   reglo,reghi
2847
2521
                        emit_sar_r32_imm(dst, reghi, 31);                                                                                       // sar   reghi,31
2848
2522
                }
2849
 
                track_resolve_link(drcbe, dst, &skip1);                                                                         // skip1:
 
2523
                track_resolve_link(dst, skip1);                                                                                         // skip1:
2850
2524
                emit_shrd_r32_r32_cl(dst, reglo, reghi);                                                                                // shrd  reglo,reghi,cl
2851
2525
                if (saveflags) emit_pushf(dst);                                                                                                 // pushf
2852
2526
                emit_sar_r32_cl(dst, reghi);                                                                                                    // sar   reghi,cl
2856
2530
}
2857
2531
 
2858
2532
 
2859
 
/*-------------------------------------------------
2860
 
    emit_rol_r64_p64 - rol operation to a 64-bit
2861
 
    pair of registers from a 64-bit parameter
2862
 
-------------------------------------------------*/
 
2533
//-------------------------------------------------
 
2534
//  emit_rol_r64_p64 - rol operation to a 64-bit
 
2535
//  pair of registers from a 64-bit parameter
 
2536
//-------------------------------------------------
2863
2537
 
2864
 
static void emit_rol_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2538
void drcbe_x86::emit_rol_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
2865
2539
{
2866
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2867
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2540
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2541
        if (param.is_immediate())
2868
2542
        {
2869
 
                int count = param->value & 63;
2870
 
                if (inst->flags == 0 && count == 0)
2871
 
                        /* skip */;
 
2543
                int count = param.immediate() & 63;
 
2544
                if (inst.flags() == 0 && count == 0)
 
2545
                        ;// skip
2872
2546
                else
2873
2547
                {
2874
2548
                        while (count >= 32)
2875
2549
                        {
2876
 
                                if (inst->flags != 0)
 
2550
                                if (inst.flags() != 0)
2877
2551
                                {
2878
2552
                                        emit_mov_r32_r32(dst, REG_ECX, reglo);                                                          // mov   ecx,reglo
2879
2553
                                        emit_shld_r32_r32_imm(dst, reglo, reghi, 31);                                           // shld  reglo,reghi,31
2886
2560
                                        count -= 32;
2887
2561
                                }
2888
2562
                        }
2889
 
                        if (inst->flags != 0 || count > 0)
 
2563
                        if (inst.flags() != 0 || count > 0)
2890
2564
                        {
2891
2565
                                emit_mov_r32_r32(dst, REG_ECX, reglo);                                                                  // mov   ecx,reglo
2892
2566
                                emit_shld_r32_r32_imm(dst, reglo, reghi, count);                                                // shld  reglo,reghi,count
2900
2574
                emit_link skip1, skip2;
2901
2575
                int tempreg = REG_EBX;
2902
2576
                emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg);                               // mov   [esp-8],ebx
2903
 
                emit_mov_r32_p32(drcbe, dst, REG_ECX, param);                                                                   // mov   ecx,param
 
2577
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
2904
2578
                emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                                  // test  ecx,0x20
2905
 
                emit_jcc_short_link(dst, COND_Z, &skip1);                                                                               // jz    skip1
2906
 
                if (inst->flags != 0)
 
2579
                emit_jcc_short_link(dst, x86emit::COND_Z, skip1);                                                               // jz    skip1
 
2580
                if (inst.flags() != 0)
2907
2581
                {
2908
2582
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2909
2583
                        emit_mov_r32_r32(dst, tempreg, reglo);                                                                          // mov   ebx,reglo
2910
2584
                        emit_shld_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shld  reglo,reghi,31
2911
2585
                        emit_shld_r32_r32_imm(dst, reghi, tempreg, 31);                                                         // shld  reghi,ebx,31
2912
2586
                        emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                          // test  ecx,0x20
2913
 
                        emit_jcc_short_link(dst, COND_Z, &skip2);                                                                       // jz    skip2
 
2587
                        emit_jcc_short_link(dst, x86emit::COND_Z, skip2);                                                       // jz    skip2
2914
2588
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2915
2589
                        emit_mov_r32_r32(dst, tempreg, reglo);                                                                          // mov   ebx,reglo
2916
2590
                        emit_shld_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shld  reglo,reghi,31
2917
2591
                        emit_shld_r32_r32_imm(dst, reghi, tempreg, 31);                                                         // shld  reghi,ebx,31
2918
 
                        track_resolve_link(drcbe, dst, &skip2);                                                                 // skip2:
 
2592
                        track_resolve_link(dst, skip2);                                                                                 // skip2:
2919
2593
                }
2920
2594
                else
2921
2595
                        emit_xchg_r32_r32(dst, reghi, reglo);                                                                           // xchg  reghi,reglo
2922
 
                track_resolve_link(drcbe, dst, &skip1);                                                                         // skip1:
 
2596
                track_resolve_link(dst, skip1);                                                                                         // skip1:
2923
2597
                emit_mov_r32_r32(dst, tempreg, reglo);                                                                                  // mov   ebx,reglo
2924
2598
                emit_shld_r32_r32_cl(dst, reglo, reghi);                                                                                // shld  reglo,reghi,cl
2925
2599
                if (saveflags) emit_pushf(dst);                                                                                                 // pushf
2931
2605
}
2932
2606
 
2933
2607
 
2934
 
/*-------------------------------------------------
2935
 
    emit_ror_r64_p64 - ror operation to a 64-bit
2936
 
    pair of registers from a 64-bit parameter
2937
 
-------------------------------------------------*/
 
2608
//-------------------------------------------------
 
2609
//  emit_ror_r64_p64 - ror operation to a 64-bit
 
2610
//  pair of registers from a 64-bit parameter
 
2611
//-------------------------------------------------
2938
2612
 
2939
 
static void emit_ror_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2613
void drcbe_x86::emit_ror_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
2940
2614
{
2941
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
2942
 
        if (param->type == DRCUML_PTYPE_IMMEDIATE)
 
2615
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
 
2616
        if (param.is_immediate())
2943
2617
        {
2944
 
                int count = param->value & 63;
2945
 
                if (inst->flags == 0 && count == 0)
2946
 
                        /* skip */;
 
2618
                int count = param.immediate() & 63;
 
2619
                if (inst.flags() == 0 && count == 0)
 
2620
                        ;// skip
2947
2621
                else
2948
2622
                {
2949
2623
                        while (count >= 32)
2950
2624
                        {
2951
 
                                if (inst->flags != 0)
 
2625
                                if (inst.flags() != 0)
2952
2626
                                {
2953
2627
                                        emit_mov_r32_r32(dst, REG_ECX, reglo);                                                          // mov   ecx,reglo
2954
2628
                                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                           // shrd  reglo,reghi,31
2961
2635
                                        count -= 32;
2962
2636
                                }
2963
2637
                        }
2964
 
                        if (inst->flags != 0 || count > 0)
 
2638
                        if (inst.flags() != 0 || count > 0)
2965
2639
                        {
2966
2640
                                emit_mov_r32_r32(dst, REG_ECX, reglo);                                                                  // mov   ecx,reglo
2967
2641
                                emit_shrd_r32_r32_imm(dst, reglo, reghi, count);                                                // shrd  reglo,reghi,count
2975
2649
                emit_link skip1, skip2;
2976
2650
                int tempreg = REG_EBX;
2977
2651
                emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg);                               // mov   [esp-8],ebx
2978
 
                emit_mov_r32_p32(drcbe, dst, REG_ECX, param);                                                                   // mov   ecx,param
 
2652
                emit_mov_r32_p32(dst, REG_ECX, param);                                                                  // mov   ecx,param
2979
2653
                emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                                  // test  ecx,0x20
2980
 
                emit_jcc_short_link(dst, COND_Z, &skip1);                                                                               // jz    skip1
2981
 
                if (inst->flags != 0)
 
2654
                emit_jcc_short_link(dst, x86emit::COND_Z, skip1);                                                               // jz    skip1
 
2655
                if (inst.flags() != 0)
2982
2656
                {
2983
2657
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2984
2658
                        emit_mov_r32_r32(dst, tempreg, reglo);                                                                          // mov   ebx,reglo
2985
2659
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2986
2660
                        emit_shrd_r32_r32_imm(dst, reghi, tempreg, 31);                                                         // shrd  reghi,ebx,31
2987
2661
                        emit_test_r32_imm(dst, REG_ECX, 0x20);                                                                          // test  ecx,0x20
2988
 
                        emit_jcc_short_link(dst, COND_Z, &skip2);                                                                       // jz    skip2
 
2662
                        emit_jcc_short_link(dst, x86emit::COND_Z, skip2);                                                       // jz    skip2
2989
2663
                        emit_sub_r32_imm(dst, REG_ECX, 31);                                                                                     // sub   ecx,31
2990
2664
                        emit_mov_r32_r32(dst, tempreg, reglo);                                                                          // mov   ebx,reglo
2991
2665
                        emit_shrd_r32_r32_imm(dst, reglo, reghi, 31);                                                           // shrd  reglo,reghi,31
2992
2666
                        emit_shrd_r32_r32_imm(dst, reghi, tempreg, 31);                                                         // shrd  reghi,ebx,31
2993
 
                        track_resolve_link(drcbe, dst, &skip2);                                                                 // skip2:
 
2667
                        track_resolve_link(dst, skip2);                                                                                 // skip2:
2994
2668
                }
2995
2669
                else
2996
2670
                        emit_xchg_r32_r32(dst, reghi, reglo);                                                                           // xchg  reghi,reglo
2997
 
                track_resolve_link(drcbe, dst, &skip1);                                                                         // skip1:
 
2671
                track_resolve_link(dst, skip1);                                                                                         // skip1:
2998
2672
                emit_mov_r32_r32(dst, tempreg, reglo);                                                                                  // mov   ebx,reglo
2999
2673
                emit_shrd_r32_r32_cl(dst, reglo, reghi);                                                                                // shrd  reglo,reghi,cl
3000
2674
                if (saveflags) emit_pushf(dst);                                                                                                 // pushf
3006
2680
}
3007
2681
 
3008
2682
 
3009
 
/*-------------------------------------------------
3010
 
    emit_rcl_r64_p64 - rcl operation to a 64-bit
3011
 
    pair of registers from a 64-bit parameter
3012
 
-------------------------------------------------*/
 
2683
//-------------------------------------------------
 
2684
//  emit_rcl_r64_p64 - rcl operation to a 64-bit
 
2685
//  pair of registers from a 64-bit parameter
 
2686
//-------------------------------------------------
3013
2687
 
3014
 
static void emit_rcl_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2688
void drcbe_x86::emit_rcl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
3015
2689
{
3016
 
        int saveflags = ((inst->flags & DRCUML_FLAG_Z) != 0);
 
2690
        int saveflags = ((inst.flags() & FLAG_Z) != 0);
3017
2691
        emit_link skipall, skiploop;
3018
2692
        x86code *loop;
3019
2693
 
3020
 
        emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param);                                                         // mov   ecx,param
 
2694
        emit_mov_r32_p32_keepflags(dst, REG_ECX, param);                                                                // mov   ecx,param
3021
2695
        if (!saveflags)
3022
2696
        {
3023
 
                loop = *dst;                                                                                                                            // loop:
3024
 
                emit_jecxz_link(dst, &skipall);                                                                                                 // jecxz skipall
 
2697
                loop = dst;                                                                                                                                     // loop:
 
2698
                emit_jecxz_link(dst, skipall);                                                                                                  // jecxz skipall
3025
2699
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3026
2700
                emit_rcl_r32_imm(dst, reglo, 1);                                                                                                // rcl   reglo,1
3027
2701
                emit_rcl_r32_imm(dst, reghi, 1);                                                                                                // rcl   reghi,1
3028
2702
                emit_jmp(dst, loop);                                                                                                                    // jmp   loop
3029
 
                track_resolve_link(drcbe, dst, &skipall);                                                                       // skipall:
 
2703
                track_resolve_link(dst, skipall);                                                                                       // skipall:
3030
2704
        }
3031
2705
        else
3032
2706
        {
3033
 
                emit_jecxz_link(dst, &skipall);                                                                                                 // jecxz skipall
 
2707
                emit_jecxz_link(dst, skipall);                                                                                                  // jecxz skipall
3034
2708
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3035
 
                loop = *dst;                                                                                                                            // loop:
3036
 
                emit_jecxz_link(dst, &skiploop);                                                                                                // jecxz skiploop
 
2709
                loop = dst;                                                                                                                                     // loop:
 
2710
                emit_jecxz_link(dst, skiploop);                                                                                         // jecxz skiploop
3037
2711
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3038
2712
                emit_rcl_r32_imm(dst, reglo, 1);                                                                                                // rcl   reglo,1
3039
2713
                emit_rcl_r32_imm(dst, reghi, 1);                                                                                                // rcl   reghi,1
3040
2714
                emit_jmp(dst, loop);                                                                                                                    // jmp   loop
3041
 
                track_resolve_link(drcbe, dst, &skiploop);                                                                      // skiploop:
 
2715
                track_resolve_link(dst, skiploop);                                                                                      // skiploop:
3042
2716
                emit_rcl_r32_imm(dst, reglo, 1);                                                                                                // rcl   reglo,1
3043
2717
                emit_pushf(dst);                                                                                                                                // pushf
3044
2718
                emit_rcl_r32_imm(dst, reghi, 1);                                                                                                // rcl   reghi,1
3045
 
                track_resolve_link(drcbe, dst, &skipall);                                                                       // skipall:
 
2719
                track_resolve_link(dst, skipall);                                                                                       // skipall:
3046
2720
                emit_combine_z_flags(dst);
3047
2721
        }
3048
2722
}
3049
2723
 
3050
2724
 
3051
 
/*-------------------------------------------------
3052
 
    emit_rcr_r64_p64 - rcr operation to a 64-bit
3053
 
    pair of registers from a 64-bit parameter
3054
 
-------------------------------------------------*/
 
2725
//-------------------------------------------------
 
2726
//  emit_rcr_r64_p64 - rcr operation to a 64-bit
 
2727
//  pair of registers from a 64-bit parameter
 
2728
//-------------------------------------------------
3055
2729
 
3056
 
static void emit_rcr_r64_p64(drcbe_state *drcbe, x86code **dst, UINT8 reglo, UINT8 reghi, const drcuml_parameter *param, const drcuml_instruction *inst)
 
2730
void drcbe_x86::emit_rcr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
3057
2731
{
3058
 
        int saveflags = (inst->flags != 0);
 
2732
        int saveflags = (inst.flags() != 0);
3059
2733
        emit_link skipall, skiploop;
3060
2734
        x86code *loop;
3061
2735
 
3062
 
        emit_mov_r32_p32_keepflags(drcbe, dst, REG_ECX, param);                                                         // mov   ecx,param
 
2736
        emit_mov_r32_p32_keepflags(dst, REG_ECX, param);                                                                // mov   ecx,param
3063
2737
        if (!saveflags)
3064
2738
        {
3065
 
                loop = *dst;                                                                                                                            // loop:
3066
 
                emit_jecxz_link(dst, &skipall);                                                                                                 // jecxz skipall
 
2739
                loop = dst;                                                                                                                                     // loop:
 
2740
                emit_jecxz_link(dst, skipall);                                                                                                  // jecxz skipall
3067
2741
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3068
2742
                emit_rcr_r32_imm(dst, reghi, 1);                                                                                                // rcr   reghi,1
3069
2743
                emit_rcr_r32_imm(dst, reglo, 1);                                                                                                // rcr   reglo,1
3070
2744
                emit_jmp(dst, loop);                                                                                                                    // jmp   loop
3071
 
                track_resolve_link(drcbe, dst, &skipall);                                                                       // skipall:
 
2745
                track_resolve_link(dst, skipall);                                                                                       // skipall:
3072
2746
        }
3073
2747
        else
3074
2748
        {
3075
 
                emit_jecxz_link(dst, &skipall);                                                                                                 // jecxz skipall
 
2749
                emit_jecxz_link(dst, skipall);                                                                                                  // jecxz skipall
3076
2750
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3077
 
                loop = *dst;                                                                                                                            // loop:
3078
 
                emit_jecxz_link(dst, &skiploop);                                                                                                // jecxz skiploop
 
2751
                loop = dst;                                                                                                                                     // loop:
 
2752
                emit_jecxz_link(dst, skiploop);                                                                                         // jecxz skiploop
3079
2753
                emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1));                                                               // lea   ecx,[ecx-1]
3080
2754
                emit_rcr_r32_imm(dst, reghi, 1);                                                                                                // rcr   reghi,1
3081
2755
                emit_rcr_r32_imm(dst, reglo, 1);                                                                                                // rcr   reglo,1
3082
2756
                emit_jmp(dst, loop);                                                                                                                    // jmp   loop
3083
 
                track_resolve_link(drcbe, dst, &skiploop);                                                                      // skiploop:
 
2757
                track_resolve_link(dst, skiploop);                                                                                      // skiploop:
3084
2758
                emit_rcr_r32_imm(dst, reghi, 1);                                                                                                // rcr   reghi,1
3085
2759
                emit_pushf(dst);                                                                                                                                // pushf
3086
2760
                emit_rcr_r32_imm(dst, reglo, 1);                                                                                                // rcr   reglo,1
3087
 
                track_resolve_link(drcbe, dst, &skipall);                                                                       // skipall:
 
2761
                track_resolve_link(dst, skipall);                                                                                       // skipall:
3088
2762
                emit_combine_z_shl_flags(dst);
3089
2763
        }
3090
2764
}
3091
2765
 
3092
2766
 
3093
2767
 
3094
 
/***************************************************************************
3095
 
    EMITTERS FOR FLOATING POINT
3096
 
***************************************************************************/
3097
 
 
3098
 
/*-------------------------------------------------
3099
 
    emit_fld_p - load a floating point parameter
3100
 
    onto the stack
3101
 
-------------------------------------------------*/
3102
 
 
3103
 
static void emit_fld_p(x86code **dst, int size, const drcuml_parameter *param)
3104
 
{
3105
 
        assert(param->type == DRCUML_PTYPE_MEMORY);
3106
 
        assert(size == 4 || size == 8);
3107
 
        if (size == 4)
3108
 
                emit_fld_m32(dst, MABS(param->value));
3109
 
        else if (size == 8)
3110
 
                emit_fld_m64(dst, MABS(param->value));
3111
 
}
3112
 
 
3113
 
 
3114
 
/*-------------------------------------------------
3115
 
    emit_fstp_p - store a floating point parameter
3116
 
    from the stack and pop it
3117
 
-------------------------------------------------*/
3118
 
 
3119
 
static void emit_fstp_p(x86code **dst, int size, const drcuml_parameter *param)
3120
 
{
3121
 
        assert(param->type == DRCUML_PTYPE_MEMORY);
3122
 
        assert(size == 4 || size == 8);
3123
 
        if (size == 4)
3124
 
                emit_fstp_m32(dst, MABS(param->value));
3125
 
        else if (size == 8)
3126
 
                emit_fstp_m64(dst, MABS(param->value));
3127
 
}
3128
 
 
3129
 
 
3130
 
 
3131
 
/***************************************************************************
3132
 
    OUT-OF-BAND CODE FIXUP CALLBACKS
3133
 
***************************************************************************/
3134
 
 
3135
 
/*-------------------------------------------------
3136
 
    fixup_label - callback to fixup forward-
3137
 
    referenced labels
3138
 
-------------------------------------------------*/
3139
 
 
3140
 
static void fixup_label(void *parameter, drccodeptr labelcodeptr)
 
2768
//**************************************************************************
 
2769
//  EMITTERS FOR FLOATING POINT
 
2770
//**************************************************************************
 
2771
 
 
2772
//-------------------------------------------------
 
2773
//  emit_fld_p - load a floating point parameter
 
2774
//  onto the stack
 
2775
//-------------------------------------------------
 
2776
 
 
2777
void drcbe_x86::emit_fld_p(x86code *&dst, int size, const be_parameter &param)
 
2778
{
 
2779
        assert(param.is_memory());
 
2780
        assert(size == 4 || size == 8);
 
2781
        if (size == 4)
 
2782
                emit_fld_m32(dst, MABS(param.memory()));
 
2783
        else if (size == 8)
 
2784
                emit_fld_m64(dst, MABS(param.memory()));
 
2785
}
 
2786
 
 
2787
 
 
2788
//-------------------------------------------------
 
2789
//  emit_fstp_p - store a floating point parameter
 
2790
//  from the stack and pop it
 
2791
//-------------------------------------------------
 
2792
 
 
2793
void drcbe_x86::emit_fstp_p(x86code *&dst, int size, const be_parameter &param)
 
2794
{
 
2795
        assert(param.is_memory());
 
2796
        assert(size == 4 || size == 8);
 
2797
        if (size == 4)
 
2798
                emit_fstp_m32(dst, MABS(param.memory()));
 
2799
        else if (size == 8)
 
2800
                emit_fstp_m64(dst, MABS(param.memory()));
 
2801
}
 
2802
 
 
2803
 
 
2804
 
 
2805
//**************************************************************************
 
2806
//  OUT-OF-BAND CODE FIXUP CALLBACKS
 
2807
//**************************************************************************
 
2808
 
 
2809
//-------------------------------------------------
 
2810
//  fixup_label - callback to fixup forward-
 
2811
//  referenced labels
 
2812
//-------------------------------------------------
 
2813
 
 
2814
void drcbe_x86::fixup_label(void *parameter, drccodeptr labelcodeptr)
3141
2815
{
3142
2816
        drccodeptr src = (drccodeptr)parameter;
3143
2817
 
3144
 
        /* find the end of the instruction */
 
2818
        // find the end of the instruction
3145
2819
        if (src[0] == 0xe3)
3146
2820
        {
3147
2821
                src += 1 + 1;
3162
2836
}
3163
2837
 
3164
2838
 
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
//-------------------------------------------------
3169
2843
 
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)
3171
2845
{
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;
 
2848
 
 
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);
 
2853
 
 
2854
        // look up the handle target
 
2855
        drccodeptr *targetptr = handp.handle().codeptr_addr();
 
2856
 
 
2857
        // first fixup the jump to get us here
3176
2858
        drccodeptr dst = *codeptr;
3177
 
        drccodeptr *targetptr;
3178
 
 
3179
 
        /* normalize parameters */
3180
 
        param_normalize_2(drcbe, inst, &handp, PTYPE_M, &exp, PTYPE_MRI);
3181
 
 
3182
 
        /* look up the handle target */
3183
 
        targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3184
 
 
3185
 
        /* first fixup the jump to get us here */
3186
2859
        ((UINT32 *)src)[-1] = dst - src;
3187
2860
 
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
3190
2863
 
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
3195
2868
        else
3196
 
                emit_jmp_m32(&dst, MABS(targetptr));                                                                                    // jmp   [targetptr]
 
2869
                emit_jmp_m32(dst, MABS(targetptr));                                                                                     // jmp   [targetptr]
3197
2870
 
3198
2871
        *codeptr = dst;
3199
2872
}
3200
2873
 
3201
2874
 
3202
2875
 
3203
 
/***************************************************************************
3204
 
    DEBUG HELPERS
3205
 
***************************************************************************/
3206
 
 
3207
 
/*-------------------------------------------------
3208
 
    debug_log_hashjmp - callback to handle
3209
 
    logging of hashjmps
3210
 
-------------------------------------------------*/
3211
 
 
3212
 
static void debug_log_hashjmp(int mode, offs_t pc)
 
2876
//**************************************************************************
 
2877
//  DEBUG HELPERS
 
2878
//**************************************************************************
 
2879
 
 
2880
//-------------------------------------------------
 
2881
//  debug_log_hashjmp - callback to handle
 
2882
//  logging of hashjmps
 
2883
//-------------------------------------------------
 
2884
 
 
2885
void drcbe_x86::debug_log_hashjmp(int mode, offs_t pc)
3213
2886
{
3214
2887
        printf("mode=%d PC=%08X\n", mode, pc);
3215
2888
}
3216
2889
 
3217
2890
 
3218
2891
 
3219
 
/***************************************************************************
3220
 
    COMPILE-TIME OPCODES
3221
 
***************************************************************************/
3222
 
 
3223
 
/*-------------------------------------------------
3224
 
    op_handle - process a HANDLE opcode
3225
 
-------------------------------------------------*/
3226
 
 
3227
 
static x86code *op_handle(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
 
2892
//**************************************************************************
 
2893
//  COMPILE-TIME OPCODES
 
2894
//**************************************************************************
 
2895
 
 
2896
//-------------------------------------------------
 
2897
//  op_handle - process a HANDLE opcode
 
2898
//-------------------------------------------------
 
2899
 
 
2900
void drcbe_x86::op_handle(x86code *&dst, const instruction &inst)
3228
2901
{
 
2902
        assert_no_condition(inst);
 
2903
        assert_no_flags(inst);
 
2904
        assert(inst.numparams() == 1);
 
2905
        assert(inst.param(0).is_code_handle());
 
2906
 
 
2907
        reset_last_upper_lower_reg();
 
2908
 
 
2909
        // emit a jump around the stack adjust in case code falls through here
3229
2910
        emit_link skip;
3230
 
 
3231
 
        assert_no_condition(inst);
3232
 
        assert_no_flags(inst);
3233
 
        assert(inst->numparams == 1);
3234
 
        assert(inst->param[0].type == DRCUML_PTYPE_MEMORY);
3235
 
 
3236
 
        reset_last_upper_lower_reg(drcbe);
3237
 
 
3238
 
        /* emit a jump around the stack adjust in case code falls through here */
3239
 
        emit_jmp_short_link(&dst, &skip);                                                                                                       // jmp   skip
3240
 
 
3241
 
        /* register the current pointer for the handle */
3242
 
        drcuml_handle_set_codeptr((drcuml_codehandle *)(FPTR)inst->param[0].value, dst);
3243
 
 
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:
3247
 
        return dst;
3248
 
}
3249
 
 
3250
 
 
3251
 
/*-------------------------------------------------
3252
 
    op_hash - process a HASH opcode
3253
 
-------------------------------------------------*/
3254
 
 
3255
 
static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3256
 
{
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);
3262
 
 
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);
3266
 
        return dst;
3267
 
}
3268
 
 
3269
 
 
3270
 
/*-------------------------------------------------
3271
 
    op_label - process a LABEL opcode
3272
 
-------------------------------------------------*/
3273
 
 
3274
 
static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3275
 
{
3276
 
        assert_no_condition(inst);
3277
 
        assert_no_flags(inst);
3278
 
        assert(inst->numparams == 1);
3279
 
        assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
3280
 
 
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);
3284
 
        return dst;
3285
 
}
3286
 
 
3287
 
 
3288
 
/*-------------------------------------------------
3289
 
    op_comment - process a COMMENT opcode
3290
 
-------------------------------------------------*/
3291
 
 
3292
 
static x86code *op_comment(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3293
 
{
3294
 
        assert_no_condition(inst);
3295
 
        assert_no_flags(inst);
3296
 
        assert(inst->numparams == 1);
3297
 
        assert(inst->param[0].type == DRCUML_PTYPE_MEMORY);
3298
 
 
3299
 
        /* do nothing */
3300
 
        return dst;
3301
 
}
3302
 
 
3303
 
 
3304
 
/*-------------------------------------------------
3305
 
    op_mapvar - process a MAPVAR opcode
3306
 
-------------------------------------------------*/
3307
 
 
3308
 
static x86code *op_mapvar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3309
 
{
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);
3315
 
 
3316
 
        /* set the value of the specified mapvar */
3317
 
        drcmap_set_value(drcbe->map, dst, inst->param[0].value, inst->param[1].value);
3318
 
        return dst;
3319
 
}
3320
 
 
3321
 
 
3322
 
 
3323
 
/***************************************************************************
3324
 
    CONTROL FLOW OPCODES
3325
 
***************************************************************************/
3326
 
 
3327
 
/*-------------------------------------------------
3328
 
    op_nop - process a NOP opcode
3329
 
-------------------------------------------------*/
3330
 
 
3331
 
static x86code *op_nop(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3332
 
{
3333
 
        /* nothing */
3334
 
        return dst;
3335
 
}
3336
 
 
3337
 
 
3338
 
/*-------------------------------------------------
3339
 
    op_debug - process a DEBUG opcode
3340
 
-------------------------------------------------*/
3341
 
 
3342
 
static x86code *op_debug(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3343
 
{
3344
 
        emit_link skip = { 0 };
3345
 
 
3346
 
        /* validate instruction */
3347
 
        assert(inst->size == 4);
3348
 
        assert_no_condition(inst);
3349
 
        assert_no_flags(inst);
3350
 
 
3351
 
        if ((drcbe->device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0)
 
2911
        emit_jmp_short_link(dst, skip);                                                                                                 // jmp   skip
 
2912
 
 
2913
        // register the current pointer for the handle
 
2914
        inst.param(0).handle().set_codeptr(dst);
 
2915
 
 
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:
 
2919
}
 
2920
 
 
2921
 
 
2922
//-------------------------------------------------
 
2923
//  op_hash - process a HASH opcode
 
2924
//-------------------------------------------------
 
2925
 
 
2926
void drcbe_x86::op_hash(x86code *&dst, const instruction &inst)
 
2927
{
 
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());
 
2933
 
 
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();
 
2937
}
 
2938
 
 
2939
 
 
2940
//-------------------------------------------------
 
2941
//  op_label - process a LABEL opcode
 
2942
//-------------------------------------------------
 
2943
 
 
2944
void drcbe_x86::op_label(x86code *&dst, const instruction &inst)
 
2945
{
 
2946
        assert_no_condition(inst);
 
2947
        assert_no_flags(inst);
 
2948
        assert(inst.numparams() == 1);
 
2949
        assert(inst.param(0).is_code_label());
 
2950
 
 
2951
        // register the current pointer for the label
 
2952
        m_labels.set_codeptr(inst.param(0).label(), dst);
 
2953
        reset_last_upper_lower_reg();
 
2954
}
 
2955
 
 
2956
 
 
2957
//-------------------------------------------------
 
2958
//  op_comment - process a COMMENT opcode
 
2959
//-------------------------------------------------
 
2960
 
 
2961
void drcbe_x86::op_comment(x86code *&dst, const instruction &inst)
 
2962
{
 
2963
        assert_no_condition(inst);
 
2964
        assert_no_flags(inst);
 
2965
        assert(inst.numparams() == 1);
 
2966
        assert(inst.param(0).is_string());
 
2967
 
 
2968
        // do nothing
 
2969
}
 
2970
 
 
2971
 
 
2972
//-------------------------------------------------
 
2973
//  op_mapvar - process a MAPVAR opcode
 
2974
//-------------------------------------------------
 
2975
 
 
2976
void drcbe_x86::op_mapvar(x86code *&dst, const instruction &inst)
 
2977
{
 
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());
 
2983
 
 
2984
        // set the value of the specified mapvar
 
2985
        m_map.set_value(dst, inst.param(0).mapvar(), inst.param(1).immediate());
 
2986
}
 
2987
 
 
2988
 
 
2989
 
 
2990
//**************************************************************************
 
2991
//  CONTROL FLOW OPCODES
 
2992
//**************************************************************************
 
2993
 
 
2994
//-------------------------------------------------
 
2995
//  op_nop - process a NOP opcode
 
2996
//-------------------------------------------------
 
2997
 
 
2998
void drcbe_x86::op_nop(x86code *&dst, const instruction &inst)
 
2999
{
 
3000
        // nothing
 
3001
}
 
3002
 
 
3003
 
 
3004
//-------------------------------------------------
 
3005
//  op_debug - process a DEBUG opcode
 
3006
//-------------------------------------------------
 
3007
 
 
3008
void drcbe_x86::op_debug(x86code *&dst, const instruction &inst)
 
3009
{
 
3010
        // validate instruction
 
3011
        assert(inst.size() == 4);
 
3012
        assert_no_condition(inst);
 
3013
        assert_no_flags(inst);
 
3014
 
 
3015
        if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
3352
3016
        {
3353
 
                drcuml_parameter pcp;
3354
 
 
3355
 
                /* normalize parameters */
3356
 
                param_normalize_1(drcbe, inst, &pcp, PTYPE_MRI);
3357
 
 
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
3361
 
 
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
3366
 
 
3367
 
                track_resolve_link(drcbe, &dst, &skip);                                                                         // skip:
 
3017
                // normalize parameters
 
3018
                be_parameter pcp(*this, inst.param(0), PTYPE_MRI);
 
3019
 
 
3020
                // test and branch
 
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
 
3024
 
 
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
 
3029
 
 
3030
                track_resolve_link(dst, skip);                                                                                          // skip:
3368
3031
        }
3369
 
 
3370
 
        return dst;
3371
3032
}
3372
3033
 
3373
3034
 
3374
 
/*-------------------------------------------------
3375
 
    op_exit - process an EXIT opcode
3376
 
-------------------------------------------------*/
 
3035
//-------------------------------------------------
 
3036
//  op_exit - process an EXIT opcode
 
3037
//-------------------------------------------------
3377
3038
 
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)
3379
3040
{
3380
 
        drcuml_parameter retp;
3381
 
 
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);
3386
3045
 
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);
3389
3048
 
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
3394
3053
        else
3395
 
                emit_jcc(&dst, X86_CONDITION(inst->condition), drcbe->exit);                                    // jcc   exit
3396
 
 
3397
 
        return dst;
 
3054
                emit_jcc(dst, X86_CONDITION(inst.condition()), m_exit);                                 // jcc   exit
3398
3055
}
3399
3056
 
3400
3057
 
3401
 
/*-------------------------------------------------
3402
 
    op_hashjmp - process a HASHJMP opcode
3403
 
-------------------------------------------------*/
 
3058
//-------------------------------------------------
 
3059
//  op_hashjmp - process a HASHJMP opcode
 
3060
//-------------------------------------------------
3404
3061
 
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)
3406
3063
{
3407
 
        drcuml_parameter modep, pcp, exp;
3408
 
 
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);
3413
3068
 
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());
3416
3074
 
3417
3075
        if (LOG_HASHJMPS)
3418
3076
        {
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);
3422
3080
        }
3423
3081
 
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]
3426
3084
 
3427
 
        /* fixed mode cases */
3428
 
        if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->base[modep.value] != drcbe->hash->emptyl1)
 
3085
        // fixed mode cases
 
3086
        if (modep.is_immediate() && m_hash.is_mode_populated(modep.immediate()))
3429
3087
        {
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())
3432
3090
                {
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]
3436
3094
                }
3437
3095
 
3438
 
                /* a fixed mode but variable PC */
 
3096
                // a fixed mode but variable PC
3439
3097
                else
3440
3098
                {
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]
3448
3106
                }
3449
3107
        }
3450
3108
        else
3451
3109
        {
3452
 
                /* variable mode */
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]
 
3110
                // variable mode
 
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]
3456
3114
 
3457
 
                /* fixed PC */
3458
 
                if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
 
3115
                // fixed PC
 
3116
                if (pcp.is_immediate())
3459
3117
                {
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]
3464
3122
                }
3465
3123
 
3466
 
                /* variable PC */
 
3124
                // variable PC
3467
3125
                else
3468
3126
                {
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]
3475
3133
                }
3476
3134
        }
3477
3135
 
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]
3482
 
 
3483
 
        return dst;
 
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]
3484
3140
}
3485
3141
 
3486
3142
 
3487
 
/*-------------------------------------------------
3488
 
    op_jmp - process a JMP opcode
3489
 
-------------------------------------------------*/
 
3143
//-------------------------------------------------
 
3144
//  op_jmp - process a JMP opcode
 
3145
//-------------------------------------------------
3490
3146
 
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)
3492
3148
{
3493
 
        drcuml_parameter labelp;
3494
 
        x86code *jmptarget;
3495
 
 
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);
3500
3153
 
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());
3503
3157
 
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
3508
3162
        else
3509
 
                emit_jcc(&dst, X86_CONDITION(inst->condition), jmptarget);                                              // jcc   target
3510
 
 
3511
 
        return dst;
 
3163
                emit_jcc(dst, X86_CONDITION(inst.condition()), jmptarget);                                              // jcc   target
3512
3164
}
3513
3165
 
3514
3166
 
3515
 
/*-------------------------------------------------
3516
 
    op_exh - process an EXH opcode
3517
 
-------------------------------------------------*/
 
3167
//-------------------------------------------------
 
3168
//  op_exh - process an EXH opcode
 
3169
//-------------------------------------------------
3518
3170
 
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)
3520
3172
{
3521
 
        drcuml_parameter handp, exp;
3522
 
        drccodeptr *targetptr;
3523
 
 
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);
3528
3177
 
3529
 
        /* normalize parameters */
3530
 
        param_normalize_2(drcbe, inst, &handp, PTYPE_M, &exp, PTYPE_MRI);
3531
 
 
3532
 
        /* look up the handle target */
3533
 
        targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3534
 
 
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);
 
3182
 
 
3183
        // look up the handle target
 
3184
        drccodeptr *targetptr = handp.handle().codeptr_addr();
 
3185
 
 
3186
        // perform the exception processing inline if unconditional
 
3187
        if (inst.condition() == uml::COND_ALWAYS)
3537
3188
        {
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
3541
3192
                else
3542
 
                        emit_call_m32(&dst, MABS(targetptr));                                                                           // call  [targetptr]
 
3193
                        emit_call_m32(dst, MABS(targetptr));                                                                            // call  [targetptr]
3543
3194
        }
3544
3195
 
3545
 
        /* otherwise, jump to an out-of-band handler */
 
3196
        // otherwise, jump to an out-of-band handler
3546
3197
        else
3547
3198
        {
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);
3550
3201
        }
3551
 
        return dst;
3552
3202
}
3553
3203
 
3554
3204
 
3555
 
/*-------------------------------------------------
3556
 
    op_callh - process a CALLH opcode
3557
 
-------------------------------------------------*/
 
3205
//-------------------------------------------------
 
3206
//  op_callh - process a CALLH opcode
 
3207
//-------------------------------------------------
3558
3208
 
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)
3560
3210
{
3561
 
        drcuml_parameter handp;
3562
 
        drccodeptr *targetptr;
3563
 
        emit_link skip = { 0 };
3564
 
 
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);
3569
3215
 
3570
 
        /* normalize parameters */
3571
 
        param_normalize_1(drcbe, inst, &handp, PTYPE_M);
3572
 
 
3573
 
        /* look up the handle target */
3574
 
        targetptr = drcuml_handle_codeptr_addr((drcuml_codehandle *)(FPTR)handp.value);
3575
 
 
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
3579
 
 
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());
 
3219
 
 
3220
        // look up the handle target
 
3221
        drccodeptr *targetptr = handp.handle().codeptr_addr();
 
3222
 
 
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
 
3227
 
 
3228
        // jump through the handle; directly if a normal jump
3581
3229
        if (*targetptr != NULL)
3582
 
                emit_call(&dst, *targetptr);                                                                                                    // call  *targetptr
3583
 
        else
3584
 
                emit_call_m32(&dst, MABS(targetptr));                                                                                   // call  [targetptr]
3585
 
 
3586
 
        /* resolve the conditional link */
3587
 
        if (inst->condition != DRCUML_COND_ALWAYS)
3588
 
                track_resolve_link(drcbe, &dst, &skip);                                                                         // skip:
3589
 
        return dst;
3590
 
}
3591
 
 
3592
 
 
3593
 
/*-------------------------------------------------
3594
 
    op_ret - process a RET opcode
3595
 
-------------------------------------------------*/
3596
 
 
3597
 
static x86code *op_ret(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3598
 
{
3599
 
        emit_link skip = { 0 };
3600
 
 
3601
 
        /* validate instruction */
3602
 
        assert(inst->size == 4);
3603
 
        assert_any_condition(inst);
3604
 
        assert_no_flags(inst);
3605
 
        assert(inst->numparams == 0);
3606
 
 
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
3610
 
 
3611
 
        /* return */
3612
 
        emit_lea_r32_m32(&dst, REG_ESP, MBD(REG_ESP, 28));                                                                      // lea   rsp,[rsp+28]
3613
 
        emit_ret(&dst);                                                                                                                                         // ret
3614
 
 
3615
 
        /* resolve the conditional link */
3616
 
        if (inst->condition != DRCUML_COND_ALWAYS)
3617
 
                track_resolve_link(drcbe, &dst, &skip);                                                                         // skip:
3618
 
        return dst;
3619
 
}
3620
 
 
3621
 
 
3622
 
/*-------------------------------------------------
3623
 
    op_callc - process a CALLC opcode
3624
 
-------------------------------------------------*/
3625
 
 
3626
 
static x86code *op_callc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3627
 
{
3628
 
        drcuml_parameter funcp, paramp;
3629
 
        emit_link skip = { 0 };
3630
 
 
3631
 
        /* validate instruction */
3632
 
        assert(inst->size == 4);
3633
 
        assert_any_condition(inst);
3634
 
        assert_no_flags(inst);
3635
 
 
3636
 
        /* normalize parameters */
3637
 
        param_normalize_2(drcbe, inst, &funcp, PTYPE_M, &paramp, PTYPE_M);
3638
 
 
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
3642
 
 
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
3646
 
 
3647
 
        /* resolve the conditional link */
3648
 
        if (inst->condition != DRCUML_COND_ALWAYS)
3649
 
                track_resolve_link(drcbe, &dst, &skip);                                                                         // skip:
3650
 
        return dst;
3651
 
}
3652
 
 
3653
 
 
3654
 
/*-------------------------------------------------
3655
 
    op_recover - process a RECOVER opcode
3656
 
-------------------------------------------------*/
3657
 
 
3658
 
static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3659
 
{
3660
 
        drcuml_parameter dstp;
3661
 
 
3662
 
        /* validate instruction */
3663
 
        assert(inst->size == 4);
3664
 
        assert_no_condition(inst);
3665
 
        assert_no_flags(inst);
3666
 
 
3667
 
        /* normalize parameters */
3668
 
        param_normalize(drcbe, &inst->param[0], &dstp, PTYPE_MR);
3669
 
 
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
3679
 
 
3680
 
        return dst;
3681
 
}
3682
 
 
3683
 
 
3684
 
 
3685
 
/***************************************************************************
3686
 
    INTERNAL REGISTER OPCODES
3687
 
***************************************************************************/
3688
 
 
3689
 
/*-------------------------------------------------
3690
 
    op_setfmod - process a SETFMOD opcode
3691
 
-------------------------------------------------*/
3692
 
 
3693
 
static x86code *op_setfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3694
 
{
3695
 
        drcuml_parameter srcp;
3696
 
 
3697
 
        /* validate instruction */
3698
 
        assert(inst->size == 4);
3699
 
        assert_no_condition(inst);
3700
 
        assert_no_flags(inst);
3701
 
 
3702
 
        /* normalize parameters */
3703
 
        param_normalize_1(drcbe, inst, &srcp, PTYPE_MRI);
3704
 
 
3705
 
        /* immediate case */
3706
 
        if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
3707
 
        {
3708
 
                srcp.value &= 3;
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]
3711
 
        }
3712
 
 
3713
 
        /* register/memory case */
3714
 
        else
3715
 
        {
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]
3720
 
        }
3721
 
 
3722
 
        return dst;
3723
 
}
3724
 
 
3725
 
 
3726
 
/*-------------------------------------------------
3727
 
    op_getfmod - process a GETFMOD opcode
3728
 
-------------------------------------------------*/
3729
 
 
3730
 
static x86code *op_getfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3731
 
{
3732
 
        drcuml_parameter dstp;
3733
 
 
3734
 
        /* validate instruction */
3735
 
        assert(inst->size == 4);
3736
 
        assert_no_condition(inst);
3737
 
        assert_no_flags(inst);
3738
 
 
3739
 
        /* normalize parameters */
3740
 
        param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
3741
 
 
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]
3745
 
        else
3746
 
        {
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
3749
 
        }
3750
 
 
3751
 
        return dst;
3752
 
}
3753
 
 
3754
 
 
3755
 
/*-------------------------------------------------
3756
 
    op_getexp - process a GETEXP opcode
3757
 
-------------------------------------------------*/
3758
 
 
3759
 
static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3760
 
{
3761
 
        drcuml_parameter dstp;
3762
 
 
3763
 
        /* validate instruction */
3764
 
        assert(inst->size == 4);
3765
 
        assert_no_condition(inst);
3766
 
        assert_no_flags(inst);
3767
 
 
3768
 
        /* normalize parameters */
3769
 
        param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
3770
 
 
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]
3774
 
        else
3775
 
        {
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
3778
 
        }
3779
 
 
3780
 
        return dst;
3781
 
}
3782
 
 
3783
 
 
3784
 
/*-------------------------------------------------
3785
 
    op_getflgs - process a GETFLGS opcode
3786
 
-------------------------------------------------*/
3787
 
 
3788
 
static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3789
 
{
3790
 
        drcuml_parameter dstp, maskp;
 
3230
                emit_call(dst, *targetptr);                                                                                                     // call  *targetptr
 
3231
        else
 
3232
                emit_call_m32(dst, MABS(targetptr));                                                                                    // call  [targetptr]
 
3233
 
 
3234
        // resolve the conditional link
 
3235
        if (inst.condition() != uml::COND_ALWAYS)
 
3236
                track_resolve_link(dst, skip);                                                                                          // skip:
 
3237
}
 
3238
 
 
3239
 
 
3240
//-------------------------------------------------
 
3241
//  op_ret - process a RET opcode
 
3242
//-------------------------------------------------
 
3243
 
 
3244
void drcbe_x86::op_ret(x86code *&dst, const instruction &inst)
 
3245
{
 
3246
        // validate instruction
 
3247
        assert(inst.size() == 4);
 
3248
        assert_any_condition(inst);
 
3249
        assert_no_flags(inst);
 
3250
        assert(inst.numparams() == 0);
 
3251
 
 
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
 
3256
 
 
3257
        // return
 
3258
        emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, 28));                                                                       // lea   rsp,[rsp+28]
 
3259
        emit_ret(dst);                                                                                                                                          // ret
 
3260
 
 
3261
        // resolve the conditional link
 
3262
        if (inst.condition() != uml::COND_ALWAYS)
 
3263
                track_resolve_link(dst, skip);                                                                                          // skip:
 
3264
}
 
3265
 
 
3266
 
 
3267
//-------------------------------------------------
 
3268
//  op_callc - process a CALLC opcode
 
3269
//-------------------------------------------------
 
3270
 
 
3271
void drcbe_x86::op_callc(x86code *&dst, const instruction &inst)
 
3272
{
 
3273
        // validate instruction
 
3274
        assert(inst.size() == 4);
 
3275
        assert_any_condition(inst);
 
3276
        assert_no_flags(inst);
 
3277
 
 
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);
 
3282
 
 
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
 
3287
 
 
3288
        // perform the call
 
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
 
3291
 
 
3292
        // resolve the conditional link
 
3293
        if (inst.condition() != uml::COND_ALWAYS)
 
3294
                track_resolve_link(dst, skip);                                                                                          // skip:
 
3295
}
 
3296
 
 
3297
 
 
3298
//-------------------------------------------------
 
3299
//  op_recover - process a RECOVER opcode
 
3300
//-------------------------------------------------
 
3301
 
 
3302
void drcbe_x86::op_recover(x86code *&dst, const instruction &inst)
 
3303
{
 
3304
        // validate instruction
 
3305
        assert(inst.size() == 4);
 
3306
        assert_no_condition(inst);
 
3307
        assert_no_flags(inst);
 
3308
 
 
3309
        // normalize parameters
 
3310
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
3311
 
 
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
 
3321
}
 
3322
 
 
3323
 
 
3324
 
 
3325
//**************************************************************************
 
3326
//  INTERNAL REGISTER OPCODES
 
3327
//**************************************************************************
 
3328
 
 
3329
//-------------------------------------------------
 
3330
//  op_setfmod - process a SETFMOD opcode
 
3331
//-------------------------------------------------
 
3332
 
 
3333
void drcbe_x86::op_setfmod(x86code *&dst, const instruction &inst)
 
3334
{
 
3335
        // validate instruction
 
3336
        assert(inst.size() == 4);
 
3337
        assert_no_condition(inst);
 
3338
        assert_no_flags(inst);
 
3339
 
 
3340
        // normalize parameters
 
3341
        be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
 
3342
 
 
3343
        // immediate case
 
3344
        if (srcp.is_immediate())
 
3345
        {
 
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]
 
3349
        }
 
3350
 
 
3351
        // register/memory case
 
3352
        else
 
3353
        {
 
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]
 
3358
        }
 
3359
}
 
3360
 
 
3361
 
 
3362
//-------------------------------------------------
 
3363
//  op_getfmod - process a GETFMOD opcode
 
3364
//-------------------------------------------------
 
3365
 
 
3366
void drcbe_x86::op_getfmod(x86code *&dst, const instruction &inst)
 
3367
{
 
3368
        // validate instruction
 
3369
        assert(inst.size() == 4);
 
3370
        assert_no_condition(inst);
 
3371
        assert_no_flags(inst);
 
3372
 
 
3373
        // normalize parameters
 
3374
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
3375
 
 
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]
 
3379
        else
 
3380
        {
 
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
 
3383
        }
 
3384
}
 
3385
 
 
3386
 
 
3387
//-------------------------------------------------
 
3388
//  op_getexp - process a GETEXP opcode
 
3389
//-------------------------------------------------
 
3390
 
 
3391
void drcbe_x86::op_getexp(x86code *&dst, const instruction &inst)
 
3392
{
 
3393
        // validate instruction
 
3394
        assert(inst.size() == 4);
 
3395
        assert_no_condition(inst);
 
3396
        assert_no_flags(inst);
 
3397
 
 
3398
        // normalize parameters
 
3399
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
3400
 
 
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]
 
3404
        else
 
3405
        {
 
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
 
3408
        }
 
3409
}
 
3410
 
 
3411
 
 
3412
//-------------------------------------------------
 
3413
//  op_getflgs - process a GETFLGS opcode
 
3414
//-------------------------------------------------
 
3415
 
 
3416
void drcbe_x86::op_getflgs(x86code *&dst, const instruction &inst)
 
3417
{
 
3418
        // validate instruction
 
3419
        assert(inst.size() == 4);
 
3420
        assert_no_condition(inst);
 
3421
        assert_no_flags(inst);
 
3422
 
 
3423
        // normalize parameters
 
3424
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
3425
        be_parameter maskp(*this, inst.param(1), PTYPE_I);
 
3426
 
 
3427
        // pick a target register for the general case
 
3428
        int dstreg = dstp.select_register(REG_EAX);
 
3429
 
 
3430
        // compute mask for flags
3791
3431
        UINT32 flagmask = 0;
3792
 
        int dstreg;
3793
 
 
3794
 
        /* validate instruction */
3795
 
        assert(inst->size == 4);
3796
 
        assert_no_condition(inst);
3797
 
        assert_no_flags(inst);
3798
 
 
3799
 
        /* normalize parameters */
3800
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &maskp, PTYPE_I);
3801
 
 
3802
 
        /* pick a target register for the general case */
3803
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
3804
 
 
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;
3811
 
 
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;
 
3437
 
 
3438
        switch (maskp.immediate())
3813
3439
        {
3814
 
                /* single flags only */
3815
 
                case DRCUML_FLAG_C:
3816
 
                        emit_setcc_r8(&dst, COND_C, REG_AL);                                                                            // setc   al
3817
 
                        emit_movzx_r32_r8(&dst, dstreg, REG_AL);                                                                        // movzx  dstreg,al
3818
 
                        break;
3819
 
 
3820
 
                case DRCUML_FLAG_V:
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
3824
 
                        break;
3825
 
 
3826
 
                case DRCUML_FLAG_Z:
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
3830
 
                        break;
3831
 
 
3832
 
                case DRCUML_FLAG_S:
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
3836
 
                        break;
3837
 
 
3838
 
                case DRCUML_FLAG_U:
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
3842
 
                        break;
3843
 
 
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]
3851
 
                        break;
3852
 
 
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]
3859
 
                        break;
3860
 
 
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]
3867
 
                        break;
3868
 
 
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
3877
 
                        break;
3878
 
 
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
3886
 
                        break;
3887
 
 
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
3896
 
                        break;
3897
 
 
3898
 
                /* default cases */
 
3440
                // single flags only
 
3441
                case FLAG_C:
 
3442
                        emit_setcc_r8(dst, x86emit::COND_C, REG_AL);                                                                            // setc   al
 
3443
                        emit_movzx_r32_r8(dst, dstreg, REG_AL);                                                                 // movzx  dstreg,al
 
3444
                        break;
 
3445
 
 
3446
                case FLAG_V:
 
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
 
3450
                        break;
 
3451
 
 
3452
                case FLAG_Z:
 
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
 
3456
                        break;
 
3457
 
 
3458
                case FLAG_S:
 
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
 
3462
                        break;
 
3463
 
 
3464
                case FLAG_U:
 
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
 
3468
                        break;
 
3469
 
 
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]
 
3477
                        break;
 
3478
 
 
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]
 
3485
                        break;
 
3486
 
 
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]
 
3493
                        break;
 
3494
 
 
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
 
3503
                        break;
 
3504
 
 
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
 
3512
                        break;
 
3513
 
 
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
 
3522
                        break;
 
3523
 
 
3524
                // default cases
3899
3525
                default:
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]
3904
3530
                        break;
3905
3531
        }
3906
3532
 
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
3909
3535
 
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)
3912
3538
        {
3913
 
                /* general case */
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
 
3539
                // general case
 
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
3918
3544
        }
3919
 
        return dst;
3920
 
}
3921
 
 
3922
 
 
3923
 
/*-------------------------------------------------
3924
 
    op_save - process a SAVE opcode
3925
 
-------------------------------------------------*/
3926
 
 
3927
 
static x86code *op_save(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3928
 
{
3929
 
        drcuml_parameter dstp;
3930
 
 
3931
 
        /* validate instruction */
3932
 
        assert(inst->size == 4);
3933
 
        assert_no_condition(inst);
3934
 
        assert_no_flags(inst);
3935
 
 
3936
 
        /* normalize parameters */
3937
 
        param_normalize_1(drcbe, inst, &dstp, PTYPE_M);
3938
 
 
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
3942
 
        return dst;
3943
 
}
3944
 
 
3945
 
 
3946
 
/*-------------------------------------------------
3947
 
    op_restore - process a RESTORE opcode
3948
 
-------------------------------------------------*/
3949
 
 
3950
 
static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3951
 
{
3952
 
        drcuml_parameter dstp;
3953
 
 
3954
 
        /* validate instruction */
3955
 
        assert(inst->size == 4);
3956
 
        assert_no_condition(inst);
3957
 
 
3958
 
        /* normalize parameters */
3959
 
        param_normalize_1(drcbe, inst, &dstp, PTYPE_M);
3960
 
 
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
3964
 
        return dst;
3965
 
}
3966
 
 
3967
 
 
3968
 
 
3969
 
/***************************************************************************
3970
 
    INTEGER OPERATIONS
3971
 
***************************************************************************/
3972
 
 
3973
 
/*-------------------------------------------------
3974
 
    op_load - process a LOAD opcode
3975
 
-------------------------------------------------*/
3976
 
 
3977
 
static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
3978
 
{
3979
 
        drcuml_parameter dstp, basep, indp, scalesizep;
3980
 
        int dstreg, scale, size;
3981
 
 
3982
 
        /* validate instruction */
3983
 
        assert(inst->size == 4 || inst->size == 8);
3984
 
        assert_no_condition(inst);
3985
 
        assert_no_flags(inst);
3986
 
 
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;
3991
 
 
3992
 
        /* pick a target register for the general case */
3993
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
3994
 
 
3995
 
        /* immediate index */
3996
 
        if (indp.type == DRCUML_PTYPE_IMMEDIATE)
 
3545
}
 
3546
 
 
3547
 
 
3548
//-------------------------------------------------
 
3549
//  op_save - process a SAVE opcode
 
3550
//-------------------------------------------------
 
3551
 
 
3552
void drcbe_x86::op_save(x86code *&dst, const instruction &inst)
 
3553
{
 
3554
        // validate instruction
 
3555
        assert(inst.size() == 4);
 
3556
        assert_no_condition(inst);
 
3557
        assert_no_flags(inst);
 
3558
 
 
3559
        // normalize parameters
 
3560
        be_parameter dstp(*this, inst.param(0), PTYPE_M);
 
3561
 
 
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
 
3565
}
 
3566
 
 
3567
 
 
3568
//-------------------------------------------------
 
3569
//  op_restore - process a RESTORE opcode
 
3570
//-------------------------------------------------
 
3571
 
 
3572
void drcbe_x86::op_restore(x86code *&dst, const instruction &inst)
 
3573
{
 
3574
        // validate instruction
 
3575
        assert(inst.size() == 4);
 
3576
        assert_no_condition(inst);
 
3577
 
 
3578
        // normalize parameters
 
3579
        be_parameter srcp(*this, inst.param(0), PTYPE_M);
 
3580
 
 
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
 
3584
}
 
3585
 
 
3586
 
 
3587
 
 
3588
//**************************************************************************
 
3589
//  INTEGER OPERATIONS
 
3590
//**************************************************************************
 
3591
 
 
3592
//-------------------------------------------------
 
3593
//  op_load - process a LOAD opcode
 
3594
//-------------------------------------------------
 
3595
 
 
3596
void drcbe_x86::op_load(x86code *&dst, const instruction &inst)
 
3597
{
 
3598
        // validate instruction
 
3599
        assert(inst.size() == 4 || inst.size() == 8);
 
3600
        assert_no_condition(inst);
 
3601
        assert_no_flags(inst);
 
3602
 
 
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();
 
3611
 
 
3612
        // pick a target register for the general case
 
3613
        int dstreg = dstp.select_register(REG_EAX);
 
3614
 
 
3615
        // immediate index
 
3616
        if (indp.is_immediate())
3997
3617
        {
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)
4005
3625
                {
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]
4008
3628
                }
4009
3629
        }
4010
3630
 
4011
 
        /* other index */
 
3631
        // other index
4012
3632
        else
4013
3633
        {
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)
4023
3643
                {
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]
4026
3646
                }
4027
3647
        }
4028
3648
 
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
4031
3651
 
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)
4034
3654
        {
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)
4037
3657
                {
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
4042
3662
                }
4043
3663
 
4044
 
                /* 8-byte case */
 
3664
                // 8-byte case
4045
3665
                else
4046
3666
                {
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);
4052
3672
                }
4053
3673
        }
4054
 
        set_last_lower_reg(drcbe, dst, &dstp, dstreg);
4055
 
        return dst;
 
3674
        set_last_lower_reg(dst, dstp, dstreg);
4056
3675
}
4057
3676
 
4058
3677
 
4059
 
/*-------------------------------------------------
4060
 
    op_loads - process a LOADS opcode
4061
 
-------------------------------------------------*/
 
3678
//-------------------------------------------------
 
3679
//  op_loads - process a LOADS opcode
 
3680
//-------------------------------------------------
4062
3681
 
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)
4064
3683
{
4065
 
        drcuml_parameter dstp, basep, indp, scalesizep;
4066
 
        int dstreg, scale, size;
4067
 
 
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);
4072
3688
 
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;
4077
 
 
4078
 
        /* pick a target register for the general case */
4079
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
4080
 
 
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();
 
3697
 
 
3698
        // pick a target register for the general case
 
3699
        int dstreg = dstp.select_register(REG_EAX);
 
3700
 
 
3701
        // immediate index
 
3702
        if (indp.is_immediate())
4083
3703
        {
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)
4091
3711
                {
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]
4094
3714
                }
4095
3715
        }
4096
3716
 
4097
 
        /* other index */
 
3717
        // other index
4098
3718
        else
4099
3719
        {
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)
4109
3729
                {
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]
4112
3732
                }
4113
3733
        }
4114
3734
 
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
4117
3737
 
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)
4120
3740
        {
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);
4127
3747
        }
4128
 
        set_last_lower_reg(drcbe, dst, &dstp, dstreg);
4129
 
        return dst;
 
3748
        set_last_lower_reg(dst, dstp, dstreg);
4130
3749
}
4131
3750
 
4132
3751
 
4133
 
/*-------------------------------------------------
4134
 
    op_store - process a STORE opcode
4135
 
-------------------------------------------------*/
 
3752
//-------------------------------------------------
 
3753
//  op_store - process a STORE opcode
 
3754
//-------------------------------------------------
4136
3755
 
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)
4138
3757
{
4139
 
        drcuml_parameter srcp, basep, indp, scalesizep;
4140
 
        int srcreg, scale, size;
4141
 
 
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);
4146
3762
 
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();
4151
3770
 
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;
4156
3775
 
4157
 
        /* degenerate case: constant index */
4158
 
        if (indp.type == DRCUML_PTYPE_IMMEDIATE)
 
3776
        // degenerate case: constant index
 
3777
        if (indp.is_immediate())
4159
3778
        {
4160
 
                /* immediate source */
4161
 
                if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
 
3779
                // immediate source
 
3780
                if (srcp.is_immediate())
4162
3781
                {
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)
4170
3789
                        {
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
4174
3793
                        }
4175
3794
                }
4176
3795
 
4177
 
                /* variable source */
 
3796
                // variable source
4178
3797
                else
4179
3798
                {
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
4182
3801
                        else
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)
4191
3810
                        {
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
4194
3813
                        }
4195
3814
                }
4196
3815
        }
4197
3816
 
4198
 
        /* normal case: variable index */
 
3817
        // normal case: variable index
4199
3818
        else
4200
3819
        {
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
4203
3822
 
4204
 
                /* immediate source */
4205
 
                if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
 
3823
                // immediate source
 
3824
                if (srcp.is_immediate())
4206
3825
                {
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)
4214
3833
                        {
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
4218
3837
                        }
4219
3838
                }
4220
3839
 
4221
 
                /* variable source */
 
3840
                // variable source
4222
3841
                else
4223
3842
                {
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
4226
3845
                        else
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)
4235
3854
                        {
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
4238
3857
                        }
4239
3858
                }
4240
3859
        }
4241
 
        return dst;
4242
3860
}
4243
3861
 
4244
3862
 
4245
 
/*-------------------------------------------------
4246
 
    op_read - process a READ opcode
4247
 
-------------------------------------------------*/
 
3863
//-------------------------------------------------
 
3864
//  op_read - process a READ opcode
 
3865
//-------------------------------------------------
4248
3866
 
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)
4250
3868
{
4251
 
        drcuml_parameter dstp, addrp, spacesizep;
4252
 
        int dstreg;
4253
 
 
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);
4258
3873
 
4259
 
        /* normalize parameters */
4260
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &spacesizep, PTYPE_I);
4261
 
 
4262
 
        /* pick a target register for the general case */
4263
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
4264
 
 
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());
 
3879
 
 
3880
        // pick a target register for the general case
 
3881
        int dstreg = dstp.select_register(REG_EAX);
 
3882
 
 
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)
4269
3887
        {
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
4273
3891
        }
4274
 
        else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
 
3892
        else if (spacesizep.size() == SIZE_WORD)
4275
3893
        {
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
4279
3897
        }
4280
 
        else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
 
3898
        else if (spacesizep.size() == SIZE_DWORD)
4281
3899
        {
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
4285
3903
        }
4286
 
        else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
 
3904
        else if (spacesizep.size() == SIZE_QWORD)
4287
3905
        {
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
4291
3909
        }
4292
3910
 
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
4295
3913
 
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)
4298
3916
        {
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)
4301
3919
                {
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
4306
3924
                }
4307
3925
 
4308
 
                /* 8-byte case */
 
3926
                // 8-byte case
4309
3927
                else
4310
3928
                {
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
4315
3933
                }
4316
3934
        }
4317
 
        return dst;
4318
3935
}
4319
3936
 
4320
3937
 
4321
 
/*-------------------------------------------------
4322
 
    op_readm - process a READM opcode
4323
 
-------------------------------------------------*/
 
3938
//-------------------------------------------------
 
3939
//  op_readm - process a READM opcode
 
3940
//-------------------------------------------------
4324
3941
 
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)
4326
3943
{
4327
 
        drcuml_parameter dstp, addrp, maskp, spacesizep;
4328
 
        int dstreg;
4329
 
 
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);
4334
3948
 
4335
 
        /* normalize parameters */
4336
 
        param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
4337
 
 
4338
 
        /* pick a target register for the general case */
4339
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
4340
 
 
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());
 
3955
 
 
3956
        // pick a target register for the general case
 
3957
        int dstreg = dstp.select_register(REG_EAX);
 
3958
 
 
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
4344
3962
        else
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)
4349
3967
        {
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
4353
3971
        }
4354
 
        else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
 
3972
        else if (spacesizep.size() == SIZE_DWORD)
4355
3973
        {
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
4359
3977
        }
4360
 
        else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
 
3978
        else if (spacesizep.size() == SIZE_QWORD)
4361
3979
        {
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
4365
3983
        }
4366
3984
 
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
4369
3987
 
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)
4372
3990
        {
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)
4375
3993
                {
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
4380
3998
                }
4381
3999
 
4382
 
                /* 8-byte case */
 
4000
                // 8-byte case
4383
4001
                else
4384
4002
                {
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
4389
4007
                }
4390
4008
        }
4391
 
        return dst;
4392
4009
}
4393
4010
 
4394
4011
 
4395
 
/*-------------------------------------------------
4396
 
    op_write - process a WRITE opcode
4397
 
-------------------------------------------------*/
 
4012
//-------------------------------------------------
 
4013
//  op_write - process a WRITE opcode
 
4014
//-------------------------------------------------
4398
4015
 
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)
4400
4017
{
4401
 
        drcuml_parameter addrp, srcp, spacesizep;
4402
 
 
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);
4407
4022
 
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());
4410
4028
 
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
4414
4032
        else
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
4430
 
        return dst;
4431
4048
}
4432
4049
 
4433
4050
 
4434
 
/*-------------------------------------------------
4435
 
    op_writem - process a WRITEM opcode
4436
 
-------------------------------------------------*/
 
4051
//-------------------------------------------------
 
4052
//  op_writem - process a WRITEM opcode
 
4053
//-------------------------------------------------
4437
4054
 
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)
4439
4056
{
4440
 
        drcuml_parameter addrp, srcp, maskp, spacesizep;
4441
 
 
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);
4446
4061
 
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());
4449
4068
 
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)
4452
4071
        {
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
4455
4074
        }
4456
4075
        else
4457
4076
        {
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
4460
4079
        }
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
4472
 
        return dst;
4473
4091
}
4474
4092
 
4475
4093
 
4476
 
/*-------------------------------------------------
4477
 
    op_carry - process a CARRY opcode
4478
 
-------------------------------------------------*/
 
4094
//-------------------------------------------------
 
4095
//  op_carry - process a CARRY opcode
 
4096
//-------------------------------------------------
4479
4097
 
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)
4481
4099
{
4482
 
        drcuml_parameter srcp, bitp;
4483
 
 
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);
4488
 
 
4489
 
        /* normalize parameters */
4490
 
        param_normalize_2(drcbe, inst, &srcp, PTYPE_MRI, &bitp, PTYPE_MRI);
4491
 
 
4492
 
        /* degenerate case: source is immediate */
4493
 
        if (srcp.type == DRCUML_PTYPE_IMMEDIATE && bitp.type == DRCUML_PTYPE_IMMEDIATE)
4494
 
        {
4495
 
                if (srcp.value & ((UINT64)1 << bitp.value))
4496
 
                        emit_stc(&dst);
4497
 
                else
4498
 
                        emit_clc(&dst);
4499
 
                return dst;
4500
 
        }
4501
 
 
4502
 
        /* load non-immediate bit numbers into a register */
4503
 
        if (bitp.type != DRCUML_PTYPE_IMMEDIATE)
4504
 
        {
4505
 
                emit_mov_r32_p32(drcbe, &dst, REG_ECX, &bitp);
4506
 
                emit_and_r32_imm(&dst, REG_ECX, inst->size * 8 - 1);
4507
 
        }
4508
 
 
4509
 
        /* 32-bit form */
4510
 
        if (inst->size == 4)
4511
 
        {
4512
 
                if (bitp.type == DRCUML_PTYPE_IMMEDIATE)
4513
 
                {
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
4518
 
                }
4519
 
                else
4520
 
                {
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
4525
 
                }
4526
 
        }
4527
 
 
4528
 
        /* 64-bit form */
 
4103
        assert_flags(inst, FLAG_C);
 
4104
 
 
4105
        // normalize parameters
 
4106
        be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
 
4107
        be_parameter bitp(*this, inst.param(1), PTYPE_MRI);
 
4108
 
 
4109
        // degenerate case: source is immediate
 
4110
        if (srcp.is_immediate() && bitp.is_immediate())
 
4111
        {
 
4112
                if (srcp.immediate() & ((UINT64)1 << bitp.immediate()))
 
4113
                        emit_stc(dst);
 
4114
                else
 
4115
                        emit_clc(dst);
 
4116
                }
 
4117
 
 
4118
        // load non-immediate bit numbers into a register
 
4119
        if (!bitp.is_immediate())
 
4120
        {
 
4121
                emit_mov_r32_p32(dst, REG_ECX, bitp);
 
4122
                emit_and_r32_imm(dst, REG_ECX, inst.size() * 8 - 1);
 
4123
        }
 
4124
 
 
4125
        // 32-bit form
 
4126
        if (inst.size() == 4)
 
4127
        {
 
4128
                if (bitp.is_immediate())
 
4129
                {
 
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
 
4134
                }
 
4135
                else
 
4136
                {
 
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
 
4141
                }
 
4142
        }
 
4143
 
 
4144
        // 64-bit form
4529
4145
        else
4530
4146
        {
4531
 
                if (bitp.type == DRCUML_PTYPE_IMMEDIATE)
 
4147
                if (bitp.is_immediate())
4532
4148
                {
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
4539
4155
                }
4540
4156
                else
4541
4157
                {
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())
4545
4161
                        {
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
4548
4164
                        }
4549
4165
                }
4550
4166
        }
4551
 
        return dst;
4552
4167
}
4553
4168
 
4554
4169
 
4555
 
/*-------------------------------------------------
4556
 
    op_set - process a SET opcode
4557
 
-------------------------------------------------*/
 
4170
//-------------------------------------------------
 
4171
//  op_set - process a SET opcode
 
4172
//-------------------------------------------------
4558
4173
 
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)
4560
4175
{
4561
 
        drcuml_parameter dstp;
4562
 
        int dstreg;
4563
 
 
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);
4568
4180
 
4569
 
        /* normalize parameters */
4570
 
        param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
4571
 
 
4572
 
        /* pick a target register for the general case */
4573
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
4574
 
 
4575
 
        /* set to AL */
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
4578
 
 
4579
 
        /* store low 32 bits */
4580
 
        emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg);                                                                           // mov   dstp,dstreg
4581
 
 
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);
 
4183
 
 
4184
        // pick a target register for the general case
 
4185
        int dstreg = dstp.select_register(REG_EAX);
 
4186
 
 
4187
        // set to AL
 
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
 
4190
 
 
4191
        // store low 32 bits
 
4192
        emit_mov_p32_r32(dst, dstp, dstreg);                                                                            // mov   dstp,dstreg
 
4193
 
 
4194
        // 64-bit form stores upper 32 bits
 
4195
        if (inst.size() == 8)
4584
4196
        {
4585
 
                /* general case */
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
 
4197
                // general case
 
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
4590
4202
        }
4591
 
        return dst;
4592
4203
}
4593
4204
 
4594
4205
 
4595
 
/*-------------------------------------------------
4596
 
    op_mov - process a MOV opcode
4597
 
-------------------------------------------------*/
 
4206
//-------------------------------------------------
 
4207
//  op_mov - process a MOV opcode
 
4208
//-------------------------------------------------
4598
4209
 
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)
4600
4211
{
4601
 
        drcuml_parameter dstp, srcp;
4602
4212
        x86code *savedst = dst;
4603
 
        emit_link skip = { 0 };
4604
 
        int dstreg;
4605
4213
 
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);
4610
4218
 
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);
4615
 
        else
4616
 
        {
4617
 
                dstp = inst->param[0];
4618
 
                srcp = inst->param[1];
4619
 
        }
4620
 
 
4621
 
        /* pick a target register for the general case */
4622
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
4623
 
 
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
4627
 
 
4628
 
        /* 32-bit form */
4629
 
        if (inst->size == 4)
4630
 
        {
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
4634
 
 
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
4638
 
 
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);
 
4222
 
 
4223
        // pick a target register for the general case
 
4224
        int dstreg = dstp.select_register(REG_EAX);
 
4225
 
 
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
 
4230
 
 
4231
        // 32-bit form
 
4232
        if (inst.size() == 4)
 
4233
        {
 
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
 
4237
 
 
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
 
4241
 
 
4242
                // conditional memory to register
 
4243
                else if (inst.condition() != uml::COND_ALWAYS && dstp.is_int_register() && srcp.is_memory())
4641
4244
                {
4642
4245
                        dst = savedst;
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]
4646
4249
                }
4647
4250
 
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())
4650
4253
                {
4651
4254
                        dst = savedst;
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
4655
4258
                }
4656
4259
 
4657
 
                /* general case */
 
4260
                // general case
4658
4261
                else
4659
4262
                {
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
4662
4265
                }
4663
4266
        }
4664
4267
 
4665
 
        /* 64-bit form */
4666
 
        else if (inst->size == 8)
 
4268
        // 64-bit form
 
4269
        else if (inst.size() == 8)
4667
4270
        {
4668
 
                /* register to memory */
4669
 
                if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_INT_REGISTER)
4670
 
                {
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
4674
 
                }
4675
 
 
4676
 
                /* immediate to memory */
4677
 
                else if (dstp.type == DRCUML_PTYPE_MEMORY && srcp.type == DRCUML_PTYPE_IMMEDIATE)
4678
 
                {
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
4681
 
                }
4682
 
 
4683
 
                /* general case */
 
4271
                // register to memory
 
4272
                if (dstp.is_memory() && srcp.is_int_register())
 
4273
                {
 
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
 
4277
                }
 
4278
 
 
4279
                // immediate to memory
 
4280
                else if (dstp.is_memory() && srcp.is_immediate())
 
4281
                {
 
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
 
4284
                }
 
4285
 
 
4286
                // general case
4684
4287
                else
4685
4288
                {
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
4688
4291
                }
4689
4292
        }
4690
4293
 
4691
 
        /* resolve the jump */
 
4294
        // resolve the jump
4692
4295
        if (skip.target != NULL)
4693
 
                track_resolve_link(drcbe, &dst, &skip);
4694
 
        return dst;
4695
 
}
4696
 
 
4697
 
 
4698
 
/*-------------------------------------------------
4699
 
    op_sext - process a SEXT opcode
4700
 
-------------------------------------------------*/
4701
 
 
4702
 
static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4703
 
{
4704
 
        drcuml_parameter dstp, srcp, sizep;
4705
 
        int dstreg;
4706
 
 
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);
4711
 
 
4712
 
        /* normalize parameters */
4713
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
4714
 
 
4715
 
        /* pick a target register for the general case */
4716
 
        dstreg = (inst->size == 8) ? REG_EAX : param_select_register(REG_EAX, &dstp, NULL);
4717
 
 
4718
 
        /* convert 8-bit source registers to EAX */
4719
 
        if (sizep.value == DRCUML_SIZE_BYTE && srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
4720
 
        {
4721
 
                emit_mov_r32_r32(&dst, REG_EAX, srcp.value);                                                                    // mov   eax,srcp
4722
 
                srcp.value = REG_EAX;
4723
 
        }
4724
 
 
4725
 
        /* general case */
4726
 
        if (srcp.type == DRCUML_PTYPE_MEMORY)
4727
 
        {
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]
4734
 
        }
4735
 
        else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
4736
 
        {
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
4743
 
        }
4744
 
        if (inst->flags != 0)
4745
 
                emit_test_r32_r32(&dst, dstreg, dstreg);                                                                                // test  dstreg,dstreg
4746
 
 
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
4750
 
 
4751
 
        /* 64-bit form: sign extend to 64 bits and store edx:eax */
4752
 
        else if (inst->size == 8)
4753
 
        {
4754
 
                emit_cdq(&dst);                                                                                                                                 // cdq
4755
 
                emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX);                                                 // mov   dstp,edx:eax
4756
 
        }
4757
 
        return dst;
4758
 
}
4759
 
 
4760
 
 
4761
 
/*-------------------------------------------------
4762
 
    op_roland - process an ROLAND opcode
4763
 
-------------------------------------------------*/
4764
 
 
4765
 
static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4766
 
{
4767
 
        drcuml_parameter dstp, srcp, shiftp, maskp;
4768
 
        int dstreg;
4769
 
 
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);
4774
 
 
4775
 
        /* normalize parameters */
4776
 
        param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &shiftp, PTYPE_MRI, &maskp, PTYPE_MRI);
4777
 
 
4778
 
        /* pick a target register for the general case */
4779
 
        dstreg = param_select_register2(REG_EAX, &dstp, &shiftp, &maskp);
4780
 
 
4781
 
        /* 32-bit form */
4782
 
        if (inst->size == 4)
4783
 
        {
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
4788
 
        }
4789
 
 
4790
 
        /* 64-bit form */
4791
 
        else if (inst->size == 8)
4792
 
        {
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
4797
 
        }
4798
 
        return dst;
4799
 
}
4800
 
 
4801
 
 
4802
 
/*-------------------------------------------------
4803
 
    op_rolins - process an ROLINS opcode
4804
 
-------------------------------------------------*/
4805
 
 
4806
 
static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4807
 
{
4808
 
        drcuml_parameter dstp, srcp, shiftp, maskp;
4809
 
        int dstreg;
4810
 
 
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);
4815
 
 
4816
 
        /* normalize parameters */
4817
 
        param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &shiftp, PTYPE_MRI, &maskp, PTYPE_MRI);
4818
 
 
4819
 
        /* pick a target register for the general case */
4820
 
        dstreg = param_select_register2(REG_ECX, &dstp, &shiftp, &maskp);
4821
 
 
4822
 
        /* 32-bit form */
4823
 
        if (inst->size == 4)
4824
 
        {
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);
 
4297
}
 
4298
 
 
4299
 
 
4300
//-------------------------------------------------
 
4301
//  op_sext - process a SEXT opcode
 
4302
//-------------------------------------------------
 
4303
 
 
4304
void drcbe_x86::op_sext(x86code *&dst, const instruction &inst)
 
4305
{
 
4306
        // validate instruction
 
4307
        assert(inst.size() == 4 || inst.size() == 8);
 
4308
        assert_no_condition(inst);
 
4309
        assert_flags(inst, FLAG_S | FLAG_Z);
 
4310
 
 
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());
 
4316
 
 
4317
        // pick a target register for the general case
 
4318
        int dstreg = (inst.size() == 8) ? REG_EAX : dstp.select_register(REG_EAX);
 
4319
 
 
4320
        // convert 8-bit source registers to EAX
 
4321
        if (sizep.size() == SIZE_BYTE && srcp.is_int_register() && (srcp.ireg() & 4))
 
4322
        {
 
4323
                emit_mov_r32_r32(dst, REG_EAX, srcp.ireg());                                                                    // mov   eax,srcp
 
4324
                srcp = be_parameter::make_ireg(REG_EAX);
 
4325
        }
 
4326
 
 
4327
        // general case
 
4328
        if (srcp.is_memory())
 
4329
        {
 
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]
 
4336
        }
 
4337
        else if (srcp.is_int_register())
 
4338
        {
 
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
 
4345
        }
 
4346
        if (inst.flags() != 0)
 
4347
                emit_test_r32_r32(dst, dstreg, dstreg);                                                                         // test  dstreg,dstreg
 
4348
 
 
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
 
4352
 
 
4353
        // 64-bit form: sign extend to 64 bits and store edx:eax
 
4354
        else if (inst.size() == 8)
 
4355
        {
 
4356
                emit_cdq(dst);                                                                                                                                  // cdq
 
4357
                emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX);                                                  // mov   dstp,edx:eax
 
4358
        }
 
4359
}
 
4360
 
 
4361
 
 
4362
//-------------------------------------------------
 
4363
//  op_roland - process an ROLAND opcode
 
4364
//-------------------------------------------------
 
4365
 
 
4366
void drcbe_x86::op_roland(x86code *&dst, const instruction &inst)
 
4367
{
 
4368
        // validate instruction
 
4369
        assert(inst.size() == 4 || inst.size() == 8);
 
4370
        assert_no_condition(inst);
 
4371
        assert_flags(inst, FLAG_S | FLAG_Z);
 
4372
 
 
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);
 
4378
 
 
4379
        // pick a target register for the general case
 
4380
        int dstreg = dstp.select_register(REG_EAX, shiftp, maskp);
 
4381
 
 
4382
        // 32-bit form
 
4383
        if (inst.size() == 4)
 
4384
        {
 
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
 
4389
        }
 
4390
 
 
4391
        // 64-bit form
 
4392
        else if (inst.size() == 8)
 
4393
        {
 
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
 
4398
        }
 
4399
}
 
4400
 
 
4401
 
 
4402
//-------------------------------------------------
 
4403
//  op_rolins - process an ROLINS opcode
 
4404
//-------------------------------------------------
 
4405
 
 
4406
void drcbe_x86::op_rolins(x86code *&dst, const instruction &inst)
 
4407
{
 
4408
        // validate instruction
 
4409
        assert(inst.size() == 4 || inst.size() == 8);
 
4410
        assert_no_condition(inst);
 
4411
        assert_flags(inst, FLAG_S | FLAG_Z);
 
4412
 
 
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);
 
4418
 
 
4419
        // pick a target register for the general case
 
4420
        int dstreg = dstp.select_register(REG_ECX, shiftp, maskp);
 
4421
 
 
4422
        // 32-bit form
 
4423
        if (inst.size() == 4)
 
4424
        {
 
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())
4829
4429
                {
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
4832
4432
                }
4833
4433
                else
4834
4434
                {
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
4839
4439
                }
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
4842
4442
        }
4843
4443
 
4844
 
        /* 64-bit form */
4845
 
        else if (inst->size == 8)
 
4444
        // 64-bit form
 
4445
        else if (inst.size() == 8)
4846
4446
        {
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())
4850
4450
                {
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())
4854
4454
                        {
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
4859
4459
                        }
4860
4460
                        else
4861
4461
                        {
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
4866
4466
                        }
4867
4467
                }
4868
4468
                else
4869
4469
                {
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())
4878
4478
                        {
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
4883
4483
                        }
4884
4484
                        else
4885
4485
                        {
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
4890
4490
                        }
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]
4892
4492
                }
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))
4898
 
                {
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
4903
 
                }
4904
 
        }
4905
 
        return dst;
4906
 
}
4907
 
 
4908
 
 
4909
 
/*-------------------------------------------------
4910
 
    op_add - process a ADD opcode
4911
 
-------------------------------------------------*/
4912
 
 
4913
 
static x86code *op_add(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4914
 
{
4915
 
        drcuml_parameter dstp, src1p, src2p;
4916
 
        int dstreg;
4917
 
 
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);
4922
 
 
4923
 
        /* normalize parameters */
4924
 
        param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
4925
 
 
4926
 
        /* pick a target register for the general case */
4927
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
4928
 
 
4929
 
        /* 32-bit form */
4930
 
        if (inst->size == 4)
4931
 
        {
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
4935
 
 
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]
4939
 
 
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]
4943
 
 
4944
 
                /* general case */
4945
 
                else
4946
 
                {
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
4950
 
                }
4951
 
        }
4952
 
 
4953
 
        /* 64-bit form */
4954
 
        else if (inst->size == 8)
4955
 
        {
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
4959
 
 
4960
 
                /* general case */
4961
 
                else
4962
 
                {
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
4966
 
                }
4967
 
        }
4968
 
        return dst;
4969
 
}
4970
 
 
4971
 
 
4972
 
/*-------------------------------------------------
4973
 
    op_addc - process a ADDC opcode
4974
 
-------------------------------------------------*/
4975
 
 
4976
 
static x86code *op_addc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
4977
 
{
4978
 
        drcuml_parameter dstp, src1p, src2p;
4979
 
        int dstreg;
4980
 
 
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);
4985
 
 
4986
 
        /* normalize parameters */
4987
 
        param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
4988
 
 
4989
 
        /* pick a target register for the general case */
4990
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
4991
 
 
4992
 
        /* 32-bit form */
4993
 
        if (inst->size == 4)
4994
 
        {
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
4998
 
 
4999
 
                /* general case */
5000
 
                else
5001
 
                {
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
5005
 
                }
5006
 
        }
5007
 
 
5008
 
        /* 64-bit form */
5009
 
        else if (inst->size == 8)
5010
 
        {
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
5014
 
 
5015
 
                /* general case */
5016
 
                else
5017
 
                {
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
5021
 
                }
5022
 
        }
5023
 
        return dst;
5024
 
}
5025
 
 
5026
 
 
5027
 
/*-------------------------------------------------
5028
 
    op_sub - process a SUB opcode
5029
 
-------------------------------------------------*/
5030
 
 
5031
 
static x86code *op_sub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5032
 
{
5033
 
        drcuml_parameter dstp, src1p, src2p;
5034
 
        int dstreg;
5035
 
 
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);
5040
 
 
5041
 
        /* normalize parameters */
5042
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5043
 
 
5044
 
        /* pick a target register for the general case */
5045
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5046
 
 
5047
 
        /* 32-bit form */
5048
 
        if (inst->size == 4)
5049
 
        {
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
5053
 
 
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]
5057
 
 
5058
 
                /* general case */
5059
 
                else
5060
 
                {
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
5064
 
                }
5065
 
        }
5066
 
 
5067
 
        /* 64-bit form */
5068
 
        else if (inst->size == 8)
5069
 
        {
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
5073
 
 
5074
 
                /* general case */
5075
 
                else
5076
 
                {
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
5080
 
                }
5081
 
        }
5082
 
        return dst;
5083
 
}
5084
 
 
5085
 
 
5086
 
/*-------------------------------------------------
5087
 
    op_subc - process a SUBC opcode
5088
 
-------------------------------------------------*/
5089
 
 
5090
 
static x86code *op_subc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5091
 
{
5092
 
        drcuml_parameter dstp, src1p, src2p;
5093
 
        int dstreg;
5094
 
 
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);
5099
 
 
5100
 
        /* normalize parameters */
5101
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5102
 
 
5103
 
        /* pick a target register for the general case */
5104
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5105
 
 
5106
 
        /* 32-bit form */
5107
 
        if (inst->size == 4)
5108
 
        {
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
5112
 
 
5113
 
                /* general case */
5114
 
                else
5115
 
                {
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
5119
 
                }
5120
 
        }
5121
 
 
5122
 
        /* 64-bit form */
5123
 
        else if (inst->size == 8)
5124
 
        {
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
5128
 
 
5129
 
                /* general case */
5130
 
                else
5131
 
                {
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
5135
 
                }
5136
 
        }
5137
 
        return dst;
5138
 
}
5139
 
 
5140
 
 
5141
 
/*-------------------------------------------------
5142
 
    op_cmp - process a CMP opcode
5143
 
-------------------------------------------------*/
5144
 
 
5145
 
static x86code *op_cmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5146
 
{
5147
 
        drcuml_parameter src1p, src2p;
5148
 
        int src1reg;
5149
 
 
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);
5154
 
 
5155
 
        /* normalize parameters */
5156
 
        param_normalize_2(drcbe, inst, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5157
 
 
5158
 
        /* pick a target register for the general case */
5159
 
        src1reg = param_select_register(REG_EAX, &src1p, NULL);
5160
 
 
5161
 
        /* 32-bit form */
5162
 
        if (inst->size == 4)
5163
 
        {
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
5167
 
 
5168
 
                /* general case */
5169
 
                else
5170
 
                {
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
5174
 
                }
5175
 
        }
5176
 
 
5177
 
        /* 64-bit form */
 
4497
                else if (inst.flags() == (FLAG_Z | FLAG_S))
 
4498
                {
 
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
 
4503
                }
 
4504
        }
 
4505
}
 
4506
 
 
4507
 
 
4508
//-------------------------------------------------
 
4509
//  op_add - process a ADD opcode
 
4510
//-------------------------------------------------
 
4511
 
 
4512
void drcbe_x86::op_add(x86code *&dst, const instruction &inst)
 
4513
{
 
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);
 
4518
 
 
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);
 
4524
 
 
4525
        // pick a target register for the general case
 
4526
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
4527
 
 
4528
        // 32-bit form
 
4529
        if (inst.size() == 4)
 
4530
        {
 
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
 
4534
 
 
4535
                // reg = reg + imm
 
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]
 
4538
 
 
4539
                // reg = reg + reg
 
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]
 
4542
 
 
4543
                // general case
 
4544
                else
 
4545
                {
 
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
 
4549
                }
 
4550
        }
 
4551
 
 
4552
        // 64-bit form
 
4553
        else if (inst.size() == 8)
 
4554
        {
 
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
 
4558
 
 
4559
                // general case
 
4560
                else
 
4561
                {
 
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
 
4565
                }
 
4566
        }
 
4567
}
 
4568
 
 
4569
 
 
4570
//-------------------------------------------------
 
4571
//  op_addc - process a ADDC opcode
 
4572
//-------------------------------------------------
 
4573
 
 
4574
void drcbe_x86::op_addc(x86code *&dst, const instruction &inst)
 
4575
{
 
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);
 
4580
 
 
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);
 
4586
 
 
4587
        // pick a target register for the general case
 
4588
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
4589
 
 
4590
        // 32-bit form
 
4591
        if (inst.size() == 4)
 
4592
        {
 
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
 
4596
 
 
4597
                // general case
 
4598
                else
 
4599
                {
 
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
 
4603
                }
 
4604
        }
 
4605
 
 
4606
        // 64-bit form
 
4607
        else if (inst.size() == 8)
 
4608
        {
 
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
 
4612
 
 
4613
                // general case
 
4614
                else
 
4615
                {
 
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
 
4619
                }
 
4620
        }
 
4621
}
 
4622
 
 
4623
 
 
4624
//-------------------------------------------------
 
4625
//  op_sub - process a SUB opcode
 
4626
//-------------------------------------------------
 
4627
 
 
4628
void drcbe_x86::op_sub(x86code *&dst, const instruction &inst)
 
4629
{
 
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);
 
4634
 
 
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);
 
4639
 
 
4640
        // pick a target register for the general case
 
4641
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
4642
 
 
4643
        // 32-bit form
 
4644
        if (inst.size() == 4)
 
4645
        {
 
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
 
4649
 
 
4650
                // reg = reg - imm
 
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]
 
4653
 
 
4654
                // general case
 
4655
                else
 
4656
                {
 
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
 
4660
                }
 
4661
        }
 
4662
 
 
4663
        // 64-bit form
 
4664
        else if (inst.size() == 8)
 
4665
        {
 
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
 
4669
 
 
4670
                // general case
 
4671
                else
 
4672
                {
 
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
 
4676
                }
 
4677
        }
 
4678
}
 
4679
 
 
4680
 
 
4681
//-------------------------------------------------
 
4682
//  op_subc - process a SUBC opcode
 
4683
//-------------------------------------------------
 
4684
 
 
4685
void drcbe_x86::op_subc(x86code *&dst, const instruction &inst)
 
4686
{
 
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);
 
4691
 
 
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);
 
4696
 
 
4697
        // pick a target register for the general case
 
4698
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
4699
 
 
4700
        // 32-bit form
 
4701
        if (inst.size() == 4)
 
4702
        {
 
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
 
4706
 
 
4707
                // general case
 
4708
                else
 
4709
                {
 
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
 
4713
                }
 
4714
        }
 
4715
 
 
4716
        // 64-bit form
 
4717
        else if (inst.size() == 8)
 
4718
        {
 
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
 
4722
 
 
4723
                // general case
 
4724
                else
 
4725
                {
 
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
 
4729
                }
 
4730
        }
 
4731
}
 
4732
 
 
4733
 
 
4734
//-------------------------------------------------
 
4735
//  op_cmp - process a CMP opcode
 
4736
//-------------------------------------------------
 
4737
 
 
4738
void drcbe_x86::op_cmp(x86code *&dst, const instruction &inst)
 
4739
{
 
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);
 
4744
 
 
4745
        // normalize parameters
 
4746
        be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
 
4747
        be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
 
4748
 
 
4749
        // pick a target register for the general case
 
4750
        int src1reg = src1p.select_register(REG_EAX);
 
4751
 
 
4752
        // 32-bit form
 
4753
        if (inst.size() == 4)
 
4754
        {
 
4755
                // memory versus anything
 
4756
                if (src1p.is_memory())
 
4757
                        emit_cmp_m32_p32(dst, MABS(src1p.memory()), src2p, inst);                               // cmp   [dstp],src2p
 
4758
 
 
4759
                // general case
 
4760
                else
 
4761
                {
 
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
 
4765
                }
 
4766
        }
 
4767
 
 
4768
        // 64-bit form
5178
4769
        else
5179
4770
        {
5180
 
                /* general case */
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
 
4771
                // general case
 
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
5183
4774
        }
5184
 
        return dst;
5185
4775
}
5186
4776
 
5187
4777
 
5188
 
/*-------------------------------------------------
5189
 
    op_mulu - process a MULU opcode
5190
 
-------------------------------------------------*/
 
4778
//-------------------------------------------------
 
4779
//  op_mulu - process a MULU opcode
 
4780
//-------------------------------------------------
5191
4781
 
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)
5193
4783
{
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;
5197
 
        int compute_hi;
 
4784
        UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
 
4785
        UINT8 vflag = inst.flags() & FLAG_V;
5198
4786
 
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);
5203
 
 
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);
5207
 
 
5208
 
        /* 32-bit form */
5209
 
        if (inst->size == 4)
 
4790
        assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
 
4791
 
 
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);
 
4799
 
 
4800
        // 32-bit form
 
4801
        if (inst.size() == 4)
5210
4802
        {
5211
 
                /* general case */
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)
 
4803
                // general case
 
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())
5218
4810
                {
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
5221
4813
                }
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
5225
4817
 
5226
 
                /* compute flags */
5227
 
                if (inst->flags != 0)
 
4818
                // compute flags
 
4819
                if (inst.flags() != 0)
5228
4820
                {
5229
4821
                        if (zsflags != 0)
5230
4822
                        {
5231
4823
                                if (vflag)
5232
 
                                        emit_pushf(&dst);                                                                                                       // pushf
 
4824
                                        emit_pushf(dst);                                                                                                        // pushf
5233
4825
                                if (compute_hi)
5234
4826
                                {
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
5239
4831
                                        else
5240
4832
                                        {
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
5245
4837
                                        }
5246
4838
                                }
5247
4839
                                else
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
5249
4841
 
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
5251
4843
                                if (vflag)
5252
4844
                                {
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
5258
4850
                                }
5259
4851
                        }
5260
4852
                }
5261
4853
        }
5262
4854
 
5263
 
        /* 64-bit form */
5264
 
        else if (inst->size == 8)
 
4855
        // 64-bit form
 
4856
        else if (inst.size() == 8)
5265
4857
        {
5266
 
                /* general case */
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
 
4858
                // general case
 
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
5272
4864
                else
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)
5282
4874
                {
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
5286
4878
                }
5287
 
                if (inst->flags != 0)
5288
 
                        emit_popf(&dst);                                                                                                                        // popf
 
4879
                if (inst.flags() != 0)
 
4880
                        emit_popf(dst);                                                                                                                 // popf
5289
4881
        }
5290
 
        return dst;
5291
4882
}
5292
4883
 
5293
4884
 
5294
 
/*-------------------------------------------------
5295
 
    op_muls - process a MULS opcode
5296
 
-------------------------------------------------*/
 
4885
//-------------------------------------------------
 
4886
//  op_muls - process a MULS opcode
 
4887
//-------------------------------------------------
5297
4888
 
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)
5299
4890
{
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;
5303
 
        int compute_hi;
 
4891
        UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
 
4892
        UINT8 vflag =  inst.flags() & FLAG_V;
5304
4893
 
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);
5309
 
 
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);
5313
 
 
5314
 
        /* 32-bit form */
5315
 
        if (inst->size == 4)
 
4897
        assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
 
4898
 
 
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);
 
4906
 
 
4907
        // 32-bit form
 
4908
        if (inst.size() == 4)
5316
4909
        {
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())
5319
4912
                {
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
5325
4918
                }
5326
4919
 
5327
 
                /* 32-bit destination, general case */
 
4920
                // 32-bit destination, general case
5328
4921
                else if (!compute_hi)
5329
4922
                {
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
5336
4929
                }
5337
4930
 
5338
 
                /* 64-bit destination, general case */
 
4931
                // 64-bit destination, general case
5339
4932
                else
5340
4933
                {
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())
5347
4940
                        {
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
5350
4943
                        }
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
5353
4946
                }
5354
4947
 
5355
 
                /* compute flags */
5356
 
                if (inst->flags != 0)
 
4948
                // compute flags
 
4949
                if (inst.flags() != 0)
5357
4950
                {
5358
4951
                        if (zsflags != 0)
5359
4952
                        {
5360
4953
                                if (vflag)
5361
 
                                        emit_pushf(&dst);                                                                                                       // pushf
 
4954
                                        emit_pushf(dst);                                                                                                        // pushf
5362
4955
                                if (compute_hi)
5363
4956
                                {
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
5368
4961
                                        else
5369
4962
                                        {
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
5374
4967
                                        }
5375
4968
                                }
5376
4969
                                else
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
5378
4971
 
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
5380
4973
                                if (vflag)
5381
4974
                                {
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
5387
4980
                                }
5388
4981
                        }
5389
4982
                }
5390
4983
        }
5391
4984
 
5392
 
        /* 64-bit form */
5393
 
        else if (inst->size == 8)
 
4985
        // 64-bit form
 
4986
        else if (inst.size() == 8)
5394
4987
        {
5395
 
                /* general case */
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
 
4988
                // general case
 
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
5401
4994
                else
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)
5411
5004
                {
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
5415
 
                }
5416
 
                if (inst->flags != 0)
5417
 
                        emit_popf(&dst);                                                                                                                        // popf
5418
 
        }
5419
 
        return dst;
5420
 
}
5421
 
 
5422
 
 
5423
 
/*-------------------------------------------------
5424
 
    op_divu - process a DIVU opcode
5425
 
-------------------------------------------------*/
5426
 
 
5427
 
static x86code *op_divu(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5428
 
{
5429
 
        drcuml_parameter dstp, edstp, src1p, src2p;
5430
 
        int compute_rem;
5431
 
        emit_link skip;
5432
 
 
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);
5437
 
 
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);
5441
 
 
5442
 
        /* 32-bit form */
5443
 
        if (inst->size == 4)
5444
 
        {
5445
 
                /* general case */
5446
 
                emit_mov_r32_p32(drcbe, &dst, REG_ECX, &src2p);                                                                 // mov   ecx,src2p
5447
 
                if (inst->flags != 0)
5448
 
                {
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
5451
 
                }
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
5457
 
                if (compute_rem)
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:
5462
 
        }
5463
 
 
5464
 
        /* 64-bit form */
5465
 
        else if (inst->size == 8)
5466
 
        {
5467
 
                /* general case */
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
5470
 
                if (!compute_rem)
5471
 
                        emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo);                           // mov   [esp+4],&reslo
5472
 
                else
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
5481
 
                if (compute_rem)
5482
 
                {
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
5486
 
                }
5487
 
                if (inst->flags != 0)
5488
 
                        emit_popf(&dst);                                                                                                                        // popf
5489
 
        }
5490
 
        return dst;
5491
 
}
5492
 
 
5493
 
 
5494
 
/*-------------------------------------------------
5495
 
    op_divs - process a DIVS opcode
5496
 
-------------------------------------------------*/
5497
 
 
5498
 
static x86code *op_divs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5499
 
{
5500
 
        drcuml_parameter dstp, edstp, src1p, src2p;
5501
 
        int compute_rem;
5502
 
        emit_link skip;
5503
 
 
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);
5508
 
 
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);
5512
 
 
5513
 
        /* 32-bit form */
5514
 
        if (inst->size == 4)
5515
 
        {
5516
 
                /* general case */
5517
 
                emit_mov_r32_p32(drcbe, &dst, REG_ECX, &src2p);                                                                 // mov   ecx,src2p
5518
 
                if (inst->flags != 0)
5519
 
                {
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
5522
 
                }
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
5528
 
                if (compute_rem)
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:
5533
 
        }
5534
 
 
5535
 
        /* 64-bit form */
5536
 
        else if (inst->size == 8)
5537
 
        {
5538
 
                /* general case */
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
5541
 
                if (!compute_rem)
5542
 
                        emit_mov_m32_imm(&dst, MBD(REG_ESP, 4), (FPTR)&drcbe->reslo);                           // mov   [esp+4],&reslo
5543
 
                else
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
5552
 
                if (compute_rem)
5553
 
                {
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
5557
 
                }
5558
 
                if (inst->flags != 0)
5559
 
                        emit_popf(&dst);                                                                                                                        // popf
5560
 
        }
5561
 
        return dst;
5562
 
}
5563
 
 
5564
 
 
5565
 
/*-------------------------------------------------
5566
 
    op_and - process a AND opcode
5567
 
-------------------------------------------------*/
5568
 
 
5569
 
static x86code *op_and(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5570
 
{
5571
 
        drcuml_parameter dstp, src1p, src2p;
5572
 
        int dstreg;
5573
 
 
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);
5578
 
 
5579
 
        /* normalize parameters */
5580
 
        param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5581
 
 
5582
 
        /* pick a target register for the general case */
5583
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5584
 
 
5585
 
        /* 32-bit form */
5586
 
        if (inst->size == 4)
5587
 
        {
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
5591
 
 
5592
 
                /* AND with immediate 0xff */
5593
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
5594
 
                {
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
5600
 
                }
5601
 
 
5602
 
                /* AND with immediate 0xffff */
5603
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
5604
 
                {
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
5610
 
                }
5611
 
 
5612
 
                /* general case */
5613
 
                else
5614
 
                {
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
5618
 
                }
5619
 
        }
5620
 
 
5621
 
        /* 64-bit form */
5622
 
        else if (inst->size == 8)
5623
 
        {
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
5627
 
 
5628
 
                /* AND with immediate 0xff */
5629
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xff && inst->flags == 0)
5630
 
                {
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
5640
 
                }
5641
 
 
5642
 
                /* AND with immediate 0xffff */
5643
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffff && inst->flags == 0)
5644
 
                {
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
5654
 
                }
5655
 
 
5656
 
                /* AND with immediate 0xffffffff */
5657
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == 0xffffffff && inst->flags == 0)
5658
 
                {
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
5665
 
                }
5666
 
 
5667
 
                /* AND with immediate 0xffffffff00000000 */
5668
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value == U64(0xffffffff00000000) && inst->flags == 0)
5669
 
                {
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
 
5008
                }
 
5009
                if (inst.flags() != 0)
 
5010
                        emit_popf(dst);                                                                                                                 // popf
 
5011
        }
 
5012
}
 
5013
 
 
5014
 
 
5015
//-------------------------------------------------
 
5016
//  op_divu - process a DIVU opcode
 
5017
//-------------------------------------------------
 
5018
 
 
5019
void drcbe_x86::op_divu(x86code *&dst, const instruction &inst)
 
5020
{
 
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);
 
5025
 
 
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);
 
5032
 
 
5033
        // 32-bit form
 
5034
        if (inst.size() == 4)
 
5035
        {
 
5036
                // general case
 
5037
                emit_mov_r32_p32(dst, REG_ECX, src2p);                                                                  // mov   ecx,src2p
 
5038
                if (inst.flags() != 0)
 
5039
                {
 
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
 
5042
                }
 
5043
                emit_link skip;
 
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
 
5049
                if (compute_rem)
 
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:
 
5054
        }
 
5055
 
 
5056
        // 64-bit form
 
5057
        else if (inst.size() == 8)
 
5058
        {
 
5059
                // general case
 
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
 
5062
                if (!compute_rem)
 
5063
                        emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo);                         // mov   [esp+4],&reslo
 
5064
                else
 
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
 
5073
                if (compute_rem)
 
5074
                {
 
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
 
5078
                }
 
5079
                if (inst.flags() != 0)
 
5080
                        emit_popf(dst);                                                                                                                 // popf
 
5081
        }
 
5082
}
 
5083
 
 
5084
 
 
5085
//-------------------------------------------------
 
5086
//  op_divs - process a DIVS opcode
 
5087
//-------------------------------------------------
 
5088
 
 
5089
void drcbe_x86::op_divs(x86code *&dst, const instruction &inst)
 
5090
{
 
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);
 
5095
 
 
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);
 
5102
 
 
5103
        // 32-bit form
 
5104
        if (inst.size() == 4)
 
5105
        {
 
5106
                // general case
 
5107
                emit_mov_r32_p32(dst, REG_ECX, src2p);                                                                  // mov   ecx,src2p
 
5108
                if (inst.flags() != 0)
 
5109
                {
 
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
 
5112
                }
 
5113
                emit_link skip;
 
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
 
5119
                if (compute_rem)
 
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:
 
5124
        }
 
5125
 
 
5126
        // 64-bit form
 
5127
        else if (inst.size() == 8)
 
5128
        {
 
5129
                // general case
 
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
 
5132
                if (!compute_rem)
 
5133
                        emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo);                         // mov   [esp+4],&reslo
 
5134
                else
 
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
 
5143
                if (compute_rem)
 
5144
                {
 
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
 
5148
                }
 
5149
                if (inst.flags() != 0)
 
5150
                        emit_popf(dst);                                                                                                                 // popf
 
5151
        }
 
5152
}
 
5153
 
 
5154
 
 
5155
//-------------------------------------------------
 
5156
//  op_and - process a AND opcode
 
5157
//-------------------------------------------------
 
5158
 
 
5159
void drcbe_x86::op_and(x86code *&dst, const instruction &inst)
 
5160
{
 
5161
        // validate instruction
 
5162
        assert(inst.size() == 4 || inst.size() == 8);
 
5163
        assert_no_condition(inst);
 
5164
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5165
 
 
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);
 
5171
 
 
5172
        // pick a target register for the general case
 
5173
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5174
 
 
5175
        // 32-bit form
 
5176
        if (inst.size() == 4)
 
5177
        {
 
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
 
5181
 
 
5182
                // AND with immediate 0xff
 
5183
                else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
 
5184
                {
 
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
 
5190
                }
 
5191
 
 
5192
                // AND with immediate 0xffff
 
5193
                else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
 
5194
                {
 
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
 
5200
                }
 
5201
 
 
5202
                // general case
 
5203
                else
 
5204
                {
 
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
 
5208
                }
 
5209
        }
 
5210
 
 
5211
        // 64-bit form
 
5212
        else if (inst.size() == 8)
 
5213
        {
 
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
 
5217
 
 
5218
                // AND with immediate 0xff
 
5219
                else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
 
5220
                {
 
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
 
5230
                }
 
5231
 
 
5232
                // AND with immediate 0xffff
 
5233
                else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
 
5234
                {
 
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
 
5244
                }
 
5245
 
 
5246
                // AND with immediate 0xffffffff
 
5247
                else if (src2p.is_immediate_value(0xffffffff) && inst.flags() == 0)
 
5248
                {
 
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
 
5255
                }
 
5256
 
 
5257
                // AND with immediate 0xffffffff00000000
 
5258
                else if (src2p.is_immediate_value(U64(0xffffffff00000000)) && inst.flags() == 0)
 
5259
                {
 
5260
                        if (src1p != dstp)
5671
5261
                        {
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
5674
5264
                        }
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
5679
 
                }
5680
 
 
5681
 
                /* AND with immediate <= 0xffffffff */
5682
 
                else if (src2p.type == DRCUML_PTYPE_IMMEDIATE && src2p.value <= 0xffffffff && inst->flags == 0)
5683
 
                {
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
5691
 
                }
5692
 
 
5693
 
                /* general case */
5694
 
                else
5695
 
                {
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
5699
 
                }
5700
 
        }
5701
 
        return dst;
5702
 
}
5703
 
 
5704
 
 
5705
 
/*-------------------------------------------------
5706
 
    op_test - process a TEST opcode
5707
 
-------------------------------------------------*/
5708
 
 
5709
 
static x86code *op_test(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5710
 
{
5711
 
        drcuml_parameter src1p, src2p;
5712
 
        int src1reg;
5713
 
 
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);
5718
 
 
5719
 
        /* normalize parameters */
5720
 
        param_normalize_2_commutative(drcbe, inst, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5721
 
 
5722
 
        /* pick a target register for the general case */
5723
 
        src1reg = param_select_register(REG_EAX, &src1p, NULL);
5724
 
 
5725
 
        /* 32-bit form */
5726
 
        if (inst->size == 4)
5727
 
        {
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
5731
 
 
5732
 
                /* general case */
5733
 
                else
5734
 
                {
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
5737
 
                }
5738
 
        }
5739
 
 
5740
 
        /* 64-bit form */
5741
 
        else if (inst->size == 8)
5742
 
        {
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
5746
 
 
5747
 
                /* general case */
5748
 
                else
5749
 
                {
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
5752
 
                }
5753
 
        }
5754
 
        return dst;
5755
 
}
5756
 
 
5757
 
 
5758
 
/*-------------------------------------------------
5759
 
    op_or - process a OR opcode
5760
 
-------------------------------------------------*/
5761
 
 
5762
 
static x86code *op_or(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5763
 
{
5764
 
        drcuml_parameter dstp, src1p, src2p;
5765
 
        int dstreg;
5766
 
 
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);
5771
 
 
5772
 
        /* normalize parameters */
5773
 
        param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5774
 
 
5775
 
        /* pick a target register for the general case */
5776
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5777
 
 
5778
 
        /* 32-bit form */
5779
 
        if (inst->size == 4)
5780
 
        {
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
5784
 
 
5785
 
                /* general case */
5786
 
                else
5787
 
                {
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
5791
 
                }
5792
 
        }
5793
 
 
5794
 
        /* 64-bit form */
5795
 
        else if (inst->size == 8)
5796
 
        {
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
5800
 
 
5801
 
                /* general case */
5802
 
                else
5803
 
                {
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
5807
 
                }
5808
 
        }
5809
 
        return dst;
5810
 
}
5811
 
 
5812
 
 
5813
 
/*-------------------------------------------------
5814
 
    op_xor - process a XOR opcode
5815
 
-------------------------------------------------*/
5816
 
 
5817
 
static x86code *op_xor(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5818
 
{
5819
 
        drcuml_parameter dstp, src1p, src2p;
5820
 
        int dstreg;
5821
 
 
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);
5826
 
 
5827
 
        /* normalize parameters */
5828
 
        param_normalize_3_commutative(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5829
 
 
5830
 
        /* pick a target register for the general case */
5831
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5832
 
 
5833
 
        /* 32-bit form */
5834
 
        if (inst->size == 4)
5835
 
        {
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
5839
 
 
5840
 
                /* general case */
5841
 
                else
5842
 
                {
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
5846
 
                }
5847
 
        }
5848
 
 
5849
 
        /* 64-bit form */
5850
 
        else if (inst->size == 8)
5851
 
        {
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
5855
 
 
5856
 
                /* general case */
5857
 
                else
5858
 
                {
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
5862
 
                }
5863
 
        }
5864
 
        return dst;
5865
 
}
5866
 
 
5867
 
 
5868
 
/*-------------------------------------------------
5869
 
    op_lzcnt - process a LZCNT opcode
5870
 
-------------------------------------------------*/
5871
 
 
5872
 
static x86code *op_lzcnt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5873
 
{
5874
 
        drcuml_parameter dstp, srcp;
5875
 
        int dstreg;
5876
 
 
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);
5881
 
 
5882
 
        /* normalize parameters */
5883
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
5884
 
 
5885
 
        /* pick a target register for the general case */
5886
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
5887
 
 
5888
 
        /* 32-bit form */
5889
 
        if (inst->size == 4)
5890
 
        {
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
5897
 
        }
5898
 
 
5899
 
        /* 64-bit form */
5900
 
        else if (inst->size == 8)
5901
 
        {
 
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
 
5269
                }
 
5270
 
 
5271
                // AND with immediate <= 0xffffffff
 
5272
                else if (src2p.is_immediate() && src2p.immediate() <= 0xffffffff && inst.flags() == 0)
 
5273
                {
 
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
 
5281
                }
 
5282
 
 
5283
                // general case
 
5284
                else
 
5285
                {
 
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
 
5289
                }
 
5290
        }
 
5291
}
 
5292
 
 
5293
 
 
5294
//-------------------------------------------------
 
5295
//  op_test - process a TEST opcode
 
5296
//-------------------------------------------------
 
5297
 
 
5298
void drcbe_x86::op_test(x86code *&dst, const instruction &inst)
 
5299
{
 
5300
        // validate instruction
 
5301
        assert(inst.size() == 4 || inst.size() == 8);
 
5302
        assert_no_condition(inst);
 
5303
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5304
 
 
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);
 
5309
 
 
5310
        // pick a target register for the general case
 
5311
        int src1reg = src1p.select_register(REG_EAX);
 
5312
 
 
5313
        // 32-bit form
 
5314
        if (inst.size() == 4)
 
5315
        {
 
5316
                // src1p in memory
 
5317
                if (src1p.is_memory())
 
5318
                        emit_test_m32_p32(dst, MABS(src1p.memory()), src2p, inst);                      // test  [src1p],src2p
 
5319
 
 
5320
                // general case
 
5321
                else
 
5322
                {
 
5323
                        emit_mov_r32_p32(dst, src1reg, src1p);                                                          // mov   src1reg,src1p
 
5324
                        emit_test_r32_p32(dst, src1reg, src2p, inst);                                           // test  src1reg,src2p
 
5325
                }
 
5326
        }
 
5327
 
 
5328
        // 64-bit form
 
5329
        else if (inst.size() == 8)
 
5330
        {
 
5331
                // src1p in memory
 
5332
                if (src1p.is_memory())
 
5333
                        emit_test_m64_p64(dst, MABS(src1p.memory()), src2p, inst);                      // test  [dstp],src2p
 
5334
 
 
5335
                // general case
 
5336
                else
 
5337
                {
 
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
 
5340
                }
 
5341
        }
 
5342
}
 
5343
 
 
5344
 
 
5345
//-------------------------------------------------
 
5346
//  op_or - process a OR opcode
 
5347
//-------------------------------------------------
 
5348
 
 
5349
void drcbe_x86::op_or(x86code *&dst, const instruction &inst)
 
5350
{
 
5351
        // validate instruction
 
5352
        assert(inst.size() == 4 || inst.size() == 8);
 
5353
        assert_no_condition(inst);
 
5354
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5355
 
 
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);
 
5361
 
 
5362
        // pick a target register for the general case
 
5363
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5364
 
 
5365
        // 32-bit form
 
5366
        if (inst.size() == 4)
 
5367
        {
 
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
 
5371
 
 
5372
                // general case
 
5373
                else
 
5374
                {
 
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
 
5378
                }
 
5379
        }
 
5380
 
 
5381
        // 64-bit form
 
5382
        else if (inst.size() == 8)
 
5383
        {
 
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
 
5387
 
 
5388
                // general case
 
5389
                else
 
5390
                {
 
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
 
5394
                }
 
5395
        }
 
5396
}
 
5397
 
 
5398
 
 
5399
//-------------------------------------------------
 
5400
//  op_xor - process a XOR opcode
 
5401
//-------------------------------------------------
 
5402
 
 
5403
void drcbe_x86::op_xor(x86code *&dst, const instruction &inst)
 
5404
{
 
5405
        // validate instruction
 
5406
        assert(inst.size() == 4 || inst.size() == 8);
 
5407
        assert_no_condition(inst);
 
5408
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5409
 
 
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);
 
5415
 
 
5416
        // pick a target register for the general case
 
5417
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5418
 
 
5419
        // 32-bit form
 
5420
        if (inst.size() == 4)
 
5421
        {
 
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
 
5425
 
 
5426
                // general case
 
5427
                else
 
5428
                {
 
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
 
5432
                }
 
5433
        }
 
5434
 
 
5435
        // 64-bit form
 
5436
        else if (inst.size() == 8)
 
5437
        {
 
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
 
5441
 
 
5442
                // general case
 
5443
                else
 
5444
                {
 
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
 
5448
                }
 
5449
        }
 
5450
}
 
5451
 
 
5452
 
 
5453
//-------------------------------------------------
 
5454
//  op_lzcnt - process a LZCNT opcode
 
5455
//-------------------------------------------------
 
5456
 
 
5457
void drcbe_x86::op_lzcnt(x86code *&dst, const instruction &inst)
 
5458
{
 
5459
        // validate instruction
 
5460
        assert(inst.size() == 4 || inst.size() == 8);
 
5461
        assert_no_condition(inst);
 
5462
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5463
 
 
5464
        // normalize parameters
 
5465
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
5466
        be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
 
5467
 
 
5468
        // pick a target register for the general case
 
5469
        int dstreg = dstp.select_register(REG_EAX);
 
5470
 
 
5471
        // 32-bit form
 
5472
        if (inst.size() == 4)
 
5473
        {
 
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
 
5480
        }
 
5481
 
 
5482
        // 64-bit form
 
5483
        else if (inst.size() == 8)
 
5484
        {
 
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;
5903
 
 
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
5915
 
        }
5916
 
        return dst;
5917
 
}
5918
 
 
5919
 
 
5920
 
/*-------------------------------------------------
5921
 
    op_bswap - process a BSWAP opcode
5922
 
-------------------------------------------------*/
5923
 
 
5924
 
static x86code *op_bswap(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5925
 
{
5926
 
        drcuml_parameter dstp, srcp;
5927
 
        int dstreg;
5928
 
 
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);
5933
 
 
5934
 
        /* normalize parameters */
5935
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
5936
 
 
5937
 
        /* pick a target register for the general case */
5938
 
        dstreg = param_select_register(REG_EAX, &dstp, NULL);
5939
 
 
5940
 
        /* 32-bit form */
5941
 
        if (inst->size == 4)
5942
 
        {
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
5948
 
        }
5949
 
 
5950
 
        /* 64-bit form */
5951
 
        else if (inst->size == 8)
5952
 
        {
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
5961
 
                else
5962
 
                {
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
5968
 
                }
5969
 
        }
5970
 
        return dst;
5971
 
}
5972
 
 
5973
 
 
5974
 
/*-------------------------------------------------
5975
 
    op_shl - process a SHL opcode
5976
 
-------------------------------------------------*/
5977
 
 
5978
 
static x86code *op_shl(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
5979
 
{
5980
 
        drcuml_parameter dstp, src1p, src2p;
5981
 
        int dstreg;
5982
 
 
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);
5987
 
 
5988
 
        /* normalize parameters */
5989
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
5990
 
 
5991
 
        /* pick a target register for the general case */
5992
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
5993
 
 
5994
 
        /* 32-bit form */
5995
 
        if (inst->size == 4)
5996
 
        {
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
6000
 
 
6001
 
                /* general case */
6002
 
                else
6003
 
                {
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
6007
 
                }
6008
 
        }
6009
 
 
6010
 
        /* 64-bit form */
6011
 
        else if (inst->size == 8)
6012
 
        {
6013
 
                /* general case */
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
6017
 
        }
6018
 
        return dst;
6019
 
}
6020
 
 
6021
 
 
6022
 
/*-------------------------------------------------
6023
 
    op_shr - process a SHR opcode
6024
 
-------------------------------------------------*/
6025
 
 
6026
 
static x86code *op_shr(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6027
 
{
6028
 
        drcuml_parameter dstp, src1p, src2p;
6029
 
        int dstreg;
6030
 
 
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);
6035
 
 
6036
 
        /* normalize parameters */
6037
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6038
 
 
6039
 
        /* pick a target register for the general case */
6040
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6041
 
 
6042
 
        /* 32-bit form */
6043
 
        if (inst->size == 4)
6044
 
        {
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
6048
 
 
6049
 
                /* general case */
6050
 
                else
6051
 
                {
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
6055
 
                }
6056
 
        }
6057
 
 
6058
 
        /* 64-bit form */
6059
 
        else if (inst->size == 8)
6060
 
        {
6061
 
                /* general case */
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
6065
 
        }
6066
 
        return dst;
6067
 
}
6068
 
 
6069
 
 
6070
 
/*-------------------------------------------------
6071
 
    op_sar - process a SAR opcode
6072
 
-------------------------------------------------*/
6073
 
 
6074
 
static x86code *op_sar(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6075
 
{
6076
 
        drcuml_parameter dstp, src1p, src2p;
6077
 
        int dstreg;
6078
 
 
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);
6083
 
 
6084
 
        /* normalize parameters */
6085
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6086
 
 
6087
 
        /* pick a target register for the general case */
6088
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6089
 
 
6090
 
        /* 32-bit form */
6091
 
        if (inst->size == 4)
6092
 
        {
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
6096
 
 
6097
 
                /* general case */
6098
 
                else
6099
 
                {
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
6103
 
                }
6104
 
        }
6105
 
 
6106
 
        /* 64-bit form */
6107
 
        else if (inst->size == 8)
6108
 
        {
6109
 
                /* general case */
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
6113
 
        }
6114
 
        return dst;
6115
 
}
6116
 
 
6117
 
 
6118
 
/*-------------------------------------------------
6119
 
    op_rol - process a rol opcode
6120
 
-------------------------------------------------*/
6121
 
 
6122
 
static x86code *op_rol(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6123
 
{
6124
 
        drcuml_parameter dstp, src1p, src2p;
6125
 
        int dstreg;
6126
 
 
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);
6131
 
 
6132
 
        /* normalize parameters */
6133
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6134
 
 
6135
 
        /* pick a target register for the general case */
6136
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6137
 
 
6138
 
        /* 32-bit form */
6139
 
        if (inst->size == 4)
6140
 
        {
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
6144
 
 
6145
 
                /* general case */
6146
 
                else
6147
 
                {
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
6151
 
                }
6152
 
        }
6153
 
 
6154
 
        /* 64-bit form */
6155
 
        else if (inst->size == 8)
6156
 
        {
6157
 
                /* general case */
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
6161
 
        }
6162
 
        return dst;
6163
 
}
6164
 
 
6165
 
 
6166
 
/*-------------------------------------------------
6167
 
    op_ror - process a ROR opcode
6168
 
-------------------------------------------------*/
6169
 
 
6170
 
static x86code *op_ror(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6171
 
{
6172
 
        drcuml_parameter dstp, src1p, src2p;
6173
 
        int dstreg;
6174
 
 
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);
6179
 
 
6180
 
        /* normalize parameters */
6181
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6182
 
 
6183
 
        /* pick a target register for the general case */
6184
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6185
 
 
6186
 
        /* 32-bit form */
6187
 
        if (inst->size == 4)
6188
 
        {
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
6192
 
 
6193
 
                /* general case */
6194
 
                else
6195
 
                {
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
6199
 
                }
6200
 
        }
6201
 
 
6202
 
        /* 64-bit form */
6203
 
        else if (inst->size == 8)
6204
 
        {
6205
 
                /* general case */
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
6209
 
        }
6210
 
        return dst;
6211
 
}
6212
 
 
6213
 
 
6214
 
/*-------------------------------------------------
6215
 
    op_rolc - process a ROLC opcode
6216
 
-------------------------------------------------*/
6217
 
 
6218
 
static x86code *op_rolc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6219
 
{
6220
 
        drcuml_parameter dstp, src1p, src2p;
6221
 
        int dstreg;
6222
 
 
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);
6227
 
 
6228
 
        /* normalize parameters */
6229
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6230
 
 
6231
 
        /* pick a target register for the general case */
6232
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6233
 
 
6234
 
        /* 32-bit form */
6235
 
        if (inst->size == 4)
6236
 
        {
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
6240
 
 
6241
 
                /* general case */
6242
 
                else
6243
 
                {
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
6247
 
                }
6248
 
        }
6249
 
 
6250
 
        /* 64-bit form */
6251
 
        else if (inst->size == 8)
6252
 
        {
6253
 
                /* general case */
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
6257
 
        }
6258
 
        return dst;
6259
 
}
6260
 
 
6261
 
 
6262
 
/*-------------------------------------------------
6263
 
    op_rorc - process a RORC opcode
6264
 
-------------------------------------------------*/
6265
 
 
6266
 
static x86code *op_rorc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6267
 
{
6268
 
        drcuml_parameter dstp, src1p, src2p;
6269
 
        int dstreg;
6270
 
 
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);
6275
 
 
6276
 
        /* normalize parameters */
6277
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &src1p, PTYPE_MRI, &src2p, PTYPE_MRI);
6278
 
 
6279
 
        /* pick a target register for the general case */
6280
 
        dstreg = param_select_register(REG_EAX, &dstp, &src2p);
6281
 
 
6282
 
        /* 32-bit form */
6283
 
        if (inst->size == 4)
6284
 
        {
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
6288
 
 
6289
 
                /* general case */
6290
 
                else
6291
 
                {
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
6295
 
                }
6296
 
        }
6297
 
 
6298
 
        /* 64-bit form */
6299
 
        else if (inst->size == 8)
6300
 
        {
6301
 
                /* general case */
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
6305
 
        }
6306
 
        return dst;
6307
 
}
6308
 
 
6309
 
 
6310
 
 
6311
 
/***************************************************************************
6312
 
    FLOATING POINT OPERATIONS
6313
 
***************************************************************************/
6314
 
 
6315
 
/*-------------------------------------------------
6316
 
    op_fload - process a FLOAD opcode
6317
 
-------------------------------------------------*/
6318
 
 
6319
 
static x86code *op_fload(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6320
 
{
6321
 
        drcuml_parameter dstp, basep, indp;
6322
 
 
6323
 
        /* validate instruction */
6324
 
        assert(inst->size == 4 || inst->size == 8);
6325
 
        assert_no_condition(inst);
6326
 
        assert_no_flags(inst);
6327
 
 
6328
 
        /* normalize parameters */
6329
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &basep, PTYPE_M, &indp, PTYPE_MRI);
6330
 
 
6331
 
        /* immediate index */
6332
 
        if (indp.type == DRCUML_PTYPE_IMMEDIATE)
6333
 
        {
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]
6337
 
        }
6338
 
 
6339
 
        /* other index */
6340
 
        else
6341
 
        {
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]
6347
 
        }
6348
 
 
6349
 
        /* general case */
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
6353
 
        return dst;
6354
 
}
6355
 
 
6356
 
 
6357
 
/*-------------------------------------------------
6358
 
    op_fstore - process a FSTORE opcode
6359
 
-------------------------------------------------*/
6360
 
 
6361
 
static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6362
 
{
6363
 
        drcuml_parameter srcp, basep, indp;
6364
 
 
6365
 
        /* validate instruction */
6366
 
        assert(inst->size == 4 || inst->size == 8);
6367
 
        assert_no_condition(inst);
6368
 
        assert_no_flags(inst);
6369
 
 
6370
 
        /* normalize parameters */
6371
 
        param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MF);
6372
 
 
6373
 
        /* general case */
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]
6377
 
 
6378
 
        /* immediate index */
6379
 
        if (indp.type == DRCUML_PTYPE_IMMEDIATE)
6380
 
        {
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
6384
 
        }
6385
 
 
6386
 
        /* other index */
6387
 
        else
6388
 
        {
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
6394
 
        }
6395
 
        return dst;
6396
 
}
6397
 
 
6398
 
 
6399
 
/*-------------------------------------------------
6400
 
    op_fread - process a FREAD opcode
6401
 
-------------------------------------------------*/
6402
 
 
6403
 
static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6404
 
{
6405
 
        drcuml_parameter dstp, spacep, addrp;
6406
 
 
6407
 
        /* validate instruction */
6408
 
        assert(inst->size == 4 || inst->size == 8);
6409
 
        assert_no_condition(inst);
6410
 
        assert_no_flags(inst);
6411
 
 
6412
 
        /* normalize parameters */
6413
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &addrp, PTYPE_MRI, &spacep, PTYPE_I);
6414
 
 
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
6422
 
 
6423
 
        /* store result */
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
6428
 
 
6429
 
        return dst;
6430
 
}
6431
 
 
6432
 
 
6433
 
/*-------------------------------------------------
6434
 
    op_fwrite - process a FWRITE opcode
6435
 
-------------------------------------------------*/
6436
 
 
6437
 
static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6438
 
{
6439
 
        drcuml_parameter spacep, addrp, srcp;
6440
 
 
6441
 
        /* validate instruction */
6442
 
        assert(inst->size == 4 || inst->size == 8);
6443
 
        assert_no_condition(inst);
6444
 
        assert_no_flags(inst);
6445
 
 
6446
 
        /* normalize parameters */
6447
 
        param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MF, &spacep, PTYPE_I);
6448
 
 
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
6460
 
 
6461
 
        return dst;
6462
 
}
6463
 
 
6464
 
 
6465
 
/*-------------------------------------------------
6466
 
    op_fmov - process a FMOV opcode
6467
 
-------------------------------------------------*/
6468
 
 
6469
 
static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6470
 
{
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
 
5497
        }
 
5498
}
 
5499
 
 
5500
 
 
5501
//-------------------------------------------------
 
5502
//  op_bswap - process a BSWAP opcode
 
5503
//-------------------------------------------------
 
5504
 
 
5505
void drcbe_x86::op_bswap(x86code *&dst, const instruction &inst)
 
5506
{
 
5507
        // validate instruction
 
5508
        assert(inst.size() == 4 || inst.size() == 8);
 
5509
        assert_no_condition(inst);
 
5510
        assert_flags(inst, FLAG_Z | FLAG_S);
 
5511
 
 
5512
        // normalize parameters
 
5513
        be_parameter dstp(*this, inst.param(0), PTYPE_MR);
 
5514
        be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
 
5515
 
 
5516
        // pick a target register for the general case
 
5517
        int dstreg = dstp.select_register(REG_EAX);
 
5518
 
 
5519
        // 32-bit form
 
5520
        if (inst.size() == 4)
 
5521
        {
 
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
 
5527
        }
 
5528
 
 
5529
        // 64-bit form
 
5530
        else if (inst.size() == 8)
 
5531
        {
 
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
 
5540
                else
 
5541
                {
 
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
 
5547
                }
 
5548
        }
 
5549
}
 
5550
 
 
5551
 
 
5552
//-------------------------------------------------
 
5553
//  op_shl - process a SHL opcode
 
5554
//-------------------------------------------------
 
5555
 
 
5556
void drcbe_x86::op_shl(x86code *&dst, const instruction &inst)
 
5557
{
 
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);
 
5562
 
 
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);
 
5567
 
 
5568
        // pick a target register for the general case
 
5569
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5570
 
 
5571
        // 32-bit form
 
5572
        if (inst.size() == 4)
 
5573
        {
 
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
 
5577
 
 
5578
                // general case
 
5579
                else
 
5580
                {
 
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
 
5584
                }
 
5585
        }
 
5586
 
 
5587
        // 64-bit form
 
5588
        else if (inst.size() == 8)
 
5589
        {
 
5590
                // general case
 
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
 
5594
        }
 
5595
}
 
5596
 
 
5597
 
 
5598
//-------------------------------------------------
 
5599
//  op_shr - process a SHR opcode
 
5600
//-------------------------------------------------
 
5601
 
 
5602
void drcbe_x86::op_shr(x86code *&dst, const instruction &inst)
 
5603
{
 
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);
 
5608
 
 
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);
 
5613
 
 
5614
        // pick a target register for the general case
 
5615
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5616
 
 
5617
        // 32-bit form
 
5618
        if (inst.size() == 4)
 
5619
        {
 
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
 
5623
 
 
5624
                // general case
 
5625
                else
 
5626
                {
 
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
 
5630
                }
 
5631
        }
 
5632
 
 
5633
        // 64-bit form
 
5634
        else if (inst.size() == 8)
 
5635
        {
 
5636
                // general case
 
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
 
5640
        }
 
5641
}
 
5642
 
 
5643
 
 
5644
//-------------------------------------------------
 
5645
//  op_sar - process a SAR opcode
 
5646
//-------------------------------------------------
 
5647
 
 
5648
void drcbe_x86::op_sar(x86code *&dst, const instruction &inst)
 
5649
{
 
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);
 
5654
 
 
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);
 
5659
 
 
5660
        // pick a target register for the general case
 
5661
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5662
 
 
5663
        // 32-bit form
 
5664
        if (inst.size() == 4)
 
5665
        {
 
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
 
5669
 
 
5670
                // general case
 
5671
                else
 
5672
                {
 
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
 
5676
                }
 
5677
        }
 
5678
 
 
5679
        // 64-bit form
 
5680
        else if (inst.size() == 8)
 
5681
        {
 
5682
                // general case
 
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
 
5686
        }
 
5687
}
 
5688
 
 
5689
 
 
5690
//-------------------------------------------------
 
5691
//  op_rol - process a rol opcode
 
5692
//-------------------------------------------------
 
5693
 
 
5694
void drcbe_x86::op_rol(x86code *&dst, const instruction &inst)
 
5695
{
 
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);
 
5700
 
 
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);
 
5705
 
 
5706
        // pick a target register for the general case
 
5707
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5708
 
 
5709
        // 32-bit form
 
5710
        if (inst.size() == 4)
 
5711
        {
 
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
 
5715
 
 
5716
                // general case
 
5717
                else
 
5718
                {
 
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
 
5722
                }
 
5723
        }
 
5724
 
 
5725
        // 64-bit form
 
5726
        else if (inst.size() == 8)
 
5727
        {
 
5728
                // general case
 
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
 
5732
        }
 
5733
}
 
5734
 
 
5735
 
 
5736
//-------------------------------------------------
 
5737
//  op_ror - process a ROR opcode
 
5738
//-------------------------------------------------
 
5739
 
 
5740
void drcbe_x86::op_ror(x86code *&dst, const instruction &inst)
 
5741
{
 
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);
 
5746
 
 
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);
 
5751
 
 
5752
        // pick a target register for the general case
 
5753
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5754
 
 
5755
        // 32-bit form
 
5756
        if (inst.size() == 4)
 
5757
        {
 
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
 
5761
 
 
5762
                // general case
 
5763
                else
 
5764
                {
 
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
 
5768
                }
 
5769
        }
 
5770
 
 
5771
        // 64-bit form
 
5772
        else if (inst.size() == 8)
 
5773
        {
 
5774
                // general case
 
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
 
5778
        }
 
5779
}
 
5780
 
 
5781
 
 
5782
//-------------------------------------------------
 
5783
//  op_rolc - process a ROLC opcode
 
5784
//-------------------------------------------------
 
5785
 
 
5786
void drcbe_x86::op_rolc(x86code *&dst, const instruction &inst)
 
5787
{
 
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);
 
5792
 
 
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);
 
5797
 
 
5798
        // pick a target register for the general case
 
5799
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5800
 
 
5801
        // 32-bit form
 
5802
        if (inst.size() == 4)
 
5803
        {
 
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
 
5807
 
 
5808
                // general case
 
5809
                else
 
5810
                {
 
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
 
5814
                }
 
5815
        }
 
5816
 
 
5817
        // 64-bit form
 
5818
        else if (inst.size() == 8)
 
5819
        {
 
5820
                // general case
 
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
 
5824
        }
 
5825
}
 
5826
 
 
5827
 
 
5828
//-------------------------------------------------
 
5829
//  op_rorc - process a RORC opcode
 
5830
//-------------------------------------------------
 
5831
 
 
5832
void drcbe_x86::op_rorc(x86code *&dst, const instruction &inst)
 
5833
{
 
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);
 
5838
 
 
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);
 
5843
 
 
5844
        // pick a target register for the general case
 
5845
        int dstreg = dstp.select_register(REG_EAX, src2p);
 
5846
 
 
5847
        // 32-bit form
 
5848
        if (inst.size() == 4)
 
5849
        {
 
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
 
5853
 
 
5854
                // general case
 
5855
                else
 
5856
                {
 
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
 
5860
                }
 
5861
        }
 
5862
 
 
5863
        // 64-bit form
 
5864
        else if (inst.size() == 8)
 
5865
        {
 
5866
                // general case
 
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
 
5870
        }
 
5871
}
 
5872
 
 
5873
 
 
5874
 
 
5875
//**************************************************************************
 
5876
//  FLOATING POINT OPERATIONS
 
5877
//**************************************************************************
 
5878
 
 
5879
//-------------------------------------------------
 
5880
//  op_fload - process a FLOAD opcode
 
5881
//-------------------------------------------------
 
5882
 
 
5883
void drcbe_x86::op_fload(x86code *&dst, const instruction &inst)
 
5884
{
 
5885
        // validate instruction
 
5886
        assert(inst.size() == 4 || inst.size() == 8);
 
5887
        assert_no_condition(inst);
 
5888
        assert_no_flags(inst);
 
5889
 
 
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);
 
5894
 
 
5895
        // immediate index
 
5896
        if (indp.is_immediate())
 
5897
        {
 
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]
 
5901
        }
 
5902
 
 
5903
        // other index
 
5904
        else
 
5905
        {
 
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]
 
5911
        }
 
5912
 
 
5913
        // general case
 
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
 
5917
}
 
5918
 
 
5919
 
 
5920
//-------------------------------------------------
 
5921
//  op_fstore - process a FSTORE opcode
 
5922
//-------------------------------------------------
 
5923
 
 
5924
void drcbe_x86::op_fstore(x86code *&dst, const instruction &inst)
 
5925
{
 
5926
        // validate instruction
 
5927
        assert(inst.size() == 4 || inst.size() == 8);
 
5928
        assert_no_condition(inst);
 
5929
        assert_no_flags(inst);
 
5930
 
 
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);
 
5935
 
 
5936
        // general case
 
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]
 
5940
 
 
5941
        // immediate index
 
5942
        if (indp.is_immediate())
 
5943
        {
 
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
 
5947
        }
 
5948
 
 
5949
        // other index
 
5950
        else
 
5951
        {
 
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
 
5957
        }
 
5958
}
 
5959
 
 
5960
 
 
5961
//-------------------------------------------------
 
5962
//  op_fread - process a FREAD opcode
 
5963
//-------------------------------------------------
 
5964
 
 
5965
void drcbe_x86::op_fread(x86code *&dst, const instruction &inst)
 
5966
{
 
5967
        // validate instruction
 
5968
        assert(inst.size() == 4 || inst.size() == 8);
 
5969
        assert_no_condition(inst);
 
5970
        assert_no_flags(inst);
 
5971
 
 
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());
 
5978
 
 
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
 
5986
 
 
5987
        // store result
 
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
 
5992
}
 
5993
 
 
5994
 
 
5995
//-------------------------------------------------
 
5996
//  op_fwrite - process a FWRITE opcode
 
5997
//-------------------------------------------------
 
5998
 
 
5999
void drcbe_x86::op_fwrite(x86code *&dst, const instruction &inst)
 
6000
{
 
6001
        // validate instruction
 
6002
        assert(inst.size() == 4 || inst.size() == 8);
 
6003
        assert_no_condition(inst);
 
6004
        assert_no_flags(inst);
 
6005
 
 
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());
 
6012
 
 
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
 
6024
}
 
6025
 
 
6026
 
 
6027
//-------------------------------------------------
 
6028
//  op_fmov - process a FMOV opcode
 
6029
//-------------------------------------------------
 
6030
 
 
6031
void drcbe_x86::op_fmov(x86code *&dst, const instruction &inst)
 
6032
{
 
6033
        // validate instruction
 
6034
        assert(inst.size() == 4 || inst.size() == 8);
 
6035
        assert_any_condition(inst);
 
6036
        assert_no_flags(inst);
 
6037
 
 
6038
        // normalize parameters
 
6039
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6040
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6041
 
 
6042
        // always start with a jmp
6472
6043
        emit_link skip = { 0 };
6473
 
 
6474
 
        /* validate instruction */
6475
 
        assert(inst->size == 4 || inst->size == 8);
6476
 
        assert_any_condition(inst);
6477
 
        assert_no_flags(inst);
6478
 
 
6479
 
        /* normalize parameters */
6480
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6481
 
 
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
6485
 
 
6486
 
        /* general case */
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
6493
 
 
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
 
6046
 
 
6047
        // general case
 
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
 
6054
 
 
6055
        // resolve the jump
6495
6056
        if (skip.target != NULL)
6496
 
                track_resolve_link(drcbe, &dst, &skip);                                                                         // skip:
6497
 
        return dst;
6498
 
}
6499
 
 
6500
 
 
6501
 
/*-------------------------------------------------
6502
 
    op_ftoint - process a FTOINT opcode
6503
 
-------------------------------------------------*/
6504
 
 
6505
 
static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6506
 
{
6507
 
        drcuml_parameter dstp, srcp, sizep, roundp;
6508
 
 
6509
 
        /* validate instruction */
6510
 
        assert(inst->size == 4 || inst->size == 8);
6511
 
        assert_no_condition(inst);
6512
 
        assert_no_flags(inst);
6513
 
 
6514
 
        /* normalize parameters */
6515
 
        param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF, &sizep, PTYPE_I, &roundp, PTYPE_I);
6516
 
 
6517
 
        /* set rounding mode if necessary */
6518
 
        if (roundp.value != DRCUML_FMOD_DEFAULT && (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC))
6519
 
        {
6520
 
                emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave));                                                                  // fstcw [fmodesave]
6521
 
                emit_fldcw_m16(&dst, MABS(&fp_control[roundp.value]));                                                  // fldcw fpcontrol[roundp]
6522
 
        }
6523
 
 
6524
 
        /* general case */
6525
 
        emit_fld_p(&dst, inst->size, &srcp);                                                                                            // fld   srcp
6526
 
 
6527
 
        /* 4-byte integer case */
6528
 
        if (sizep.value == DRCUML_SIZE_DWORD)
6529
 
        {
6530
 
                if (dstp.type == DRCUML_PTYPE_MEMORY)
6531
 
                {
6532
 
                        if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6533
 
                                emit_fistp_m32(&dst, MABS(dstp.value));                                                                 // fistp [dstp]
6534
 
                        else
6535
 
                                emit_fisttp_m32(&dst, MABS(dstp.value));                                                                // fisttp [dstp]
6536
 
                }
6537
 
                else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
6538
 
                {
6539
 
                        if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6540
 
                                emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value]));                                   // fistp reglo[dstp]
6541
 
                        else
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]
6544
 
                }
6545
 
        }
6546
 
 
6547
 
        /* 8-byte integer case */
6548
 
        else if (sizep.value == DRCUML_SIZE_QWORD)
6549
 
        {
6550
 
                if (dstp.type == DRCUML_PTYPE_MEMORY)
6551
 
                {
6552
 
                        if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6553
 
                                emit_fistp_m64(&dst, MABS(dstp.value));                                                                 // fistp [dstp]
6554
 
                        else
6555
 
                                emit_fisttp_m64(&dst, MABS(dstp.value));                                                                // fisttp [dstp]
6556
 
                }
6557
 
                else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
6558
 
                {
6559
 
                        if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
6560
 
                                emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value]));                                   // fistp reglo[dstp]
6561
 
                        else
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]
6564
 
                }
6565
 
        }
6566
 
 
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]
6570
 
 
6571
 
        return dst;
6572
 
}
6573
 
 
6574
 
 
6575
 
/*-------------------------------------------------
6576
 
    op_ffrint - process a FFRINT opcode
6577
 
-------------------------------------------------*/
6578
 
 
6579
 
static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6580
 
{
6581
 
        drcuml_parameter dstp, srcp, sizep;
6582
 
 
6583
 
        /* validate instruction */
6584
 
        assert(inst->size == 4 || inst->size == 8);
6585
 
        assert_no_condition(inst);
6586
 
        assert_no_flags(inst);
6587
 
 
6588
 
        /* normalize parameters */
6589
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
6590
 
 
6591
 
        /* 4-byte integer case */
6592
 
        if (sizep.value == DRCUML_SIZE_DWORD)
6593
 
        {
6594
 
                if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
6595
 
                {
6596
 
                        emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value);                                       // mov   [fptemp],srcp
6597
 
                        emit_fild_m32(&dst, MABS(&drcbe->fptemp));                                                                      // fild  [fptemp]
6598
 
                }
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)
6602
 
                {
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]
6605
 
                }
6606
 
        }
6607
 
 
6608
 
        /* 8-bit integer case */
6609
 
        else if (sizep.value == DRCUML_SIZE_QWORD)
6610
 
        {
6611
 
                if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
6612
 
                {
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]
6616
 
                }
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)
6620
 
                {
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]
6623
 
                }
6624
 
        }
6625
 
 
6626
 
        /* store the result and be done */
6627
 
        emit_fstp_p(&dst, inst->size, &dstp);                                                                                           // fstp  [dstp]
6628
 
        return dst;
6629
 
}
6630
 
 
6631
 
 
6632
 
/*-------------------------------------------------
6633
 
    op_ffrflt - process a FFRFLT opcode
6634
 
-------------------------------------------------*/
6635
 
 
6636
 
static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6637
 
{
6638
 
        drcuml_parameter dstp, srcp, sizep;
6639
 
 
6640
 
        /* validate instruction */
6641
 
        assert(inst->size == 4 || inst->size == 8);
6642
 
        assert_no_condition(inst);
6643
 
        assert_no_flags(inst);
6644
 
 
6645
 
        /* normalize parameters */
6646
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF, &sizep, PTYPE_I);
6647
 
 
6648
 
        /* general case */
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
6654
 
 
6655
 
        return dst;
6656
 
}
6657
 
 
6658
 
 
6659
 
/*-------------------------------------------------
6660
 
    op_frnds - process a FRNDS opcode
6661
 
-------------------------------------------------*/
6662
 
 
6663
 
static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6664
 
{
6665
 
        drcuml_parameter dstp, srcp;
6666
 
 
6667
 
        /* validate instruction */
6668
 
        assert(inst->size == 8);
6669
 
        assert_no_condition(inst);
6670
 
        assert_no_flags(inst);
6671
 
 
6672
 
        /* normalize parameters */
6673
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6674
 
 
6675
 
        /* general case */
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]
6680
 
        return dst;
6681
 
}
6682
 
 
6683
 
 
6684
 
/*-------------------------------------------------
6685
 
    op_fadd - process a FADD opcode
6686
 
-------------------------------------------------*/
6687
 
 
6688
 
static x86code *op_fadd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6689
 
{
6690
 
        drcuml_parameter dstp, src1p, src2p;
6691
 
 
6692
 
        /* validate instruction */
6693
 
        assert(inst->size == 4 || inst->size == 8);
6694
 
        assert_no_condition(inst);
6695
 
        assert_no_flags(inst);
6696
 
 
6697
 
        /* normalize parameters */
6698
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6699
 
 
6700
 
        /* general case */
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
6705
 
 
6706
 
        return dst;
6707
 
}
6708
 
 
6709
 
 
6710
 
/*-------------------------------------------------
6711
 
    op_fsub - process a FSUB opcode
6712
 
-------------------------------------------------*/
6713
 
 
6714
 
static x86code *op_fsub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6715
 
{
6716
 
        drcuml_parameter dstp, src1p, src2p;
6717
 
 
6718
 
        /* validate instruction */
6719
 
        assert(inst->size == 4 || inst->size == 8);
6720
 
        assert_no_condition(inst);
6721
 
        assert_no_flags(inst);
6722
 
 
6723
 
        /* normalize parameters */
6724
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6725
 
 
6726
 
        /* general case */
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
6731
 
 
6732
 
        return dst;
6733
 
}
6734
 
 
6735
 
 
6736
 
/*-------------------------------------------------
6737
 
    op_fcmp - process a FCMP opcode
6738
 
-------------------------------------------------*/
6739
 
 
6740
 
static x86code *op_fcmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6741
 
{
6742
 
        drcuml_parameter src1p, src2p;
6743
 
 
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);
6748
 
 
6749
 
        /* normalize parameters */
6750
 
        param_normalize_2(drcbe, inst, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6751
 
 
6752
 
        /* general case */
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
6758
 
 
6759
 
        return dst;
6760
 
}
6761
 
 
6762
 
 
6763
 
/*-------------------------------------------------
6764
 
    op_fmul - process a FMUL opcode
6765
 
-------------------------------------------------*/
6766
 
 
6767
 
static x86code *op_fmul(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6768
 
{
6769
 
        drcuml_parameter dstp, src1p, src2p;
6770
 
 
6771
 
        /* validate instruction */
6772
 
        assert(inst->size == 4 || inst->size == 8);
6773
 
        assert_no_condition(inst);
6774
 
        assert_no_flags(inst);
6775
 
 
6776
 
        /* normalize parameters */
6777
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6778
 
 
6779
 
        /* general case */
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
6784
 
 
6785
 
        return dst;
6786
 
}
6787
 
 
6788
 
 
6789
 
/*-------------------------------------------------
6790
 
    op_fdiv - process a FDIV opcode
6791
 
-------------------------------------------------*/
6792
 
 
6793
 
static x86code *op_fdiv(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6794
 
{
6795
 
        drcuml_parameter dstp, src1p, src2p;
6796
 
 
6797
 
        /* validate instruction */
6798
 
        assert(inst->size == 4 || inst->size == 8);
6799
 
        assert_no_condition(inst);
6800
 
        assert_no_flags(inst);
6801
 
 
6802
 
        /* normalize parameters */
6803
 
        param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &src1p, PTYPE_MF, &src2p, PTYPE_MF);
6804
 
 
6805
 
        /* general case */
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
6810
 
 
6811
 
        return dst;
6812
 
}
6813
 
 
6814
 
 
6815
 
/*-------------------------------------------------
6816
 
    op_fneg - process a FNEG opcode
6817
 
-------------------------------------------------*/
6818
 
 
6819
 
static x86code *op_fneg(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6820
 
{
6821
 
        drcuml_parameter dstp, srcp;
6822
 
 
6823
 
        /* validate instruction */
6824
 
        assert(inst->size == 4 || inst->size == 8);
6825
 
        assert_no_condition(inst);
6826
 
        assert_no_flags(inst);
6827
 
 
6828
 
        /* normalize parameters */
6829
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6830
 
 
6831
 
        /* general case */
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
6835
 
 
6836
 
        return dst;
6837
 
}
6838
 
 
6839
 
 
6840
 
/*-------------------------------------------------
6841
 
    op_fabs - process a FABS opcode
6842
 
-------------------------------------------------*/
6843
 
 
6844
 
static x86code *op_fabs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6845
 
{
6846
 
        drcuml_parameter dstp, srcp;
6847
 
 
6848
 
        /* validate instruction */
6849
 
        assert(inst->size == 4 || inst->size == 8);
6850
 
        assert_no_condition(inst);
6851
 
        assert_no_flags(inst);
6852
 
 
6853
 
        /* normalize parameters */
6854
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6855
 
 
6856
 
        /* general case */
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
6860
 
 
6861
 
        return dst;
6862
 
}
6863
 
 
6864
 
 
6865
 
/*-------------------------------------------------
6866
 
    op_fsqrt - process a FSQRT opcode
6867
 
-------------------------------------------------*/
6868
 
 
6869
 
static x86code *op_fsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6870
 
{
6871
 
        drcuml_parameter dstp, srcp;
6872
 
 
6873
 
        /* validate instruction */
6874
 
        assert(inst->size == 4 || inst->size == 8);
6875
 
        assert_no_condition(inst);
6876
 
        assert_no_flags(inst);
6877
 
 
6878
 
        /* normalize parameters */
6879
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6880
 
 
6881
 
        /* general case */
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
6885
 
 
6886
 
        return dst;
6887
 
}
6888
 
 
6889
 
 
6890
 
/*-------------------------------------------------
6891
 
    op_frecip - process a FRECIP opcode
6892
 
-------------------------------------------------*/
6893
 
 
6894
 
static x86code *op_frecip(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6895
 
{
6896
 
        drcuml_parameter dstp, srcp;
6897
 
 
6898
 
        /* validate instruction */
6899
 
        assert(inst->size == 4 || inst->size == 8);
6900
 
        assert_no_condition(inst);
6901
 
        assert_no_flags(inst);
6902
 
 
6903
 
        /* normalize parameters */
6904
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6905
 
 
6906
 
        /* general case */
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
6911
 
 
6912
 
        return dst;
6913
 
}
6914
 
 
6915
 
 
6916
 
/*-------------------------------------------------
6917
 
    op_frsqrt - process a FRSQRT opcode
6918
 
-------------------------------------------------*/
6919
 
 
6920
 
static x86code *op_frsqrt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
6921
 
{
6922
 
        drcuml_parameter dstp, srcp;
6923
 
 
6924
 
        /* validate instruction */
6925
 
        assert(inst->size == 4 || inst->size == 8);
6926
 
        assert_no_condition(inst);
6927
 
        assert_no_flags(inst);
6928
 
 
6929
 
        /* normalize parameters */
6930
 
        param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
6931
 
 
6932
 
        /* general case */
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
6938
 
 
6939
 
        return dst;
6940
 
}
6941
 
 
6942
 
 
6943
 
 
6944
 
/***************************************************************************
6945
 
    MISCELLAENOUS FUNCTIONS
6946
 
***************************************************************************/
6947
 
 
6948
 
/*-------------------------------------------------
6949
 
    dmulu - perform a double-wide unsigned multiply
6950
 
-------------------------------------------------*/
6951
 
 
6952
 
static int dmulu(UINT64 *dstlo, UINT64 *dsthi, UINT64 src1, UINT64 src2, int flags)
6953
 
{
6954
 
        UINT64 lo, hi, prevlo;
6955
 
        UINT64 a, b, temp;
6956
 
 
6957
 
        /* shortcut if we don't care about the high bits or the flags */
6958
 
        if (dstlo == dsthi && flags == 0)
6959
 
        {
6960
 
                *dstlo = src1 * src2;
 
6057
                track_resolve_link(dst, skip);                                                                                          // skip:
 
6058
}
 
6059
 
 
6060
 
 
6061
//-------------------------------------------------
 
6062
//  op_ftoint - process a FTOINT opcode
 
6063
//-------------------------------------------------
 
6064
 
 
6065
void drcbe_x86::op_ftoint(x86code *&dst, const instruction &inst)
 
6066
{
 
6067
        // validate instruction
 
6068
        assert(inst.size() == 4 || inst.size() == 8);
 
6069
        assert_no_condition(inst);
 
6070
        assert_no_flags(inst);
 
6071
 
 
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());
 
6079
 
 
6080
        // set rounding mode if necessary
 
6081
        if (roundp.rounding() != ROUND_DEFAULT && (!m_sse3 || roundp.rounding() != ROUND_TRUNC))
 
6082
        {
 
6083
                emit_fstcw_m16(dst, MABS(&m_fmodesave));                                                                        // fstcw [fmodesave]
 
6084
                emit_fldcw_m16(dst, MABS(&fp_control[roundp.rounding()]));                                                      // fldcw fpcontrol[roundp]
 
6085
        }
 
6086
 
 
6087
        // general case
 
6088
        emit_fld_p(dst, inst.size(), srcp);                                                                                             // fld   srcp
 
6089
 
 
6090
        // 4-byte integer case
 
6091
        if (sizep.size() == SIZE_DWORD)
 
6092
        {
 
6093
                if (dstp.is_memory())
 
6094
                {
 
6095
                        if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
 
6096
                                emit_fistp_m32(dst, MABS(dstp.memory()));                                                                       // fistp [dstp]
 
6097
                        else
 
6098
                                emit_fisttp_m32(dst, MABS(dstp.memory()));                                                              // fisttp [dstp]
 
6099
                }
 
6100
                else if (dstp.is_int_register())
 
6101
                {
 
6102
                        if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
 
6103
                                emit_fistp_m32(dst, MABS(m_reglo[dstp.ireg()]));                                        // fistp reglo[dstp]
 
6104
                        else
 
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]
 
6107
                }
 
6108
        }
 
6109
 
 
6110
        // 8-byte integer case
 
6111
        else if (sizep.size() == SIZE_QWORD)
 
6112
        {
 
6113
                if (dstp.is_memory())
 
6114
                {
 
6115
                        if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
 
6116
                                emit_fistp_m64(dst, MABS(dstp.memory()));                                                                       // fistp [dstp]
 
6117
                        else
 
6118
                                emit_fisttp_m64(dst, MABS(dstp.memory()));                                                              // fisttp [dstp]
 
6119
                }
 
6120
                else if (dstp.is_int_register())
 
6121
                {
 
6122
                        if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
 
6123
                                emit_fistp_m64(dst, MABS(m_reglo[dstp.ireg()]));                                        // fistp reglo[dstp]
 
6124
                        else
 
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]
 
6127
                }
 
6128
        }
 
6129
 
 
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]
 
6133
}
 
6134
 
 
6135
 
 
6136
//-------------------------------------------------
 
6137
//  op_ffrint - process a FFRINT opcode
 
6138
//-------------------------------------------------
 
6139
 
 
6140
void drcbe_x86::op_ffrint(x86code *&dst, const instruction &inst)
 
6141
{
 
6142
        // validate instruction
 
6143
        assert(inst.size() == 4 || inst.size() == 8);
 
6144
        assert_no_condition(inst);
 
6145
        assert_no_flags(inst);
 
6146
 
 
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());
 
6152
 
 
6153
        // 4-byte integer case
 
6154
        if (sizep.size() == SIZE_DWORD)
 
6155
        {
 
6156
                if (srcp.is_immediate())
 
6157
                {
 
6158
                        emit_mov_m32_imm(dst, MABS(&m_fptemp), srcp.immediate());                                       // mov   [fptemp],srcp
 
6159
                        emit_fild_m32(dst, MABS(&m_fptemp));                                                                    // fild  [fptemp]
 
6160
                }
 
6161
                else if (srcp.is_memory())
 
6162
                        emit_fild_m32(dst, MABS(srcp.memory()));                                                                                // fild  [srcp]
 
6163
                else if (srcp.is_int_register())
 
6164
                {
 
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]
 
6167
                }
 
6168
        }
 
6169
 
 
6170
        // 8-bit integer case
 
6171
        else if (sizep.size() == SIZE_QWORD)
 
6172
        {
 
6173
                if (srcp.is_immediate())
 
6174
                {
 
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]
 
6178
                }
 
6179
                else if (srcp.is_memory())
 
6180
                        emit_fild_m64(dst, MABS(srcp.memory()));                                                                                // fild  [srcp]
 
6181
                else if (srcp.is_int_register())
 
6182
                {
 
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]
 
6185
                }
 
6186
        }
 
6187
 
 
6188
        // store the result and be done
 
6189
        emit_fstp_p(dst, inst.size(), dstp);                                                                                            // fstp  [dstp]
 
6190
}
 
6191
 
 
6192
 
 
6193
//-------------------------------------------------
 
6194
//  op_ffrflt - process a FFRFLT opcode
 
6195
//-------------------------------------------------
 
6196
 
 
6197
void drcbe_x86::op_ffrflt(x86code *&dst, const instruction &inst)
 
6198
{
 
6199
        // validate instruction
 
6200
        assert(inst.size() == 4 || inst.size() == 8);
 
6201
        assert_no_condition(inst);
 
6202
        assert_no_flags(inst);
 
6203
 
 
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());
 
6209
 
 
6210
        // general case
 
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
 
6216
}
 
6217
 
 
6218
 
 
6219
//-------------------------------------------------
 
6220
//  op_frnds - process a FRNDS opcode
 
6221
//-------------------------------------------------
 
6222
 
 
6223
void drcbe_x86::op_frnds(x86code *&dst, const instruction &inst)
 
6224
{
 
6225
        // validate instruction
 
6226
        assert(inst.size() == 8);
 
6227
        assert_no_condition(inst);
 
6228
        assert_no_flags(inst);
 
6229
 
 
6230
        // normalize parameters
 
6231
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6232
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6233
 
 
6234
        // general case
 
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]
 
6239
}
 
6240
 
 
6241
 
 
6242
//-------------------------------------------------
 
6243
//  op_fadd - process a FADD opcode
 
6244
//-------------------------------------------------
 
6245
 
 
6246
void drcbe_x86::op_fadd(x86code *&dst, const instruction &inst)
 
6247
{
 
6248
        // validate instruction
 
6249
        assert(inst.size() == 4 || inst.size() == 8);
 
6250
        assert_no_condition(inst);
 
6251
        assert_no_flags(inst);
 
6252
 
 
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);
 
6258
 
 
6259
        // general case
 
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
 
6264
}
 
6265
 
 
6266
 
 
6267
//-------------------------------------------------
 
6268
//  op_fsub - process a FSUB opcode
 
6269
//-------------------------------------------------
 
6270
 
 
6271
void drcbe_x86::op_fsub(x86code *&dst, const instruction &inst)
 
6272
{
 
6273
        // validate instruction
 
6274
        assert(inst.size() == 4 || inst.size() == 8);
 
6275
        assert_no_condition(inst);
 
6276
        assert_no_flags(inst);
 
6277
 
 
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);
 
6282
 
 
6283
        // general case
 
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
 
6288
}
 
6289
 
 
6290
 
 
6291
//-------------------------------------------------
 
6292
//  op_fcmp - process a FCMP opcode
 
6293
//-------------------------------------------------
 
6294
 
 
6295
void drcbe_x86::op_fcmp(x86code *&dst, const instruction &inst)
 
6296
{
 
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);
 
6301
 
 
6302
        // normalize parameters
 
6303
        be_parameter src1p(*this, inst.param(0), PTYPE_MF);
 
6304
        be_parameter src2p(*this, inst.param(1), PTYPE_MF);
 
6305
 
 
6306
        // general case
 
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
 
6312
}
 
6313
 
 
6314
 
 
6315
//-------------------------------------------------
 
6316
//  op_fmul - process a FMUL opcode
 
6317
//-------------------------------------------------
 
6318
 
 
6319
void drcbe_x86::op_fmul(x86code *&dst, const instruction &inst)
 
6320
{
 
6321
        // validate instruction
 
6322
        assert(inst.size() == 4 || inst.size() == 8);
 
6323
        assert_no_condition(inst);
 
6324
        assert_no_flags(inst);
 
6325
 
 
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);
 
6331
 
 
6332
        // general case
 
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
 
6337
}
 
6338
 
 
6339
 
 
6340
//-------------------------------------------------
 
6341
//  op_fdiv - process a FDIV opcode
 
6342
//-------------------------------------------------
 
6343
 
 
6344
void drcbe_x86::op_fdiv(x86code *&dst, const instruction &inst)
 
6345
{
 
6346
        // validate instruction
 
6347
        assert(inst.size() == 4 || inst.size() == 8);
 
6348
        assert_no_condition(inst);
 
6349
        assert_no_flags(inst);
 
6350
 
 
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);
 
6355
 
 
6356
        // general case
 
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
 
6361
}
 
6362
 
 
6363
 
 
6364
//-------------------------------------------------
 
6365
//  op_fneg - process a FNEG opcode
 
6366
//-------------------------------------------------
 
6367
 
 
6368
void drcbe_x86::op_fneg(x86code *&dst, const instruction &inst)
 
6369
{
 
6370
        // validate instruction
 
6371
        assert(inst.size() == 4 || inst.size() == 8);
 
6372
        assert_no_condition(inst);
 
6373
        assert_no_flags(inst);
 
6374
 
 
6375
        // normalize parameters
 
6376
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6377
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6378
 
 
6379
        // general case
 
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
 
6383
}
 
6384
 
 
6385
 
 
6386
//-------------------------------------------------
 
6387
//  op_fabs - process a FABS opcode
 
6388
//-------------------------------------------------
 
6389
 
 
6390
void drcbe_x86::op_fabs(x86code *&dst, const instruction &inst)
 
6391
{
 
6392
        // validate instruction
 
6393
        assert(inst.size() == 4 || inst.size() == 8);
 
6394
        assert_no_condition(inst);
 
6395
        assert_no_flags(inst);
 
6396
 
 
6397
        // normalize parameters
 
6398
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6399
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6400
 
 
6401
        // general case
 
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
 
6405
}
 
6406
 
 
6407
 
 
6408
//-------------------------------------------------
 
6409
//  op_fsqrt - process a FSQRT opcode
 
6410
//-------------------------------------------------
 
6411
 
 
6412
void drcbe_x86::op_fsqrt(x86code *&dst, const instruction &inst)
 
6413
{
 
6414
        // validate instruction
 
6415
        assert(inst.size() == 4 || inst.size() == 8);
 
6416
        assert_no_condition(inst);
 
6417
        assert_no_flags(inst);
 
6418
 
 
6419
        // normalize parameters
 
6420
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6421
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6422
 
 
6423
        // general case
 
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
 
6427
}
 
6428
 
 
6429
 
 
6430
//-------------------------------------------------
 
6431
//  op_frecip - process a FRECIP opcode
 
6432
//-------------------------------------------------
 
6433
 
 
6434
void drcbe_x86::op_frecip(x86code *&dst, const instruction &inst)
 
6435
{
 
6436
        // validate instruction
 
6437
        assert(inst.size() == 4 || inst.size() == 8);
 
6438
        assert_no_condition(inst);
 
6439
        assert_no_flags(inst);
 
6440
 
 
6441
        // normalize parameters
 
6442
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6443
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6444
 
 
6445
        // general case
 
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
 
6450
}
 
6451
 
 
6452
 
 
6453
//-------------------------------------------------
 
6454
//  op_frsqrt - process a FRSQRT opcode
 
6455
//-------------------------------------------------
 
6456
 
 
6457
void drcbe_x86::op_frsqrt(x86code *&dst, const instruction &inst)
 
6458
{
 
6459
        // validate instruction
 
6460
        assert(inst.size() == 4 || inst.size() == 8);
 
6461
        assert_no_condition(inst);
 
6462
        assert_no_flags(inst);
 
6463
 
 
6464
        // normalize parameters
 
6465
        be_parameter dstp(*this, inst.param(0), PTYPE_MF);
 
6466
        be_parameter srcp(*this, inst.param(1), PTYPE_MF);
 
6467
 
 
6468
        // general case
 
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
 
6474
}
 
6475
 
 
6476
 
 
6477
 
 
6478
//**************************************************************************
 
6479
//  MISCELLAENOUS FUNCTIONS
 
6480
//**************************************************************************
 
6481
 
 
6482
//-------------------------------------------------
 
6483
//  dmulu - perform a double-wide unsigned multiply
 
6484
//-------------------------------------------------
 
6485
 
 
6486
int drcbe_x86::dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags)
 
6487
{
 
6488
        // shortcut if we don't care about the high bits or the flags
 
6489
        if (&dstlo == &dsthi && flags == 0)
 
6490
        {
 
6491
                dstlo = src1 * src2;
6961
6492
                return 0;
6962
6493
        }
6963
6494
 
6964
 
        /* fetch source values */
6965
 
        a = src1;
6966
 
        b = src2;
 
6495
        // fetch source values
 
6496
        UINT64 a = src1;
 
6497
        UINT64 b = src2;
6967
6498
        if (a == 0 || b == 0)
6968
6499
        {
6969
 
                *dsthi = *dstlo = 0;
6970
 
                return DRCUML_FLAG_Z;
 
6500
                dsthi = dstlo = 0;
 
6501
                return FLAG_Z;
6971
6502
        }
6972
6503
 
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);
6976
6507
 
6977
 
        /* compute middle parts */
6978
 
        prevlo = lo;
6979
 
        temp = (UINT64)(UINT32)(a >> 32)  * (UINT64)(UINT32)(b >> 0);
 
6508
        // compute middle parts
 
6509
        UINT64 prevlo = lo;
 
6510
        UINT64 temp = (UINT64)(UINT32)(a >> 32)  * (UINT64)(UINT32)(b >> 0);
6980
6511
        lo += temp << 32;
6981
6512
        hi += (temp >> 32) + (lo < prevlo);
6982
6513
 
6985
6516
        lo += temp << 32;
6986
6517
        hi += (temp >> 32) + (lo < prevlo);
6987
6518
 
6988
 
        /* store the results */
6989
 
        *dsthi = hi;
6990
 
        *dstlo = lo;
6991
 
        return ((hi >> 60) & DRCUML_FLAG_S) | ((*dsthi != 0) << 1);
 
6519
        // store the results
 
6520
        dsthi = hi;
 
6521
        dstlo = lo;
 
6522
        return ((hi >> 60) & FLAG_S) | ((dsthi != 0) << 1);
6992
6523
}
6993
6524
 
6994
6525
 
6995
 
/*-------------------------------------------------
6996
 
    dmuls - perform a double-wide signed multiply
6997
 
-------------------------------------------------*/
 
6526
//-------------------------------------------------
 
6527
//  dmuls - perform a double-wide signed multiply
 
6528
//-------------------------------------------------
6998
6529
 
6999
 
static int dmuls(UINT64 *dstlo, UINT64 *dsthi, INT64 src1, INT64 src2, int flags)
 
6530
int drcbe_x86::dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags)
7000
6531
{
7001
6532
        UINT64 lo, hi, prevlo;
7002
6533
        UINT64 a, b, temp;
7003
6534
 
7004
 
        /* shortcut if we don't care about the high bits or the flags */
7005
 
        if (dstlo == dsthi && flags == 0)
 
6535
        // shortcut if we don't care about the high bits or the flags
 
6536
        if (&dstlo == &dsthi && flags == 0)
7006
6537
        {
7007
 
                *dstlo = src1 * src2;
 
6538
                dstlo = src1 * src2;
7008
6539
                return 0;
7009
6540
        }
7010
6541
 
7011
 
        /* fetch absolute source values */
 
6542
        // fetch absolute source values
7012
6543
        a = src1; if ((INT64)a < 0) a = -a;
7013
6544
        b = src2; if ((INT64)b < 0) b = -b;
7014
6545
        if (a == 0 || b == 0)
7015
6546
        {
7016
 
                *dsthi = *dstlo = 0;
7017
 
                return DRCUML_FLAG_Z;
 
6547
                dsthi = dstlo = 0;
 
6548
                return FLAG_Z;
7018
6549
        }
7019
6550
 
7020
 
        /* compute high and low parts first */
 
6551
        // compute high and low parts first
7021
6552
        lo = (UINT64)(UINT32)(a >> 0)  * (UINT64)(UINT32)(b >> 0);
7022
6553
        hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
7023
6554
 
7024
 
        /* compute middle parts */
 
6555
        // compute middle parts
7025
6556
        prevlo = lo;
7026
6557
        temp = (UINT64)(UINT32)(a >> 32)  * (UINT64)(UINT32)(b >> 0);
7027
6558
        lo += temp << 32;
7032
6563
        lo += temp << 32;
7033
6564
        hi += (temp >> 32) + (lo < prevlo);
7034
6565
 
7035
 
        /* adjust for signage */
 
6566
        // adjust for signage
7036
6567
        if ((INT64)(src1 ^ src2) < 0)
7037
6568
        {
7038
6569
                hi = ~hi + (lo == 0);
7039
6570
                lo = ~lo + 1;
7040
6571
        }
7041
6572
 
7042
 
        /* store the results */
7043
 
        *dsthi = hi;
7044
 
        *dstlo = lo;
7045
 
        return ((hi >> 60) & DRCUML_FLAG_S) | ((*dsthi != ((INT64)lo >> 63)) << 1);
7046
 
}
7047
 
 
7048
 
 
7049
 
/*-------------------------------------------------
7050
 
    ddivu - perform a double-wide unsigned divide
7051
 
-------------------------------------------------*/
7052
 
 
7053
 
static int ddivu(UINT64 *dstlo, UINT64 *dsthi, UINT64 src1, UINT64 src2)
7054
 
{
7055
 
        /* do nothing if src2 == 0 */
7056
 
        if (src2 == 0)
7057
 
                return DRCUML_FLAG_V;
7058
 
 
7059
 
        /* shortcut if no remainder */
7060
 
        *dstlo = src1 / src2;
7061
 
        if (dstlo != dsthi)
7062
 
                *dsthi = src1 % src2;
7063
 
        return ((*dstlo == 0) << 2) | ((*dstlo >> 60) & DRCUML_FLAG_S);
7064
 
}
7065
 
 
7066
 
 
7067
 
/*-------------------------------------------------
7068
 
    ddivs - perform a double-wide signed divide
7069
 
-------------------------------------------------*/
7070
 
 
7071
 
static int ddivs(UINT64 *dstlo, UINT64 *dsthi, INT64 src1, INT64 src2)
7072
 
{
7073
 
        /* do nothing if src2 == 0 */
7074
 
        if (src2 == 0)
7075
 
                return DRCUML_FLAG_V;
7076
 
 
7077
 
        /* shortcut if no remainder */
7078
 
        *dstlo = src1 / src2;
7079
 
        if (dstlo != dsthi)
7080
 
                *dsthi = src1 % src2;
7081
 
        return ((*dstlo == 0) << 2) | ((*dstlo >> 60) & DRCUML_FLAG_S);
 
6573
        // store the results
 
6574
        dsthi = hi;
 
6575
        dstlo = lo;
 
6576
        return ((hi >> 60) & FLAG_S) | ((dsthi != ((INT64)lo >> 63)) << 1);
 
6577
}
 
6578
 
 
6579
 
 
6580
//-------------------------------------------------
 
6581
//  ddivu - perform a double-wide unsigned divide
 
6582
//-------------------------------------------------
 
6583
 
 
6584
int drcbe_x86::ddivu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2)
 
6585
{
 
6586
        // do nothing if src2 == 0
 
6587
        if (src2 == 0)
 
6588
                return FLAG_V;
 
6589
 
 
6590
        // shortcut if no remainder
 
6591
        dstlo = src1 / src2;
 
6592
        if (dstlo != dsthi)
 
6593
                dsthi = src1 % src2;
 
6594
        return ((dstlo == 0) << 2) | ((dstlo >> 60) & FLAG_S);
 
6595
}
 
6596
 
 
6597
 
 
6598
//-------------------------------------------------
 
6599
//  ddivs - perform a double-wide signed divide
 
6600
//-------------------------------------------------
 
6601
 
 
6602
int drcbe_x86::ddivs(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2)
 
6603
{
 
6604
        // do nothing if src2 == 0
 
6605
        if (src2 == 0)
 
6606
                return FLAG_V;
 
6607
 
 
6608
        // shortcut if no remainder
 
6609
        dstlo = src1 / src2;
 
6610
        if (dstlo != dsthi)
 
6611
                dsthi = src1 % src2;
 
6612
        return ((dstlo == 0) << 2) | ((dstlo >> 60) & FLAG_S);
7082
6613
}