Revision e6dbd3b3 target-m68k/translate.c

b/target-m68k/translate.c
42 42

  
43 43
/* internal defines */
44 44
typedef struct DisasContext {
45
    CPUM68KState *env;
45 46
    target_ulong pc;
46 47
    int is_jmp;
47 48
    int cc_op;
......
198 199
    }
199 200
}
200 201

  
202
/* Read a 32-bit immediate constant.  */
203
static inline uint32_t read_im32(DisasContext *s)
204
{
205
    uint32_t im;
206
    im = ((uint32_t)lduw_code(s->pc)) << 16;
207
    s->pc += 2;
208
    im |= lduw_code(s->pc);
209
    s->pc += 2;
210
    return im;
211
}
212

  
213
/* Calculate and address index.  */
214
static int gen_addr_index(uint16_t ext, int tmp)
215
{
216
    int add;
217
    int scale;
218

  
219
    add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
220
    if ((ext & 0x800) == 0) {
221
        gen_op_ext16s32(tmp, add);
222
        add = tmp;
223
    }
224
    scale = (ext >> 9) & 3;
225
    if (scale != 0) {
226
        gen_op_shl32(tmp, add, gen_im32(scale));
227
        add = tmp;
228
    }
229
    return add;
230
}
231

  
201 232
/* Handle a base + index + displacement effective addresss.  A base of
202 233
   -1 means pc-relative.  */
203 234
static int gen_lea_indexed(DisasContext *s, int opsize, int base)
204 235
{
205
    int scale;
206 236
    uint32_t offset;
207 237
    uint16_t ext;
208 238
    int add;
209 239
    int tmp;
240
    uint32_t bd, od;
210 241

  
211 242
    offset = s->pc;
212 243
    ext = lduw_code(s->pc);
213 244
    s->pc += 2;
214
    tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
215
    /* ??? Check W/L bit.  */
216
    scale = (ext >> 9) & 3;
217
    if (scale == 0) {
218
        add = tmp;
219
    } else {
220
        add = gen_new_qreg(QMODE_I32);
221
        gen_op_shl32(add, tmp, gen_im32(scale));
222
    }
223
    tmp = gen_new_qreg(QMODE_I32);
224
    if (base != -1) {
225
        gen_op_add32(tmp, base, gen_im32((int8_t)ext));
226
        gen_op_add32(tmp, tmp, add);
245

  
246
    if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
247
        return -1;
248

  
249
    if (ext & 0x100) {
250
        /* full extension word format */
251
        if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
252
            return -1;
253

  
254
        if ((ext & 0x30) > 0x10) {
255
            /* base displacement */
256
            if ((ext & 0x30) == 0x20) {
257
                bd = (int16_t)lduw_code(s->pc);
258
                s->pc += 2;
259
            } else {
260
                bd = read_im32(s);
261
            }
262
        } else {
263
            bd = 0;
264
        }
265
        tmp = gen_new_qreg(QMODE_I32);
266
        if ((ext & 0x44) == 0) {
267
            /* pre-index */
268
            add = gen_addr_index(ext, tmp);
269
        } else {
270
            add = QREG_NULL;
271
        }
272
        if ((ext & 0x80) == 0) {
273
            /* base not suppressed */
274
            if (base == -1) {
275
                base = gen_im32(offset + bd);
276
                bd = 0;
277
            }
278
            if (add) {
279
                gen_op_add32(tmp, add, base);
280
                add = tmp;
281
            } else {
282
                add = base;
283
            }
284
        }
285
        if (add) {
286
            if (bd != 0) {
287
                gen_op_add32(tmp, add, gen_im32(bd));
288
                add = tmp;
289
            }
290
        } else {
291
            add = gen_im32(bd);
292
        }
293
        if ((ext & 3) != 0) {
294
            /* memory indirect */
295
            base = gen_load(s, OS_LONG, add, 0);
296
            if ((ext & 0x44) == 4) {
297
                add = gen_addr_index(ext, tmp);
298
                gen_op_add32(tmp, add, base);
299
                add = tmp;
300
            } else {
301
                add = base;
302
            }
303
            if ((ext & 3) > 1) {
304
                /* outer displacement */
305
                if ((ext & 3) == 2) {
306
                    od = (int16_t)lduw_code(s->pc);
307
                    s->pc += 2;
308
                } else {
309
                    od = read_im32(s);
310
                }
311
            } else {
312
                od = 0;
313
            }
314
            if (od != 0) {
315
                gen_op_add32(add, tmp, gen_im32(od));
316
                add = tmp;
317
            }
318
        }
227 319
    } else {
228
        gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
320
        /* brief extension word format */
321
        tmp = gen_new_qreg(QMODE_I32);
322
        add = gen_addr_index(ext, tmp);
323
        if (base != -1) {
324
            gen_op_add32(tmp, add, base);
325
            if ((int8_t)ext)
326
                gen_op_add32(tmp, tmp, gen_im32((int8_t)ext));
327
        } else {
328
            gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
329
        }
330
        add = tmp;
229 331
    }
230
    return tmp;
231
}
232

  
233
/* Read a 32-bit immediate constant.  */
234
static inline uint32_t read_im32(DisasContext *s)
235
{
236
    uint32_t im;
237
    im = ((uint32_t)lduw_code(s->pc)) << 16;
238
    s->pc += 2;
239
    im |= lduw_code(s->pc);
240
    s->pc += 2;
241
    return im;
332
    return add;
242 333
}
243 334

  
244

  
245 335
/* Update the CPU env CC_OP state.  */
246 336
static inline void gen_flush_cc_op(DisasContext *s)
247 337
{
......
2721 2811
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2722 2812
    gen_opparam_ptr = gen_opparam_buf;
2723 2813

  
2814
    dc->env = env;
2724 2815
    dc->is_jmp = DISAS_NEXT;
2725 2816
    dc->pc = pc_start;
2726 2817
    dc->cc_op = CC_OP_DYNAMIC;

Also available in: Unified diff