~ubuntu-branches/ubuntu/karmic/e-uae/karmic

« back to all changes in this revision

Viewing changes to src/newcpu.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephan Suerken
  • Date: 2008-07-05 14:02:02 UTC
  • Revision ID: james.westby@ubuntu.com-20080705140202-u5aagnhtg31pmjc3
Tags: upstream-0.8.29-WIP4
ImportĀ upstreamĀ versionĀ 0.8.29-WIP4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 /*
 
2
  * UAE - The Un*x Amiga Emulator
 
3
  *
 
4
  * MC68000 emulation
 
5
  *
 
6
  * (c) 1995 Bernd Schmidt
 
7
  */
 
8
 
 
9
#include "sysconfig.h"
 
10
#include "sysdeps.h"
 
11
 
 
12
#include "options.h"
 
13
#include "events.h"
 
14
#include "uae.h"
 
15
#include "memory.h"
 
16
#include "custom.h"
 
17
#include "newcpu.h"
 
18
#include "cpu_prefetch.h"
 
19
#include "autoconf.h"
 
20
#include "traps.h"
 
21
#include "ersatz.h"
 
22
#include "debug.h"
 
23
#include "gui.h"
 
24
#include "savestate.h"
 
25
#include "blitter.h"
 
26
#include "ar.h"
 
27
#include "sleep.h"
 
28
 
 
29
#ifdef JIT
 
30
extern uae_u8* compiled_code;
 
31
#include "compemu.h"
 
32
#endif
 
33
 
 
34
#define f_out fprintf
 
35
#define console_out printf
 
36
 
 
37
/* Opcode of faulting instruction */
 
38
static uae_u16 last_op_for_exception_3;
 
39
/* PC at fault time */
 
40
static uaecptr last_addr_for_exception_3;
 
41
/* Address that generated the exception */
 
42
static uaecptr last_fault_for_exception_3;
 
43
/* read (0) or write (1) access */
 
44
static int last_writeaccess_for_exception_3;
 
45
/* instruction (1) or data (0) access */
 
46
static int last_instructionaccess_for_exception_3;
 
47
 
 
48
const int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
 
49
const int imm8_table[] = { 8,1,2,3,4,5,6,7 };
 
50
 
 
51
int movem_index1[256];
 
52
int movem_index2[256];
 
53
int movem_next[256];
 
54
 
 
55
#ifdef FPUEMU
 
56
int fpp_movem_index1[256];
 
57
int fpp_movem_index2[256];
 
58
int fpp_movem_next[256];
 
59
#endif
 
60
 
 
61
cpuop_func *cpufunctbl[65536];
 
62
 
 
63
static int warned_cpu68020;
 
64
 
 
65
 
 
66
#define COUNT_INSTRS 0
 
67
 
 
68
#if COUNT_INSTRS
 
69
static unsigned long int instrcount[65536];
 
70
static uae_u16 opcodenums[65536];
 
71
 
 
72
static int compfn (const void *el1, const void *el2)
 
73
{
 
74
    return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
 
75
}
 
76
 
 
77
static char *icountfilename (void)
 
78
{
 
79
    char *name = getenv ("INSNCOUNT");
 
80
    if (name)
 
81
        return name;
 
82
    return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
 
83
}
 
84
 
 
85
void dump_counts (void)
 
86
{
 
87
    FILE *f = fopen (icountfilename (), "w");
 
88
    unsigned long int total;
 
89
    int i;
 
90
 
 
91
    write_log ("Writing instruction count file...\n");
 
92
    for (i = 0; i < 65536; i++) {
 
93
        opcodenums[i] = i;
 
94
        total += instrcount[i];
 
95
    }
 
96
    qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
 
97
 
 
98
    fprintf (f, "Total: %lu\n", total);
 
99
    for (i=0; i < 65536; i++) {
 
100
        unsigned long int cnt = instrcount[opcodenums[i]];
 
101
        struct instr *dp;
 
102
        struct mnemolookup *lookup;
 
103
        if (!cnt)
 
104
            break;
 
105
        dp = table68k + opcodenums[i];
 
106
        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
 
107
            ;
 
108
        fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
 
109
    }
 
110
    fclose (f);
 
111
}
 
112
#else
 
113
void dump_counts (void)
 
114
{
 
115
}
 
116
#endif
 
117
 
 
118
STATIC_INLINE void count_instr (unsigned int opcode)
 
119
{
 
120
#if COUNT_INSTRS == 2
 
121
    if (table68k[opcode].handler != -1)
 
122
        instrcount[table68k[opcode].handler]++;
 
123
#elif COUNT_INSTRS == 1
 
124
    instrcount[opcode]++;
 
125
#endif
 
126
}
 
127
 
 
128
static unsigned long op_illg_1 (uae_u32 opcode, struct regstruct *regs) REGPARAM;
 
129
 
 
130
static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode, struct regstruct *regs)
 
131
{
 
132
    op_illg (opcode, regs);
 
133
    return 4;
 
134
}
 
135
 
 
136
static void build_cpufunctbl (void)
 
137
{
 
138
    int i, opcnt;
 
139
    unsigned long opcode;
 
140
    const struct cputbl *tbl = 0;
 
141
 
 
142
    switch (currprefs.cpu_level) {
 
143
#ifdef CPUEMU_0
 
144
#ifndef CPUEMU_68000_ONLY
 
145
        case 4:
 
146
        case 6:
 
147
        tbl = op_smalltbl_0_ff;
 
148
        break;
 
149
        case 3:
 
150
        tbl = op_smalltbl_1_ff;
 
151
        break;
 
152
        case 2:
 
153
        tbl = op_smalltbl_2_ff;
 
154
        break;
 
155
        case 1:
 
156
        tbl = op_smalltbl_3_ff;
 
157
        break;
 
158
#endif
 
159
#endif
 
160
        case 0:
 
161
        tbl = op_smalltbl_4_ff;
 
162
#ifdef CPUEMU_5
 
163
        if (currprefs.cpu_compatible)
 
164
            tbl = op_smalltbl_5_ff; /* prefetch */
 
165
#endif
 
166
#ifdef CPUEMU_6
 
167
        if (currprefs.cpu_cycle_exact)
 
168
            tbl = op_smalltbl_6_ff; /* prefetch and cycle-exact */
 
169
#endif
 
170
        break;
 
171
    }
 
172
 
 
173
    if (tbl == 0) {
 
174
        write_log ("no CPU emulation cores available!");
 
175
        abort ();
 
176
    }
 
177
 
 
178
    for (opcode = 0; opcode < 65536; opcode++)
 
179
        cpufunctbl[opcode] = op_illg_1;
 
180
    for (i = 0; tbl[i].handler != NULL; i++)
 
181
        cpufunctbl[tbl[i].opcode] = tbl[i].handler;
 
182
 
 
183
    opcnt = 0;
 
184
    for (opcode = 0; opcode < 65536; opcode++) {
 
185
        cpuop_func *f;
 
186
 
 
187
        if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
 
188
            continue;
 
189
 
 
190
        if (table68k[opcode].handler != -1) {
 
191
            f = cpufunctbl[table68k[opcode].handler];
 
192
            if (f == op_illg_1)
 
193
                abort();
 
194
            cpufunctbl[opcode] = f;
 
195
            opcnt++;
 
196
        }
 
197
    }
 
198
    write_log ("Building CPU function table, %d opcodes (%d %d %d).\n",
 
199
        opcnt, currprefs.cpu_level,
 
200
        currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0,
 
201
        currprefs.address_space_24);
 
202
#ifdef JIT
 
203
    build_comp ();
 
204
#endif
 
205
}
 
206
 
 
207
void fill_prefetch_slow (struct regstruct *regs)
 
208
{
 
209
#ifdef CPUEMU_6
 
210
    if (currprefs.cpu_cycle_exact) {
 
211
        regs->ir  = get_word_ce (m68k_getpc (regs));
 
212
        regs->irc = get_word_ce (m68k_getpc (regs) + 2);
 
213
    } else {
 
214
#endif
 
215
        regs->ir  = get_word (m68k_getpc (regs));
 
216
        regs->irc = get_word (m68k_getpc (regs) + 2);
 
217
#ifdef CPUEMU_6
 
218
    }
 
219
#endif
 
220
}
 
221
 
 
222
unsigned long cycles_mask, cycles_val;
 
223
 
 
224
static void update_68k_cycles (void)
 
225
{
 
226
    cycles_mask = 0;
 
227
    cycles_val = currprefs.m68k_speed;
 
228
    if (currprefs.m68k_speed < 1) {
 
229
        cycles_mask = 0xFFFFFFFF;
 
230
        cycles_val = 0;
 
231
    }
 
232
}
 
233
 
 
234
void check_prefs_changed_cpu (void)
 
235
{
 
236
    if (currprefs.cpu_level != changed_prefs.cpu_level
 
237
        || currprefs.cpu_compatible != changed_prefs.cpu_compatible
 
238
        || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
 
239
 
 
240
        if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
 
241
            fill_prefetch_slow (&regs);
 
242
 
 
243
        currprefs.cpu_level = changed_prefs.cpu_level;
 
244
        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
 
245
        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
 
246
        currprefs.blitter_cycle_exact = changed_prefs.cpu_cycle_exact;
 
247
        build_cpufunctbl ();
 
248
 
 
249
        /* Force opcode handler loop to exit. We don't want it to
 
250
         * carry on running with the old opcode handler table. */
 
251
        set_special (&regs, SPCFLAG_MODE_CHANGE);
 
252
    }
 
253
    if (currprefs.m68k_speed != changed_prefs.m68k_speed) {
 
254
        currprefs.m68k_speed = changed_prefs.m68k_speed;
 
255
        reset_frame_rate_hack ();
 
256
        update_68k_cycles ();
 
257
        /* Force opcode handler loop to exit. We don't want it to
 
258
         * carry on running with cached values of cycles_mask and
 
259
         * cycles_val.
 
260
         */
 
261
        set_special (&regs, SPCFLAG_MODE_CHANGE);
 
262
    }
 
263
    if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
 
264
        currprefs.cpu_idle = changed_prefs.cpu_idle;
 
265
    }
 
266
}
 
267
 
 
268
void init_m68k (void)
 
269
{
 
270
    int i;
 
271
 
 
272
    update_68k_cycles ();
 
273
 
 
274
    for (i = 0 ; i < 256 ; i++) {
 
275
        int j;
 
276
        for (j = 0 ; j < 8 ; j++) {
 
277
                if (i & (1 << j)) break;
 
278
        }
 
279
        movem_index1[i] = j;
 
280
        movem_index2[i] = 7-j;
 
281
        movem_next[i] = i & (~(1 << j));
 
282
    }
 
283
#ifdef FPUEMU
 
284
    for (i = 0 ; i < 256 ; i++) {
 
285
        int j;
 
286
        for (j = 7 ; j >= 0 ; j--) {
 
287
                if (i & (1 << j)) break;
 
288
        }
 
289
        fpp_movem_index1[i] = 7-j;
 
290
        fpp_movem_index2[i] = j;
 
291
        fpp_movem_next[i] = i & (~(1 << j));
 
292
    }
 
293
#endif
 
294
#if COUNT_INSTRS
 
295
    {
 
296
        FILE *f = fopen (icountfilename (), "r");
 
297
        memset (instrcount, 0, sizeof instrcount);
 
298
        if (f) {
 
299
            uae_u32 opcode, count, total;
 
300
            char name[20];
 
301
            write_log ("Reading instruction count file...\n");
 
302
            fscanf (f, "Total: %lu\n", &total);
 
303
            while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
 
304
                instrcount[opcode] = count;
 
305
            }
 
306
            fclose(f);
 
307
        }
 
308
    }
 
309
#endif
 
310
    write_log ("Building CPU table for configuration: 68");
 
311
    regs.address_space_mask = 0xffffffff;
 
312
    if (currprefs.cpu_compatible > 0) {
 
313
        if (currprefs.address_space_24 && currprefs.cpu_level > 3)
 
314
            currprefs.address_space_24 = 0;
 
315
        if (currprefs.address_space_24 && currprefs.cpu_level > 1)
 
316
            write_log ("EC");
 
317
    }
 
318
    switch (currprefs.cpu_level) {
 
319
    case 1:
 
320
        write_log ("010");
 
321
        break;
 
322
    case 2:
 
323
        write_log ("020");
 
324
        break;
 
325
    case 3:
 
326
        write_log ("020/881");
 
327
        break;
 
328
    case 4:
 
329
        /* Who is going to miss the MMU anyway...? :-)  */
 
330
        write_log ("040");
 
331
        break;
 
332
    case 6:
 
333
        /* Who is going to miss the MMU anyway...? :-)  */
 
334
        write_log ("060");
 
335
        break;
 
336
    default:
 
337
        write_log ("000");
 
338
        break;
 
339
    }
 
340
    if (currprefs.cpu_cycle_exact) {
 
341
        if (currprefs.cpu_level == 0)
 
342
            write_log (" prefetch and cycle-exact");
 
343
        else
 
344
            write_log (" ~cycle-exact");
 
345
    } else if (currprefs.cpu_compatible)
 
346
        write_log (" prefetch");
 
347
    if (currprefs.address_space_24) {
 
348
        regs.address_space_mask = 0x00ffffff;
 
349
        write_log (" 24-bit addressing");
 
350
    }
 
351
    write_log ("\n");
 
352
 
 
353
    read_table68k ();
 
354
    do_merges ();
 
355
 
 
356
    write_log ("%d CPU functions\n", nr_cpuop_funcs);
 
357
 
 
358
    build_cpufunctbl ();
 
359
 
 
360
#ifdef JIT
 
361
    /* We need to check whether NATMEM settings have changed
 
362
     * before starting the CPU */
 
363
    check_prefs_changed_comp ();
 
364
#endif
 
365
 
 
366
    reset_frame_rate_hack ();
 
367
    update_68k_cycles ();
 
368
}
 
369
 
 
370
struct regstruct regs;
 
371
static uae_s32 m68kpc_offset;
 
372
 
 
373
#define get_ibyte_1(regs, o) get_byte((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o) + 1)
 
374
#define get_iword_1(regs, o) get_word((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o))
 
375
#define get_ilong_1(regs, o) get_long((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o))
 
376
 
 
377
static uae_s32 ShowEA (void *f, uae_u16 opcode, int reg, amodes mode, wordsizes size, char *buf, uae_u32 *eaddr, int safemode)
 
378
{
 
379
    uae_u16 dp;
 
380
    uae_s8 disp8;
 
381
    uae_s16 disp16;
 
382
    int r;
 
383
    uae_u32 dispreg;
 
384
    uaecptr addr = 0;
 
385
    uae_s32 offset = 0;
 
386
    char buffer[80];
 
387
 
 
388
    switch (mode){
 
389
     case Dreg:
 
390
        sprintf (buffer, "D%d", reg);
 
391
        break;
 
392
     case Areg:
 
393
        sprintf (buffer, "A%d", reg);
 
394
        break;
 
395
     case Aind:
 
396
        sprintf (buffer, "(A%d)", reg);
 
397
        addr = regs.regs[reg + 8];
 
398
        break;
 
399
     case Aipi:
 
400
        sprintf (buffer, "(A%d)+", reg);
 
401
        addr = regs.regs[reg + 8];
 
402
        break;
 
403
     case Apdi:
 
404
        sprintf (buffer, "-(A%d)", reg);
 
405
        addr = regs.regs[reg + 8];
 
406
        break;
 
407
     case Ad16:
 
408
        {
 
409
            char offtxt[80];
 
410
            disp16 = get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2;
 
411
            if (disp16 < 0)
 
412
                sprintf (offtxt, "-$%04x", -disp16);
 
413
            else
 
414
                sprintf (offtxt, "$%04x", disp16);
 
415
            addr = m68k_areg (&regs,reg) + disp16;
 
416
            sprintf (buffer, "(A%d,%s) == $%08x", reg, offtxt, (unsigned long)addr);
 
417
        }
 
418
        break;
 
419
     case Ad8r:
 
420
        dp = get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2;
 
421
        disp8 = dp & 0xFF;
 
422
        r = (dp & 0x7000) >> 12;
 
423
        dispreg = dp & 0x8000 ? m68k_areg (&regs,r) : m68k_dreg (&regs,r);
 
424
        if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
 
425
        dispreg <<= (dp >> 9) & 3;
 
426
 
 
427
        if (dp & 0x100) {
 
428
            uae_s32 outer = 0, disp = 0;
 
429
            uae_s32 base = m68k_areg (&regs,reg);
 
430
            char name[10];
 
431
            sprintf (name, "A%d, ", reg);
 
432
            if (dp & 0x80) { base = 0; name[0] = 0; }
 
433
            if (dp & 0x40) dispreg = 0;
 
434
            if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2; }
 
435
            if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (&regs, m68kpc_offset); m68kpc_offset += 4; }
 
436
            base += disp;
 
437
 
 
438
            if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2; }
 
439
            if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (&regs, m68kpc_offset); m68kpc_offset += 4; }
 
440
 
 
441
            if (!(dp & 4)) base += dispreg;
 
442
            if ((dp & 3) && !safemode) base = get_long (base);
 
443
            if (dp & 4) base += dispreg;
 
444
 
 
445
            addr = base + outer;
 
446
            sprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08x", name,
 
447
                     dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
 
448
                     1 << ((dp >> 9) & 3),
 
449
                     disp, outer, addr);
 
450
        } else {
 
451
          addr = m68k_areg (&regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
 
452
          sprintf (buffer, "(A%d, %c%d.%c*%d, $%02x) == $%08x", reg,
 
453
                   dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
 
454
                   1 << ((dp >> 9) & 3), disp8, addr);
 
455
        }
 
456
        break;
 
457
     case PC16:
 
458
        addr = m68k_getpc (&regs) + m68kpc_offset;
 
459
        disp16 = get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2;
 
460
        addr += (uae_s16)disp16;
 
461
        sprintf (buffer, "(PC,$%04x) == $%08x", disp16 & 0xffff, addr);
 
462
        break;
 
463
     case PC8r:
 
464
        addr = m68k_getpc (&regs) + m68kpc_offset;
 
465
        dp = get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2;
 
466
        disp8 = dp & 0xFF;
 
467
        r = (dp & 0x7000) >> 12;
 
468
        dispreg = dp & 0x8000 ? m68k_areg (&regs,r) : m68k_dreg (&regs,r);
 
469
        if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
 
470
        dispreg <<= (dp >> 9) & 3;
 
471
 
 
472
        if (dp & 0x100) {
 
473
            uae_s32 outer = 0,disp = 0;
 
474
            uae_s32 base = addr;
 
475
            char name[10];
 
476
            sprintf (name, "PC, ");
 
477
            if (dp & 0x80) { base = 0; name[0] = 0; }
 
478
            if (dp & 0x40) dispreg = 0;
 
479
            if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2; }
 
480
            if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (&regs, m68kpc_offset); m68kpc_offset += 4; }
 
481
            base += disp;
 
482
 
 
483
            if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset); m68kpc_offset += 2; }
 
484
            if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (&regs, m68kpc_offset); m68kpc_offset += 4; }
 
485
 
 
486
            if (!(dp & 4)) base += dispreg;
 
487
            if ((dp & 3) && !safemode) base = get_long (base);
 
488
            if (dp & 4) base += dispreg;
 
489
 
 
490
            addr = base + outer;
 
491
            sprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08x", name,
 
492
                     dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
 
493
                     1 << ((dp >> 9) & 3),
 
494
                     disp, outer, addr);
 
495
        } else {
 
496
          addr += (uae_s32)((uae_s8)disp8) + dispreg;
 
497
          sprintf (buffer, "(PC, %c%d.%c*%d, $%02x) == $%08x", dp & 0x8000 ? 'A' : 'D',
 
498
                   r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
 
499
                   disp8, addr);
 
500
        }
 
501
        break;
 
502
     case absw:
 
503
        addr = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset);
 
504
        sprintf (buffer,"$%08x", (unsigned long)addr);
 
505
        m68kpc_offset += 2;
 
506
        break;
 
507
     case absl:
 
508
        addr = get_ilong_1 (&regs, m68kpc_offset);
 
509
        sprintf (buffer,"$%0lx", (unsigned long)addr);
 
510
        m68kpc_offset += 4;
 
511
        break;
 
512
     case imm:
 
513
        switch (size){
 
514
         case sz_byte:
 
515
            sprintf (buffer, "#$%02x", (unsigned int)(get_iword_1 (&regs, m68kpc_offset) & 0xff));
 
516
            m68kpc_offset += 2;
 
517
            break;
 
518
         case sz_word:
 
519
            sprintf (buffer, "#$%04x", (unsigned int)(get_iword_1 (&regs, m68kpc_offset) & 0xffff));
 
520
            m68kpc_offset += 2;
 
521
            break;
 
522
         case sz_long:
 
523
            sprintf (buffer, "#$%08x", (unsigned int)(get_ilong_1 (&regs, m68kpc_offset) & 0xffffffff));
 
524
            m68kpc_offset += 4;
 
525
            break;
 
526
         default:
 
527
            break;
 
528
        }
 
529
        break;
 
530
     case imm0:
 
531
        offset = (uae_s32)(uae_s8)get_iword_1 (&regs, m68kpc_offset);
 
532
        m68kpc_offset += 2;
 
533
        sprintf (buffer, "#$%02x", (unsigned int)(offset & 0xff));
 
534
        break;
 
535
     case imm1:
 
536
        offset = (uae_s32)(uae_s16)get_iword_1 (&regs, m68kpc_offset);
 
537
        m68kpc_offset += 2;
 
538
        buffer[0] = 0;
 
539
        sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
 
540
        break;
 
541
     case imm2:
 
542
        offset = (uae_s32)get_ilong_1 (&regs, m68kpc_offset);
 
543
        m68kpc_offset += 4;
 
544
        sprintf (buffer, "#$%08x", (unsigned int)offset);
 
545
        break;
 
546
     case immi:
 
547
        offset = (uae_s32)(uae_s8)(reg & 0xff);
 
548
        sprintf (buffer, "#$%08x", (unsigned int)offset);
 
549
        break;
 
550
     default:
 
551
        break;
 
552
    }
 
553
    if (buf == 0)
 
554
        f_out (f, "%s", buffer);
 
555
    else
 
556
        strcat (buf, buffer);
 
557
    if (eaddr)
 
558
        *eaddr = addr;
 
559
    return offset;
 
560
}
 
561
 
 
562
 
 
563
uae_u32 REGPARAM2 get_disp_ea_020 (struct regstruct *regs, uae_u32 base, uae_u32 dp)
 
564
{
 
565
    int reg = (dp >> 12) & 15;
 
566
    uae_s32 regd = regs->regs[reg];
 
567
    if ((dp & 0x800) == 0)
 
568
        regd = (uae_s32)(uae_s16)regd;
 
569
    regd <<= (dp >> 9) & 3;
 
570
    if (dp & 0x100) {
 
571
        uae_s32 outer = 0;
 
572
        if (dp & 0x80) base = 0;
 
573
        if (dp & 0x40) regd = 0;
 
574
 
 
575
        if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16) next_iword (regs);
 
576
        if ((dp & 0x30) == 0x30) base += next_ilong (regs);
 
577
 
 
578
        if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16) next_iword (regs);
 
579
        if ((dp & 0x3) == 0x3) outer = next_ilong (regs);
 
580
 
 
581
        if ((dp & 0x4) == 0) base += regd;
 
582
        if (dp & 0x3) base = get_long (base);
 
583
        if (dp & 0x4) base += regd;
 
584
 
 
585
        return base + outer;
 
586
    } else {
 
587
        return base + (uae_s32)((uae_s8)dp) + regd;
 
588
    }
 
589
}
 
590
 
 
591
uae_u32 REGPARAM2 get_disp_ea_000 (struct regstruct *regs, uae_u32 base, uae_u32 dp)
 
592
{
 
593
    int reg = (dp >> 12) & 15;
 
594
    uae_s32 regd = regs->regs[reg];
 
595
#if 1
 
596
    if ((dp & 0x800) == 0)
 
597
        regd = (uae_s32)(uae_s16)regd;
 
598
    return base + (uae_s8)dp + regd;
 
599
#else
 
600
    /* Branch-free code... benchmark this again now that
 
601
     * things are no longer inline.  */
 
602
    uae_s32 regd16;
 
603
    uae_u32 mask;
 
604
    mask = ((dp & 0x800) >> 11) - 1;
 
605
    regd16 = (uae_s32)(uae_s16)regd;
 
606
    regd16 &= mask;
 
607
    mask = ~mask;
 
608
    base += (uae_s8)dp;
 
609
    regd &= mask;
 
610
    regd |= regd16;
 
611
    return base + regd;
 
612
#endif
 
613
}
 
614
 
 
615
void REGPARAM2 MakeSR (struct regstruct *regs)
 
616
{
 
617
#if 0
 
618
    assert((regs.t1 & 1) == regs->t1);
 
619
    assert((regs.t0 & 1) == regs->t0);
 
620
    assert((regs.s & 1) == regs->s);
 
621
    assert((regs.m & 1) == regs->m);
 
622
    assert((XFLG & 1) == XFLG);
 
623
    assert((NFLG & 1) == NFLG);
 
624
    assert((ZFLG & 1) == ZFLG);
 
625
    assert((VFLG & 1) == VFLG);
 
626
    assert((CFLG & 1) == CFLG);
 
627
#endif
 
628
    regs->sr = ((regs->t1 << 15) | (regs->t0 << 14)
 
629
               | (regs->s << 13) | (regs->m << 12) | (regs->intmask << 8)
 
630
               | (GET_XFLG(&regs->ccrflags) << 4) | (GET_NFLG(&regs->ccrflags) << 3)
 
631
               | (GET_ZFLG(&regs->ccrflags) << 2) | (GET_VFLG(&regs->ccrflags) << 1)
 
632
               |  GET_CFLG(&regs->ccrflags));
 
633
}
 
634
 
 
635
void REGPARAM2 MakeFromSR (struct regstruct *regs)
 
636
{
 
637
    int oldm = regs->m;
 
638
    int olds = regs->s;
 
639
 
 
640
    SET_XFLG (&regs->ccrflags, (regs->sr >> 4) & 1);
 
641
    SET_NFLG (&regs->ccrflags, (regs->sr >> 3) & 1);
 
642
    SET_ZFLG (&regs->ccrflags, (regs->sr >> 2) & 1);
 
643
    SET_VFLG (&regs->ccrflags, (regs->sr >> 1) & 1);
 
644
    SET_CFLG (&regs->ccrflags,  regs->sr & 1);
 
645
    if (regs->t1 == ((regs->sr >> 15) & 1) &&
 
646
        regs->t0 == ((regs->sr >> 14) & 1) &&
 
647
        regs->s  == ((regs->sr >> 13) & 1) &&
 
648
        regs->m  == ((regs->sr >> 12) & 1) &&
 
649
        regs->intmask == ((regs->sr >> 8) & 7))
 
650
            return;
 
651
    regs->t1 = (regs->sr >> 15) & 1;
 
652
    regs->t0 = (regs->sr >> 14) & 1;
 
653
    regs->s  = (regs->sr >> 13) & 1;
 
654
    regs->m  = (regs->sr >> 12) & 1;
 
655
    regs->intmask = (regs->sr >> 8) & 7;
 
656
    if (currprefs.cpu_level >= 2) {
 
657
        if (olds != regs->s) {
 
658
            if (olds) {
 
659
                if (oldm)
 
660
                    regs->msp = m68k_areg (regs, 7);
 
661
                else
 
662
                    regs->isp = m68k_areg (regs, 7);
 
663
                m68k_areg (regs, 7) = regs->usp;
 
664
            } else {
 
665
                regs->usp = m68k_areg (regs, 7);
 
666
                m68k_areg (regs, 7) = regs->m ? regs->msp : regs->isp;
 
667
            }
 
668
        } else if (olds && oldm != regs->m) {
 
669
            if (oldm) {
 
670
                regs->msp = m68k_areg (regs, 7);
 
671
                m68k_areg (regs, 7) = regs->isp;
 
672
            } else {
 
673
                regs->isp = m68k_areg (regs, 7);
 
674
                m68k_areg (regs, 7) = regs->msp;
 
675
            }
 
676
        }
 
677
    } else {
 
678
        regs->t0 = regs->m = 0;
 
679
        if (olds != regs->s) {
 
680
            if (olds) {
 
681
                regs->isp = m68k_areg (regs, 7);
 
682
                m68k_areg (regs, 7) = regs->usp;
 
683
            } else {
 
684
                regs->usp = m68k_areg (regs, 7);
 
685
                m68k_areg (regs, 7) = regs->isp;
 
686
            }
 
687
        }
 
688
    }
 
689
 
 
690
    set_special (regs, SPCFLAG_INT);
 
691
    if (regs->t1 || regs->t0)
 
692
        set_special (regs, SPCFLAG_TRACE);
 
693
    else
 
694
        /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
 
695
           SR-modifying instructions (including STOP).  */
 
696
        unset_special (regs, SPCFLAG_TRACE);
 
697
}
 
698
 
 
699
STATIC_INLINE void trace_exception (struct regstruct *regs, unsigned int nr)
 
700
{
 
701
    unset_special (regs, SPCFLAG_TRACE | SPCFLAG_DOTRACE);
 
702
    if (regs->t1 && !regs->t0) {
 
703
        /* Trace stays pending if exception is div by zero, chk,
 
704
         * trapv or trap #x
 
705
         */
 
706
        if (nr == 5 || nr == 6 || nr ==  7 || (nr >= 32 && nr <= 47))
 
707
            set_special (regs, SPCFLAG_DOTRACE);
 
708
    }
 
709
    regs->t1 = regs->t0 = regs->m = 0;
 
710
}
 
711
 
 
712
static void exception_debug (int nr)
 
713
{
 
714
#ifdef DEBUGGER
 
715
    if (!exception_debugging)
 
716
        return;
 
717
    console_out ("Exception %d, PC=%08x\n", nr, m68k_getpc (&regs));
 
718
#endif
 
719
}
 
720
 
 
721
#ifdef CPUEMU_6
 
722
 
 
723
/* cycle-exact exception handler, 68000 only */
 
724
 
 
725
STATIC_INLINE void Exception_ce (int nr, struct regstruct *regs, uaecptr oldpc)
 
726
{
 
727
    uae_u32 currpc = m68k_getpc (regs), newpc;
 
728
    int c;
 
729
    int sv = regs->s;
 
730
 
 
731
    exception_debug (nr);
 
732
    MakeSR (regs);
 
733
 
 
734
    c = 0;
 
735
    switch (nr)
 
736
    {
 
737
        case 2: /* bus */
 
738
        case 3: /* address */
 
739
        c = 6;
 
740
        break;
 
741
        case 4: /* illegal instruction */
 
742
        c = 6;
 
743
        break;
 
744
        case 5: /* divide by zero */
 
745
        c = 10;
 
746
        break;
 
747
        case 6: /* chk */
 
748
        c = 12;
 
749
        break;
 
750
        case 7: /* trapv */
 
751
        c = 6;
 
752
        break;
 
753
        case 8: /* privilege */
 
754
        c = 6;
 
755
        break;
 
756
        case 9: /* trace */
 
757
        c = 6;
 
758
        break;
 
759
        case 25: /* interrupts */
 
760
        case 26:
 
761
        case 27:
 
762
        case 28:
 
763
        case 29:
 
764
        case 30:
 
765
        case 31:
 
766
        c = 12;
 
767
        break;
 
768
        case 32: /* traps */
 
769
        case 33:
 
770
        case 34:
 
771
        case 35:
 
772
        case 36:
 
773
        case 37:
 
774
        case 38:
 
775
        case 39:
 
776
        case 40:
 
777
        case 41:
 
778
        case 42:
 
779
        case 43:
 
780
        case 44:
 
781
        case 45:
 
782
        case 46:
 
783
        case 47:
 
784
        c = 6;
 
785
        break;
 
786
    }
 
787
    /* some delays are interleaved with stack pushes, not bothered yet..
 
788
     */
 
789
    if (c)
 
790
        do_cycles (c * CYCLE_UNIT / 2);
 
791
 
 
792
    if (!regs->s) {
 
793
        regs->usp = m68k_areg (regs, 7);
 
794
        m68k_areg (regs, 7) = regs->isp;
 
795
        regs->s = 1;
 
796
    }
 
797
    if (nr == 2 || nr == 3) { /* 2=bus error,3=address error */
 
798
        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
 
799
        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
 
800
        m68k_areg (regs, 7) -= 14;
 
801
        /* fixme: bit3=I/N */
 
802
        put_word_ce (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
 
803
        put_word_ce (m68k_areg (regs, 7) + 8,  regs->sr);
 
804
        put_word_ce (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
 
805
        put_word_ce (m68k_areg (regs, 7) + 6,  last_op_for_exception_3);
 
806
        put_word_ce (m68k_areg (regs, 7) + 4,  last_fault_for_exception_3);
 
807
        put_word_ce (m68k_areg (regs, 7) + 0,  mode);
 
808
        put_word_ce (m68k_areg (regs, 7) + 2,  last_fault_for_exception_3 >> 16);
 
809
#if 0
 
810
        write_log ("Exception %d at %08x -> %08x!\n", nr, currpc, get_long (4 * nr));
 
811
#endif
 
812
        goto kludge_me_do;
 
813
    }
 
814
    m68k_areg (regs, 7) -= 6;
 
815
    put_word_ce (m68k_areg (regs, 7) + 4, currpc);
 
816
    put_word_ce (m68k_areg (regs, 7) + 0, regs->sr);
 
817
    put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16);
 
818
kludge_me_do:
 
819
    newpc = get_word_ce (4 * nr) << 16;
 
820
    newpc |= get_word_ce (4 * nr + 2);
 
821
    if (newpc & 1) {
 
822
        if (nr == 2 || nr == 3)
 
823
            uae_reset (1); /* there is nothing else we can do.. */
 
824
        else
 
825
            exception3 (regs->ir, m68k_getpc (regs), newpc);
 
826
        return;
 
827
    }
 
828
    m68k_setpc (regs, newpc);
 
829
    fill_prefetch_slow (regs);
 
830
    set_special (regs, SPCFLAG_END_COMPILE);
 
831
    trace_exception (regs, nr);
 
832
}
 
833
#endif
 
834
 
 
835
STATIC_INLINE void Exception_normal (int nr, struct regstruct *regs, uaecptr oldpc)
 
836
{
 
837
    uae_u32 currpc = m68k_getpc (regs), newpc;
 
838
    int sv = regs->s;
 
839
 
 
840
    exception_debug (nr);
 
841
    MakeSR (regs);
 
842
 
 
843
    if (!regs->s) {
 
844
        regs->usp = m68k_areg (regs, 7);
 
845
        if (currprefs.cpu_level >= 2)
 
846
            m68k_areg (regs, 7) = regs->m ? regs->msp : regs->isp;
 
847
        else
 
848
            m68k_areg (regs, 7) = regs->isp;
 
849
        regs->s = 1;
 
850
    }
 
851
    if (currprefs.cpu_level > 0) {
 
852
        if (nr == 2 || nr == 3) {
 
853
            int i;
 
854
            if (currprefs.cpu_level >= 4) { /* 68040 */
 
855
                if (nr == 2) {
 
856
                    for (i = 0 ; i < 18 ; i++) {
 
857
                        m68k_areg (regs, 7) -= 2;
 
858
                        put_word (m68k_areg (regs, 7), 0);
 
859
                    }
 
860
                    m68k_areg (regs, 7) -= 4;
 
861
                    put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
 
862
                    m68k_areg (regs, 7) -= 2;
 
863
                    put_word (m68k_areg (regs, 7), 0);
 
864
                    m68k_areg (regs, 7) -= 2;
 
865
                    put_word (m68k_areg (regs, 7), 0);
 
866
                    m68k_areg (regs, 7) -= 2;
 
867
                    put_word (m68k_areg (regs, 7), 0);
 
868
                    m68k_areg (regs, 7) -= 2;
 
869
                    put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
 
870
                    m68k_areg (regs, 7) -= 4;
 
871
                    put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
 
872
                    m68k_areg (regs, 7) -= 2;
 
873
                    put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
 
874
                } else {
 
875
                    m68k_areg (regs, 7) -= 4;
 
876
                    put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
 
877
                    m68k_areg (regs, 7) -= 2;
 
878
                    put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
 
879
                }
 
880
            } else {
 
881
                uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
 
882
                ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
 
883
                ssw |= 0x20;
 
884
                for (i = 0 ; i < 36; i++) {
 
885
                    m68k_areg (regs, 7) -= 2;
 
886
                    put_word (m68k_areg (regs, 7), 0);
 
887
                }
 
888
                m68k_areg (regs, 7) -= 4;
 
889
                put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
 
890
                m68k_areg (regs, 7) -= 2;
 
891
                put_word (m68k_areg (regs, 7), 0);
 
892
                m68k_areg (regs, 7) -= 2;
 
893
                put_word (m68k_areg (regs, 7), 0);
 
894
                m68k_areg (regs, 7) -= 2;
 
895
                put_word (m68k_areg (regs, 7), 0);
 
896
                m68k_areg (regs, 7) -= 2;
 
897
                put_word (m68k_areg (regs, 7), ssw);
 
898
                m68k_areg (regs, 7) -= 2;
 
899
                put_word (m68k_areg (regs, 7), 0xb000 + nr * 4);
 
900
            }
 
901
#if 0
 
902
            write_log ("Exception %d (%08x) at %08x -> %08x!\n", nr, oldpc, currpc, get_long (regs->vbr + 4*nr));
 
903
#endif
 
904
        } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
 
905
            m68k_areg (regs, 7) -= 4;
 
906
            put_long (m68k_areg (regs, 7), oldpc);
 
907
            m68k_areg (regs, 7) -= 2;
 
908
            put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
 
909
        } else if (regs->m && nr >= 24 && nr < 32) { /* M + Interrupt */
 
910
            m68k_areg (regs, 7) -= 2;
 
911
            put_word  (m68k_areg (regs, 7), nr * 4);
 
912
            m68k_areg (regs, 7) -= 4;
 
913
            put_long  (m68k_areg (regs, 7), currpc);
 
914
            m68k_areg (regs, 7) -= 2;
 
915
            put_word  (m68k_areg (regs, 7), regs->sr);
 
916
            regs->sr |= (1 << 13);
 
917
            regs->msp = m68k_areg (regs, 7);
 
918
            m68k_areg (regs, 7) = regs->isp;
 
919
            m68k_areg (regs, 7) -= 2;
 
920
            put_word  (m68k_areg (regs, 7), 0x1000 + nr * 4);
 
921
        } else {
 
922
            m68k_areg (regs, 7) -= 2;
 
923
            put_word (m68k_areg (regs, 7), nr * 4);
 
924
        }
 
925
    } else if (nr == 2 || nr == 3) {
 
926
        uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
 
927
        mode |= last_writeaccess_for_exception_3 ? 0 : 16;
 
928
        m68k_areg (regs, 7) -= 14;
 
929
        /* fixme: bit3=I/N */
 
930
        put_word (m68k_areg (regs, 7) + 0,  mode);
 
931
        put_long (m68k_areg (regs, 7) + 2,  last_fault_for_exception_3);
 
932
        put_word (m68k_areg (regs, 7) + 6,  last_op_for_exception_3);
 
933
        put_word (m68k_areg (regs, 7) + 8,  regs->sr);
 
934
        put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
 
935
#if 0
 
936
        write_log ("Exception %d (%08x) at %08x -> %08x!\n", nr, oldpc, currpc, get_long (regs->vbr + 4*nr));
 
937
#endif
 
938
        goto kludge_me_do;
 
939
    }
 
940
    m68k_areg (regs, 7) -= 4;
 
941
    put_long  (m68k_areg (regs, 7), currpc);
 
942
    m68k_areg (regs, 7) -= 2;
 
943
    put_word  (m68k_areg (regs, 7), regs->sr);
 
944
kludge_me_do:
 
945
    newpc = get_long (regs->vbr + 4 * nr);
 
946
    if (newpc & 1) {
 
947
        if (nr == 2 || nr == 3)
 
948
            uae_reset (1); /* there is nothing else we can do.. */
 
949
        else
 
950
            exception3 (regs->ir, m68k_getpc (regs), newpc);
 
951
        return;
 
952
    }
 
953
    m68k_setpc (regs, newpc);
 
954
    set_special (regs, SPCFLAG_END_COMPILE);
 
955
    fill_prefetch_slow (regs);
 
956
    trace_exception (regs, nr);
 
957
}
 
958
 
 
959
void REGPARAM2 Exception (int nr, struct regstruct *regs, uaecptr oldpc)
 
960
{
 
961
#if 0
 
962
    if (1 || nr < 24)
 
963
        write_log ("exception %2d %08x %08x (%04x %04x)\n",
 
964
            nr, oldpc, m68k_getpc (regs), intena, intreq);
 
965
#endif
 
966
#ifdef CPUEMU_6
 
967
    if (currprefs.cpu_cycle_exact && currprefs.cpu_level == 0)
 
968
        Exception_ce (nr, regs, oldpc);
 
969
    else
 
970
#endif
 
971
        Exception_normal (nr, regs, oldpc);
 
972
}
 
973
 
 
974
STATIC_INLINE void service_interrupt (unsigned int level, struct regstruct *regs)
 
975
{
 
976
    if (level > regs->intmask) {
 
977
 
 
978
        regs->stopped = 0;
 
979
        unset_special (regs, SPCFLAG_STOP);
 
980
 
 
981
        Exception (level + 24, regs, 0);
 
982
 
 
983
        regs->intmask = level;
 
984
    }
 
985
}
 
986
 
 
987
/*
 
988
 * Directly cause an interrupt to occur.
 
989
 *
 
990
 * This probably ain't a great idea, because this could allow an interrupt
 
991
 * to be forced before an opcode is completed and the PC updated.
 
992
 */
 
993
void Interrupt (unsigned int level)
 
994
{
 
995
    assert (level < 8);
 
996
    service_interrupt (level, &regs);
 
997
}
 
998
 
 
999
static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp, buscr, pcr;
 
1000
 
 
1001
#ifndef CPUEMU_68000_ONLY
 
1002
 
 
1003
static int movec_illg (int regno)
 
1004
{
 
1005
    int regno2 = regno & 0x7ff;
 
1006
    if (currprefs.cpu_level == 1) { /* 68010 */
 
1007
        if (regno2 < 2)
 
1008
            return 0;
 
1009
        return 1;
 
1010
    }
 
1011
    if (currprefs.cpu_level == 2 || currprefs.cpu_level == 3) { /* 68020 */
 
1012
        if (regno == 3) return 1; /* 68040 only */
 
1013
        /* 4 is >=68040, but 0x804 is in 68020 */
 
1014
        if (regno2 < 4 || regno == 0x804)
 
1015
            return 0;
 
1016
        return 1;
 
1017
    }
 
1018
    if (currprefs.cpu_level >= 4) { /* 68040 */
 
1019
        if (regno == 0x802) return 1; /* 68020 only */
 
1020
        if (regno2 < 8) return 0;
 
1021
        if (currprefs.cpu_level == 6 && regno2 == 8) /* 68060 only */
 
1022
            return 0;
 
1023
        return 1;
 
1024
    }
 
1025
    return 1;
 
1026
}
 
1027
 
 
1028
int m68k_move2c (int regno, uae_u32 *regp)
 
1029
{
 
1030
//    write_log ("move2c %04x <- %08x\n", regno, *regp);
 
1031
    if (movec_illg (regno)) {
 
1032
        op_illg (0x4E7B, &regs);
 
1033
        return 0;
 
1034
    } else {
 
1035
        switch (regno) {
 
1036
        case 0: regs.sfc = *regp & 7; break;
 
1037
        case 1: regs.dfc = *regp & 7; break;
 
1038
        case 2:
 
1039
            cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : (currprefs.cpu_level == 4 ? 0x80008000 : 0xf8800e00));
 
1040
#ifdef JIT
 
1041
            if (currprefs.cpu_level < 4) {
 
1042
                set_cache_state (cacr & 1);
 
1043
                if (*regp & 0x08) {
 
1044
                    flush_icache (1);
 
1045
                }
 
1046
            } else {
 
1047
                set_cache_state ((cacr & 0x8000) || 0);
 
1048
                if (*regp & 0x08) {   /* Just to be on the safe side */
 
1049
                    flush_icache (2);
 
1050
                }
 
1051
            }
 
1052
#endif
 
1053
            break;
 
1054
        case 3: tc = *regp & 0xc000; break;
 
1055
            /* Mask out fields that should be zero.  */
 
1056
        case 4: itt0 = *regp & 0xffffe364; break;
 
1057
        case 5: itt1 = *regp & 0xffffe364; break;
 
1058
        case 6: dtt0 = *regp & 0xffffe364; break;
 
1059
        case 7: dtt1 = *regp & 0xffffe364; break;
 
1060
        case 8: buscr = *regp & 0xf0000000; break;
 
1061
 
 
1062
        case 0x800: regs.usp = *regp; break;
 
1063
        case 0x801: regs.vbr = *regp; break;
 
1064
        case 0x802: caar = *regp & 0xfc; break;
 
1065
        case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (&regs, 7) = regs.msp; break;
 
1066
        case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (&regs, 7) = regs.isp; break;
 
1067
        case 0x805: mmusr = *regp; break;
 
1068
        case 0x806: urp = *regp; break;
 
1069
        case 0x807: srp = *regp; break;
 
1070
        case 0x808: pcr = *regp & (0x40 | 2 | 1); break;
 
1071
        default:
 
1072
            op_illg (0x4E7B, &regs);
 
1073
            return 0;
 
1074
        }
 
1075
    }
 
1076
    return 1;
 
1077
}
 
1078
 
 
1079
int m68k_movec2 (int regno, uae_u32 *regp)
 
1080
{
 
1081
//    write_log ("movec2 %04x ", regno);
 
1082
    if (movec_illg (regno)) {
 
1083
        op_illg (0x4E7A, &regs);
 
1084
        return 0;
 
1085
    } else {
 
1086
        switch (regno) {
 
1087
        case 0: *regp = regs.sfc; break;
 
1088
        case 1: *regp = regs.dfc; break;
 
1089
        case 2: *regp = cacr; break;
 
1090
        case 3: *regp = tc; break;
 
1091
        case 4: *regp = itt0; break;
 
1092
        case 5: *regp = itt1; break;
 
1093
        case 6: *regp = dtt0; break;
 
1094
        case 7: *regp = dtt1; break;
 
1095
        case 8: *regp = buscr; break;
 
1096
 
 
1097
        case 0x800: *regp = regs.usp; break;
 
1098
        case 0x801: *regp = regs.vbr; break;
 
1099
        case 0x802: *regp = caar; break;
 
1100
        case 0x803: *regp = regs.m == 1 ? m68k_areg (&regs, 7) : regs.msp; break;
 
1101
        case 0x804: *regp = regs.m == 0 ? m68k_areg (&regs, 7) : regs.isp; break;
 
1102
        case 0x805: *regp = mmusr; break;
 
1103
        case 0x806: *regp = urp; break;
 
1104
        case 0x807: *regp = srp; break;
 
1105
        case 0x808: *regp = 0x04300100 | pcr; break;
 
1106
 
 
1107
        default:
 
1108
            op_illg (0x4E7A, &regs);
 
1109
            return 0;
 
1110
        }
 
1111
    }
 
1112
//    write_log ("-> %08x\n", *regp);
 
1113
    return 1;
 
1114
}
 
1115
 
 
1116
STATIC_INLINE int
 
1117
div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
 
1118
{
 
1119
        uae_u32 q = 0, cbit = 0;
 
1120
        int i;
 
1121
 
 
1122
        if (div <= src_hi) {
 
1123
            return 1;
 
1124
        }
 
1125
        for (i = 0 ; i < 32 ; i++) {
 
1126
                cbit = src_hi & 0x80000000ul;
 
1127
                src_hi <<= 1;
 
1128
                if (src_lo & 0x80000000ul) src_hi++;
 
1129
                src_lo <<= 1;
 
1130
                q = q << 1;
 
1131
                if (cbit || div <= src_hi) {
 
1132
                        q |= 1;
 
1133
                        src_hi -= div;
 
1134
                }
 
1135
        }
 
1136
        *quot = q;
 
1137
        *rem = src_hi;
 
1138
        return 0;
 
1139
}
 
1140
 
 
1141
void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
 
1142
{
 
1143
#if defined(uae_s64)
 
1144
    if (src == 0) {
 
1145
        Exception (5, &regs, oldpc);
 
1146
        return;
 
1147
    }
 
1148
    if (extra & 0x800) {
 
1149
        /* signed variant */
 
1150
        uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1151
        uae_s64 quot, rem;
 
1152
 
 
1153
        if (extra & 0x400) {
 
1154
            a &= 0xffffffffu;
 
1155
            a |= (uae_s64)m68k_dreg (&regs, extra & 7) << 32;
 
1156
        }
 
1157
        rem = a % (uae_s64)(uae_s32)src;
 
1158
        quot = a / (uae_s64)(uae_s32)src;
 
1159
        if ((quot & UVAL64(0xffffffff80000000)) != 0
 
1160
            && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
 
1161
        {
 
1162
            SET_VFLG (&regs.ccrflags, 1);
 
1163
            SET_NFLG (&regs.ccrflags, 1);
 
1164
            SET_CFLG (&regs.ccrflags, 0);
 
1165
        } else {
 
1166
            if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
 
1167
            SET_VFLG (&regs.ccrflags, 0);
 
1168
            SET_CFLG (&regs.ccrflags, 0);
 
1169
            SET_ZFLG (&regs.ccrflags, ((uae_s32)quot) == 0);
 
1170
            SET_NFLG (&regs.ccrflags, ((uae_s32)quot) < 0);
 
1171
            m68k_dreg (&regs, extra & 7) = (uae_u32)rem;
 
1172
            m68k_dreg (&regs, (extra >> 12) & 7) = (uae_u32)quot;
 
1173
        }
 
1174
    } else {
 
1175
        /* unsigned */
 
1176
        uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1177
        uae_u64 quot, rem;
 
1178
 
 
1179
        if (extra & 0x400) {
 
1180
            a &= 0xffffffffu;
 
1181
            a |= (uae_u64)m68k_dreg (&regs, extra & 7) << 32;
 
1182
        }
 
1183
        rem = a % (uae_u64)src;
 
1184
        quot = a / (uae_u64)src;
 
1185
        if (quot > 0xffffffffu) {
 
1186
            SET_VFLG (&regs.ccrflags, 1);
 
1187
            SET_NFLG (&regs.ccrflags, 1);
 
1188
            SET_CFLG (&regs.ccrflags, 0);
 
1189
        } else {
 
1190
            SET_VFLG (&regs.ccrflags, 0);
 
1191
            SET_CFLG (&regs.ccrflags, 0);
 
1192
            SET_ZFLG (&regs.ccrflags, ((uae_s32)quot) == 0);
 
1193
            SET_NFLG (&regs.ccrflags, ((uae_s32)quot) < 0);
 
1194
            m68k_dreg (&regs, extra & 7) = (uae_u32)rem;
 
1195
            m68k_dreg (&regs, (extra >> 12) & 7) = (uae_u32)quot;
 
1196
        }
 
1197
    }
 
1198
#else
 
1199
    if (src == 0) {
 
1200
        Exception (5, &regs, oldpc);
 
1201
        return;
 
1202
    }
 
1203
    if (extra & 0x800) {
 
1204
        /* signed variant */
 
1205
        uae_s32 lo = (uae_s32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1206
        uae_s32 hi = lo < 0 ? -1 : 0;
 
1207
        uae_s32 save_high;
 
1208
        uae_u32 quot, rem;
 
1209
        uae_u32 sign;
 
1210
 
 
1211
        if (extra & 0x400) {
 
1212
            hi = (uae_s32)m68k_dreg (&regs, extra & 7);
 
1213
        }
 
1214
        save_high = hi;
 
1215
        sign = (hi ^ src);
 
1216
        if (hi < 0) {
 
1217
            hi = ~hi;
 
1218
            lo = -lo;
 
1219
            if (lo == 0) hi++;
 
1220
        }
 
1221
        if ((uae_s32)src < 0) src = -src;
 
1222
        if (div_unsigned(hi, lo, src, &quot, &rem) ||
 
1223
            (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
 
1224
            SET_VFLG (&regs.ccrflags, 1);
 
1225
            SET_NFLG (&regs.ccrflags, 1);
 
1226
            SET_CFLG (&regs.ccrflags, 0);
 
1227
        } else {
 
1228
            if (sign & 0x80000000) quot = -quot;
 
1229
            if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
 
1230
            SET_VFLG (&regs.ccrflags, 0);
 
1231
            SET_CFLG (&regs.ccrflags, 0);
 
1232
            SET_ZFLG (&regs.ccrflags, ((uae_s32)quot) == 0);
 
1233
            SET_NFLG (&regs.ccrflags, ((uae_s32)quot) < 0);
 
1234
            m68k_dreg (&regs, extra & 7) = rem;
 
1235
            m68k_dreg (&regs, (extra >> 12) & 7) = quot;
 
1236
        }
 
1237
    } else {
 
1238
        /* unsigned */
 
1239
        uae_u32 lo = (uae_u32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1240
        uae_u32 hi = 0;
 
1241
        uae_u32 quot, rem;
 
1242
 
 
1243
        if (extra & 0x400) {
 
1244
            hi = (uae_u32)m68k_dreg (&regs, extra & 7);
 
1245
        }
 
1246
        if (div_unsigned(hi, lo, src, &quot, &rem)) {
 
1247
            SET_VFLG (&regs.ccrflags, 1);
 
1248
            SET_NFLG (&regs.ccrflags, 1);
 
1249
            SET_CFLG (&regs.ccrflags, 0);
 
1250
        } else {
 
1251
            SET_VFLG (&regs.ccrflags, 0);
 
1252
            SET_CFLG (&regs.ccrflags, 0);
 
1253
            SET_ZFLG (&regs.ccrflags, ((uae_s32)quot) == 0);
 
1254
            SET_NFLG (&regs.ccrflags, ((uae_s32)quot) < 0);
 
1255
            m68k_dreg (&regs, extra & 7) = rem;
 
1256
            m68k_dreg (&regs, (extra >> 12) & 7) = quot;
 
1257
        }
 
1258
    }
 
1259
#endif
 
1260
}
 
1261
 
 
1262
STATIC_INLINE void
 
1263
mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
 
1264
{
 
1265
        uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
 
1266
        uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
 
1267
        uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
 
1268
        uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
 
1269
        uae_u32 lo;
 
1270
 
 
1271
        lo = r0 + ((r1 << 16) & 0xffff0000ul);
 
1272
        if (lo < r0) r3++;
 
1273
        r0 = lo;
 
1274
        lo = r0 + ((r2 << 16) & 0xffff0000ul);
 
1275
        if (lo < r0) r3++;
 
1276
        r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
 
1277
        *dst_lo = lo;
 
1278
        *dst_hi = r3;
 
1279
}
 
1280
 
 
1281
void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
 
1282
{
 
1283
#if defined(uae_s64)
 
1284
    if (extra & 0x800) {
 
1285
        /* signed variant */
 
1286
        uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1287
 
 
1288
        a *= (uae_s64)(uae_s32)src;
 
1289
        SET_VFLG (&regs.ccrflags, 0);
 
1290
        SET_CFLG (&regs.ccrflags, 0);
 
1291
        SET_ZFLG (&regs.ccrflags, a == 0);
 
1292
        SET_NFLG (&regs.ccrflags, a < 0);
 
1293
        if (extra & 0x400)
 
1294
            m68k_dreg (&regs, extra & 7) = (uae_u32)(a >> 32);
 
1295
        else if ((a & UVAL64(0xffffffff80000000)) != 0
 
1296
                 && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
 
1297
        {
 
1298
            SET_VFLG (&regs.ccrflags, 1);
 
1299
        }
 
1300
        m68k_dreg (&regs, (extra >> 12) & 7) = (uae_u32)a;
 
1301
    } else {
 
1302
        /* unsigned */
 
1303
        uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1304
 
 
1305
        a *= (uae_u64)src;
 
1306
        SET_VFLG (&regs.ccrflags, 0);
 
1307
        SET_CFLG (&regs.ccrflags, 0);
 
1308
        SET_ZFLG (&regs.ccrflags, a == 0);
 
1309
        SET_NFLG (&regs.ccrflags, ((uae_s64)a) < 0);
 
1310
        if (extra & 0x400)
 
1311
            m68k_dreg (&regs, extra & 7) = (uae_u32)(a >> 32);
 
1312
        else if ((a & UVAL64(0xffffffff00000000)) != 0) {
 
1313
            SET_VFLG (&regs.ccrflags, 1);
 
1314
        }
 
1315
        m68k_dreg (&regs, (extra >> 12) & 7) = (uae_u32)a;
 
1316
    }
 
1317
#else
 
1318
    if (extra & 0x800) {
 
1319
        /* signed variant */
 
1320
        uae_s32 src1,src2;
 
1321
        uae_u32 dst_lo,dst_hi;
 
1322
        uae_u32 sign;
 
1323
 
 
1324
        src1 = (uae_s32)src;
 
1325
        src2 = (uae_s32)m68k_dreg (&regs, (extra >> 12) & 7);
 
1326
        sign = (src1 ^ src2);
 
1327
        if (src1 < 0) src1 = -src1;
 
1328
        if (src2 < 0) src2 = -src2;
 
1329
        mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
 
1330
        if (sign & 0x80000000) {
 
1331
                dst_hi = ~dst_hi;
 
1332
                dst_lo = -dst_lo;
 
1333
                if (dst_lo == 0) dst_hi++;
 
1334
        }
 
1335
        SET_VFLG (&regs.ccrflags, 0);
 
1336
        SET_CFLG (&regs.ccrflags, 0);
 
1337
        SET_ZFLG (&regs.ccrflags, dst_hi == 0 && dst_lo == 0);
 
1338
        SET_NFLG (&regs.ccrflags, ((uae_s32)dst_hi) < 0);
 
1339
        if (extra & 0x400)
 
1340
            m68k_dreg (&regs, extra & 7) = dst_hi;
 
1341
        else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
 
1342
                 && ((dst_hi & 0xffffffff) != 0xffffffff
 
1343
                     || (dst_lo & 0x80000000) != 0x80000000))
 
1344
        {
 
1345
            SET_VFLG (&regs.ccrflags, 1);
 
1346
        }
 
1347
        m68k_dreg (&regs, (extra >> 12) & 7) = dst_lo;
 
1348
    } else {
 
1349
        /* unsigned */
 
1350
        uae_u32 dst_lo,dst_hi;
 
1351
 
 
1352
        mul_unsigned(src,(uae_u32)m68k_dreg (&regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
 
1353
 
 
1354
        SET_VFLG (&regs.ccrflags, 0);
 
1355
        SET_CFLG (&regs.ccrflags, 0);
 
1356
        SET_ZFLG (&regs.ccrflags, dst_hi == 0 && dst_lo == 0);
 
1357
        SET_NFLG (&regs.ccrflags, ((uae_s32)dst_hi) < 0);
 
1358
        if (extra & 0x400)
 
1359
            m68k_dreg (&regs, extra & 7) = dst_hi;
 
1360
        else if (dst_hi != 0) {
 
1361
            SET_VFLG (&regs.ccrflags, 1);
 
1362
        }
 
1363
        m68k_dreg (&regs, (extra >> 12) & 7) = dst_lo;
 
1364
    }
 
1365
#endif
 
1366
}
 
1367
 
 
1368
#endif
 
1369
 
 
1370
 
 
1371
void m68k_reset (void)
 
1372
{
 
1373
    regs.kick_mask = 0x00F80000;
 
1374
    regs.spcflags = 0;
 
1375
 
 
1376
#ifdef SAVESTATE
 
1377
    if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) {
 
1378
        m68k_setpc (&regs, regs.pc);
 
1379
        /* MakeFromSR() must not swap stack pointer */
 
1380
        regs.s = (regs.sr >> 13) & 1;
 
1381
        MakeFromSR (&regs);
 
1382
        /* set stack pointer */
 
1383
        if (regs.s)
 
1384
            m68k_areg (&regs, 7) = regs.isp;
 
1385
        else
 
1386
            m68k_areg (&regs, 7) = regs.usp;
 
1387
        return;
 
1388
    }
 
1389
#endif
 
1390
 
 
1391
    m68k_areg  (&regs, 7) = get_long (0x00f80000);
 
1392
    m68k_setpc (&regs, get_long (0x00f80004));
 
1393
    regs.s = 1;
 
1394
    regs.m = 0;
 
1395
    regs.stopped = 0;
 
1396
    regs.t1 = 0;
 
1397
    regs.t0 = 0;
 
1398
    SET_ZFLG (&regs.ccrflags, 0);
 
1399
    SET_XFLG (&regs.ccrflags, 0);
 
1400
    SET_CFLG (&regs.ccrflags, 0);
 
1401
    SET_VFLG (&regs.ccrflags, 0);
 
1402
    SET_NFLG (&regs.ccrflags, 0);
 
1403
    regs.intmask = 7;
 
1404
    regs.vbr = regs.sfc = regs.dfc = 0;
 
1405
#ifdef FPUEMU
 
1406
    regs.fpcr = regs.fpsr = regs.fpiar = 0;
 
1407
    regs.fp_result=1;
 
1408
    regs.irc = 0xffff;
 
1409
#endif
 
1410
    fill_prefetch_slow (&regs);
 
1411
 
 
1412
    warned_cpu68020 = 0;
 
1413
}
 
1414
 
 
1415
STATIC_INLINE int in_rom (uaecptr pc)
 
1416
{
 
1417
    return (munge24 (pc) & 0xFFF80000) == 0xF80000;
 
1418
}
 
1419
 
 
1420
STATIC_INLINE int in_rtarea (uaecptr pc)
 
1421
{
 
1422
    return (munge24 (pc) & 0xFFFF0000) == RTAREA_BASE;
 
1423
}
 
1424
 
 
1425
unsigned long REGPARAM2 op_illg (uae_u32 opcode, struct regstruct *regs)
 
1426
{
 
1427
    uaecptr pc = m68k_getpc (regs);
 
1428
    static int warned;
 
1429
    int inrom = in_rom (pc);
 
1430
    int inrt = in_rtarea (pc);
 
1431
 
 
1432
    if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
 
1433
        m68k_dreg  (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
 
1434
        m68k_incpc (regs, 2);
 
1435
        fill_prefetch_slow (regs);
 
1436
        return 4;
 
1437
    }
 
1438
 
 
1439
    if (opcode == 0x4E7B && get_long (0x10) == 0 && inrom && !warned_cpu68020) {
 
1440
        gui_message ("Your Kickstart requires a 68020 CPU");
 
1441
        warned_cpu68020 = 1;
 
1442
        uae_restart (-1, NULL);
 
1443
    }
 
1444
 
 
1445
#ifdef AUTOCONFIG
 
1446
    if (opcode == 0xFF0D) {
 
1447
        if (inrom) {
 
1448
            /* This is from the dummy Kickstart replacement */
 
1449
            uae_u16 arg = get_iword (regs, 2);
 
1450
            m68k_incpc (regs, 4);
 
1451
            ersatz_perform (arg);
 
1452
            fill_prefetch_slow (regs);
 
1453
            return 4;
 
1454
        } else if (inrt) {
 
1455
            /* User-mode STOP replacement */
 
1456
            m68k_setstopped (regs, 1);
 
1457
            return 4;
 
1458
        }
 
1459
    }
 
1460
 
 
1461
    if ((opcode & 0xF000) == 0xA000 && inrt) {
 
1462
        /* Calltrap. */
 
1463
        m68k_incpc (regs, 2);
 
1464
        m68k_handle_trap (opcode & 0xFFF, regs);
 
1465
        fill_prefetch_slow (regs);
 
1466
        return 4;
 
1467
    }
 
1468
#endif
 
1469
 
 
1470
    if ((opcode & 0xF000) == 0xF000) {
 
1471
        if (warned < 20) {
 
1472
            write_log ("B-Trap %04x at %08x (%p)\n", opcode, m68k_getpc (regs) + m68kpc_offset, regs->pc_p);
 
1473
            warned++;
 
1474
        }
 
1475
        Exception (0xB, regs, 0);
 
1476
        return 4;
 
1477
    }
 
1478
    if ((opcode & 0xF000) == 0xA000) {
 
1479
#ifdef AUTOCONFIG
 
1480
        if (inrt) {
 
1481
            /* Calltrap. */
 
1482
            m68k_handle_trap (opcode & 0xFFF, regs);
 
1483
        }
 
1484
#endif
 
1485
        Exception (0xA, regs, 0);
 
1486
        return 4;
 
1487
    }
 
1488
    if (warned < 20) {
 
1489
        write_log ("Illegal instruction: %04x at %08x -> %08x\n", opcode, pc, get_long (regs->vbr + 0x10));
 
1490
        warned++;
 
1491
    }
 
1492
 
 
1493
    Exception (4, regs, 0);
 
1494
    return 4;
 
1495
}
 
1496
 
 
1497
#ifdef CPUEMU_0
 
1498
 
 
1499
void mmu_op(uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
 
1500
{
 
1501
    if ((opcode & 0xFE0) == 0x0500) {
 
1502
        /* PFLUSH */
 
1503
        mmusr = 0;
 
1504
        write_log ("PFLUSH @ %08x\n", m68k_getpc (regs));
 
1505
    } else if ((opcode & 0x0FD8) == 0x548) {
 
1506
        /* PTEST */
 
1507
        write_log ("PTEST @ %08x\n", m68k_getpc (regs));
 
1508
    } else
 
1509
        op_illg (opcode, regs);
 
1510
}
 
1511
 
 
1512
#endif
 
1513
 
 
1514
static uaecptr last_trace_ad = 0;
 
1515
 
 
1516
static NOINLINE void do_trace (struct regstruct *regs)
 
1517
{
 
1518
    if (regs->t0 && currprefs.cpu_level >= 2) {
 
1519
        uae_u16 opcode;
 
1520
        /* should also include TRAP, CHK, SR modification FPcc */
 
1521
        /* probably never used so why bother */
 
1522
        /* We can afford this to be inefficient... */
 
1523
        m68k_setpc (regs, m68k_getpc (regs));
 
1524
        fill_prefetch_slow (regs);
 
1525
        opcode = get_word (regs->pc);
 
1526
        if (   opcode == 0x4e72                 /* RTE */
 
1527
            || opcode == 0x4e74                 /* RTD */
 
1528
            || opcode == 0x4e75                 /* RTS */
 
1529
            || opcode == 0x4e77                 /* RTR */
 
1530
            || opcode == 0x4e76                 /* TRAPV */
 
1531
            || (opcode & 0xffc0) == 0x4e80      /* JSR */
 
1532
            || (opcode & 0xffc0) == 0x4ec0      /* JMP */
 
1533
            || (opcode & 0xff00) == 0x6100      /* BSR */
 
1534
            || ((opcode & 0xf000) == 0x6000     /* Bcc */
 
1535
                && cctrue (&regs->ccrflags, (opcode >> 8) & 0xf))
 
1536
            || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
 
1537
                && !cctrue (&regs->ccrflags, (opcode >> 8) & 0xf)
 
1538
                && (uae_s16) m68k_dreg (regs, opcode & 7) != 0))
 
1539
        {
 
1540
            last_trace_ad = m68k_getpc (regs);
 
1541
            unset_special (regs, SPCFLAG_TRACE);
 
1542
            set_special (regs, SPCFLAG_DOTRACE);
 
1543
        }
 
1544
    } else if (regs->t1) {
 
1545
        last_trace_ad = m68k_getpc (regs);
 
1546
        unset_special (regs, SPCFLAG_TRACE);
 
1547
        set_special (regs, SPCFLAG_DOTRACE);
 
1548
    }
 
1549
}
 
1550
 
 
1551
/*
 
1552
 * Handle the STOP opcode.
 
1553
 *
 
1554
 * The 68k CPU stays in stopped state, essentially doing
 
1555
 * nothing, until an IRQ arrives,
 
1556
 */
 
1557
static NOINLINE void do_stop (struct regstruct *regs)
 
1558
{
 
1559
    unsigned int stop_count = 0;
 
1560
 
 
1561
    do {
 
1562
        /* An IRQ breaks the STOP state. */
 
1563
        if (regs->spcflags & (SPCFLAG_INT | SPCFLAG_DOINT))
 
1564
            break;
 
1565
 
 
1566
        /* E-UAE wants us to stop interpeting opcodes for some reason -
 
1567
         * perhaps to handle changes in settings - and this will
 
1568
         * implicitly break the STOP state.
 
1569
         */
 
1570
        if ((regs->spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
 
1571
            break;
 
1572
 
 
1573
        if (currprefs.cpu_idle && currprefs.m68k_speed != 0) {
 
1574
            /* The CPU idle thang. We attempt to stop hogging the host
 
1575
             * CPU when the emulated 68k ain't doing nothing.
 
1576
             */
 
1577
            static int          sleep_countdown;
 
1578
            static unsigned int lvpos;
 
1579
 
 
1580
            /* Check that we are not passed the end a frame. If
 
1581
             * we are passed, then no IRQs will occur to get us out
 
1582
             * of the STOP state, so we don't want to sleep.
 
1583
             *
 
1584
             * We could have used !is_lastline here, but the JIT mucks
 
1585
             * around with that for its own evil purposes.
 
1586
             */
 
1587
            if (lvpos != vpos) {
 
1588
                lvpos = vpos;
 
1589
 
 
1590
                stop_count++; /* Count of STOP cycles for this execution of STOP. */
 
1591
 
 
1592
                sleep_countdown--;
 
1593
                if (sleep_countdown < 0) {
 
1594
 
 
1595
                    sleep_countdown = currprefs.cpu_idle;
 
1596
 
 
1597
                    /* Avoid small numbers of STOP cycles. Arbitrary number here. */
 
1598
                    if (stop_count > 32) {
 
1599
 
 
1600
                        frame_time_t curr_time = uae_gethrtime ();
 
1601
 
 
1602
                        uae_msleep (1);
 
1603
 
 
1604
                        idletime += uae_gethrtime() - curr_time;
 
1605
                    }
 
1606
                }
 
1607
            }
 
1608
        }
 
1609
 
 
1610
        do_cycles (4 * CYCLE_UNIT);
 
1611
 
 
1612
        if (regs->spcflags & SPCFLAG_COPPER)
 
1613
            do_copper ();
 
1614
 
 
1615
    } while (regs->spcflags & SPCFLAG_STOP);
 
1616
}
 
1617
 
 
1618
 
 
1619
STATIC_INLINE int do_specialties (int cycles, struct regstruct *regs)
 
1620
{
 
1621
    #ifdef ACTION_REPLAY
 
1622
    #ifdef ACTION_REPLAY_HRTMON
 
1623
    if ((regs->spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
 
1624
        int isinhrt = (m68k_getpc (regs) >= hrtmem_start && m68k_getpc (regs) < hrtmem_start + hrtmem_size);
 
1625
        /* exit from HRTMon? */
 
1626
        if(hrtmon_flag == ACTION_REPLAY_HIDE && !isinhrt) hrtmon_hide();
 
1627
        /* HRTMon breakpoint? (not via IRQ7) */
 
1628
        if(hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt) hrtmon_breakenter();
 
1629
        if(hrtmon_flag == ACTION_REPLAY_ACTIVE && isinhrt) hrtmon_flag = ACTION_REPLAY_HIDE;
 
1630
        if(hrtmon_flag == ACTION_REPLAY_ACTIVATE) hrtmon_enter();
 
1631
        if(!(regs->spcflags & ~SPCFLAG_ACTION_REPLAY)) return 0;
 
1632
    }
 
1633
    #endif
 
1634
    if ((regs->spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE )
 
1635
    {
 
1636
        /*if(action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom())*/
 
1637
        /*      write_log ("PC:%p\n", m68k_getpc (regs));*/
 
1638
 
 
1639
        if(action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
 
1640
            action_replay_enter();
 
1641
        if(action_replay_flag == ACTION_REPLAY_HIDE && !is_ar_pc_in_rom())
 
1642
        {
 
1643
            action_replay_hide();
 
1644
            unset_special (regs, SPCFLAG_ACTION_REPLAY);
 
1645
        }
 
1646
        if (action_replay_flag == ACTION_REPLAY_WAIT_PC )
 
1647
        {
 
1648
            /*write_log ("Waiting for PC: %p, current PC= %p\n", wait_for_pc, m68k_getpc (regs));*/
 
1649
            if (m68k_getpc (regs) == wait_for_pc)
 
1650
            {
 
1651
                action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
 
1652
            }
 
1653
        }
 
1654
    }
 
1655
    #endif
 
1656
 
 
1657
    if (regs->spcflags & SPCFLAG_COPPER)
 
1658
        do_copper ();
 
1659
 
 
1660
    /*n_spcinsns++;*/
 
1661
#ifdef JIT
 
1662
    unset_special (regs, SPCFLAG_END_COMPILE);   /* has done its job */
 
1663
#endif
 
1664
 
 
1665
    while ((regs->spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
 
1666
        unsigned int c = blitnasty ();
 
1667
        if (c > 0) {
 
1668
            cycles -= c * CYCLE_UNIT * 2;
 
1669
            if (cycles < CYCLE_UNIT)
 
1670
                cycles = 0;
 
1671
        } else
 
1672
            c = 4;
 
1673
        do_cycles (c * CYCLE_UNIT);
 
1674
        if (regs->spcflags & SPCFLAG_COPPER)
 
1675
            do_copper ();
 
1676
    }
 
1677
 
 
1678
    if (regs->spcflags & SPCFLAG_DOTRACE)
 
1679
        Exception (9, regs, last_trace_ad);
 
1680
    if (regs->spcflags & SPCFLAG_TRAP) {
 
1681
        unset_special (regs, SPCFLAG_TRAP);
 
1682
        Exception (3, regs, 0);
 
1683
    }
 
1684
 
 
1685
    if (regs->spcflags & SPCFLAG_STOP)
 
1686
        do_stop (regs);
 
1687
 
 
1688
    if (regs->spcflags & SPCFLAG_TRACE)
 
1689
        do_trace (regs);
 
1690
 
 
1691
    /* An interrupt request takes at least 2 cycles (maybe 4) to reach the CPU, and
 
1692
     * there are programs that require this delay - which is not too surprising...
 
1693
     *
 
1694
     * In non-cycle-exact mode we handle this by separating the interrupt request
 
1695
     * pending (SPCFLAG_INT) and interrupt request arrived (SPCFLAG_DOINT) events.
 
1696
     * This ensures that there's always a delay of one opcode (and so at least 2
 
1697
     * machine cycles) between the interrupt controller requesting an interrupt
 
1698
     * and us servicing it here.
 
1699
     *
 
1700
     * In cycle-exact mode, there's just one event (SPCFLAG_INT) and the delay is
 
1701
     * handled internally by the interrupt controller code in custom.c - intlev()
 
1702
     * and friends.
 
1703
     */
 
1704
    if ((regs->spcflags & SPCFLAG_DOINT) ||
 
1705
        (currprefs.cpu_cycle_exact && (regs->spcflags & SPCFLAG_INT))) {
 
1706
 
 
1707
        int intr = intlev ();
 
1708
 
 
1709
        unset_special (regs, SPCFLAG_DOINT);
 
1710
 
 
1711
        if (intr != -1)
 
1712
            service_interrupt (intr, regs);
 
1713
    }
 
1714
 
 
1715
    if ((regs->spcflags & SPCFLAG_INT) && !currprefs.cpu_cycle_exact) {
 
1716
        unset_special (regs, SPCFLAG_INT);
 
1717
        set_special (regs, SPCFLAG_DOINT);
 
1718
    }
 
1719
 
 
1720
    if ((regs->spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
 
1721
        unset_special (regs, SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
 
1722
        return 1;
 
1723
    }
 
1724
    return 0;
 
1725
}
 
1726
 
 
1727
 
 
1728
#ifndef CPUEMU_5
 
1729
 
 
1730
static void m68k_run_1 (void)
 
1731
{
 
1732
}
 
1733
 
 
1734
#else
 
1735
 
 
1736
/* It's really sad to have two almost identical functions for this, but we
 
1737
   do it all for performance... :(
 
1738
   This version emulates 68000's prefetch "cache" */
 
1739
static void m68k_run_1 (void)
 
1740
{
 
1741
    struct regstruct *r = &regs;
 
1742
    unsigned long cycles_mask_local = cycles_mask;
 
1743
    unsigned long cycles_val_local  = cycles_val;
 
1744
 
 
1745
    for (;;) {
 
1746
        unsigned long cycles;
 
1747
        uae_u32 opcode = r->ir;
 
1748
        count_instr (opcode);
 
1749
 
 
1750
        cycles = (*cpufunctbl[opcode])(opcode, r);
 
1751
 
 
1752
        cycles &= cycles_mask_local;
 
1753
        cycles |= cycles_val_local;
 
1754
        do_cycles (cycles);
 
1755
        if (r->spcflags) {
 
1756
            if (do_specialties (cycles, r))
 
1757
                return;
 
1758
        }
 
1759
    }
 
1760
}
 
1761
 
 
1762
#endif /* CPUEMU_5 */
 
1763
 
 
1764
#ifndef CPUEMU_6
 
1765
 
 
1766
static void m68k_run_1_ce (void)
 
1767
{
 
1768
}
 
1769
 
 
1770
#else
 
1771
 
 
1772
/* cycle-exact m68k_run() */
 
1773
 
 
1774
static void m68k_run_1_ce (void)
 
1775
{
 
1776
    struct regstruct *r = &regs;
 
1777
 
 
1778
    for (;;) {
 
1779
        uae_u32 opcode = r->ir;
 
1780
 
 
1781
        (*cpufunctbl[opcode])(opcode, r);
 
1782
        if (r->spcflags) {
 
1783
            if (do_specialties (0, r))
 
1784
                return;
 
1785
        }
 
1786
    }
 
1787
}
 
1788
#endif /* CPUEMU_6 */
 
1789
 
 
1790
#ifdef JIT  /* Completely different run_2 replacement */
 
1791
 
 
1792
void do_nothing(void)
 
1793
{
 
1794
    /* What did you expect this to do? */
 
1795
    do_cycles(0);
 
1796
    /* I bet you didn't expect *that* ;-) */
 
1797
}
 
1798
 
 
1799
void exec_nostats(void)
 
1800
{
 
1801
    struct regstruct *r = &regs;
 
1802
    unsigned long cycles_mask_local = cycles_mask;
 
1803
    unsigned long cycles_val_local  = cycles_val;
 
1804
 
 
1805
    for (;;)
 
1806
    {
 
1807
        int new_cycles;
 
1808
        uae_u32 opcode = get_iword (r, 0);
 
1809
 
 
1810
        new_cycles = (*cpufunctbl[opcode])(opcode, r);
 
1811
 
 
1812
        new_cycles &= cycles_mask_local;
 
1813
        new_cycles |= cycles_val_local;
 
1814
        do_cycles (new_cycles);
 
1815
 
 
1816
        if (end_block(opcode) || r->spcflags)
 
1817
            return; /* We will deal with the spcflags in the caller */
 
1818
    }
 
1819
}
 
1820
 
 
1821
static int triggered;
 
1822
 
 
1823
void execute_normal(void)
 
1824
{
 
1825
    struct regstruct *r = &regs;
 
1826
    unsigned long cycles_mask_local = cycles_mask;
 
1827
    unsigned long cycles_val_local  = cycles_val;
 
1828
    int blocklen;
 
1829
    cpu_history pc_hist[MAXRUN];
 
1830
    int new_cycles;
 
1831
    int total_cycles;
 
1832
 
 
1833
    if (check_for_cache_miss())
 
1834
        return;
 
1835
 
 
1836
    total_cycles = 0;
 
1837
    blocklen = 0;
 
1838
    start_pc_p = r->pc_oldp;
 
1839
    start_pc   = r->pc;
 
1840
 
 
1841
    for (;;) {
 
1842
        /* Take note: This is the do-it-normal loop */
 
1843
        uae_u32 opcode = get_iword (r, 0);
 
1844
 
 
1845
        special_mem = DISTRUST_CONSISTENT_MEM;
 
1846
        pc_hist[blocklen].location = (uae_u16*)r->pc_p;
 
1847
 
 
1848
        new_cycles = (*cpufunctbl[opcode])(opcode, r);
 
1849
 
 
1850
        new_cycles &= cycles_mask_local;
 
1851
        new_cycles |= cycles_val_local;
 
1852
        do_cycles (new_cycles);
 
1853
        total_cycles += new_cycles;
 
1854
        pc_hist[blocklen].specmem = special_mem;
 
1855
        blocklen++;
 
1856
        if (end_block(opcode) || blocklen >= MAXRUN || r->spcflags) {
 
1857
            compile_block(pc_hist,blocklen,total_cycles);
 
1858
            return; /* We will deal with the spcflags in the caller */
 
1859
        }
 
1860
        /* No need to check regs.spcflags, because if they were set,
 
1861
           we'd have ended up inside that "if" */
 
1862
    }
 
1863
}
 
1864
 
 
1865
typedef void compiled_handler(void);
 
1866
 
 
1867
static void m68k_run_2a (void)
 
1868
{
 
1869
    for (;;) {
 
1870
#if defined X86_ASSEMBLY
 
1871
        __asm__ __volatile__(
 
1872
            "\tpush %%ebp\n\tcall *%0\n\tpop %%ebp"  /* FIXME */
 
1873
            :: "m" (cache_tags[cacheline(regs.pc_p)].handler)
 
1874
            : "%edx", "%ecx", "%eax",
 
1875
            "%esi", "%ebx", "%edi", "%ebp", "memory", "cc");
 
1876
#else
 
1877
        ((compiled_handler*)(pushall_call_handler))();
 
1878
#endif
 
1879
        /* Whenever we return from that, we should check spcflags */
 
1880
        if (regs.spcflags) {
 
1881
            if (do_specialties (0, &regs)) {
 
1882
                return;
 
1883
            }
 
1884
        }
 
1885
    }
 
1886
}
 
1887
#endif /* JIT */
 
1888
 
 
1889
#ifndef CPUEMU_0
 
1890
 
 
1891
static void m68k_run_2 (void)
 
1892
{
 
1893
}
 
1894
 
 
1895
static void m68k_run_2p (void)
 
1896
{
 
1897
}
 
1898
 
 
1899
#else
 
1900
 
 
1901
/* emulate simple prefetch  */
 
1902
static void m68k_run_2p (void)
 
1903
{
 
1904
    uae_u32 prefetch, prefetch_pc;
 
1905
    struct regstruct *r = &regs;
 
1906
    unsigned long cycles_mask_local = cycles_mask;
 
1907
    unsigned long cycles_val_local  = cycles_val;
 
1908
 
 
1909
    prefetch_pc = m68k_getpc (r);
 
1910
    prefetch = get_long (prefetch_pc);
 
1911
    for (;;) {
 
1912
        unsigned long cycles;
 
1913
        uae_u32 opcode;
 
1914
        uae_u32 pc = m68k_getpc (r);
 
1915
        if (pc == prefetch_pc)
 
1916
            opcode = prefetch >> 16;
 
1917
        else if (pc == prefetch_pc + 2)
 
1918
            opcode = prefetch & 0xffff;
 
1919
        else
 
1920
            opcode = get_word (pc);
 
1921
 
 
1922
        count_instr (opcode);
 
1923
 
 
1924
        prefetch_pc = m68k_getpc (r) + 2;
 
1925
        prefetch = get_long (prefetch_pc);
 
1926
        cycles = (*cpufunctbl[opcode])(opcode, r);
 
1927
        cycles &= cycles_mask_local;
 
1928
        cycles |= cycles_val_local;
 
1929
        do_cycles (cycles);
 
1930
        if (r->spcflags) {
 
1931
            if (do_specialties (cycles, r))
 
1932
                return;
 
1933
        }
 
1934
    }
 
1935
}
 
1936
 
 
1937
/* Same thing, but don't use prefetch to get opcode.  */
 
1938
static void m68k_run_2 (void)
 
1939
{
 
1940
    struct regstruct *r = &regs;
 
1941
    unsigned long cycles_mask_local = cycles_mask;
 
1942
    unsigned long cycles_val_local  = cycles_val;
 
1943
 
 
1944
    for (;;) {
 
1945
        unsigned long cycles;
 
1946
        uae_u32 opcode = get_iword (r, 0);
 
1947
        count_instr (opcode);
 
1948
 
 
1949
        cycles = (*cpufunctbl[opcode])(opcode, r);
 
1950
 
 
1951
        cycles &= cycles_mask_local;
 
1952
        cycles |= cycles_val_local;
 
1953
        do_cycles (cycles);
 
1954
        if (r->spcflags) {
 
1955
            if (do_specialties (cycles, r))
 
1956
                return;
 
1957
        }
 
1958
    }
 
1959
}
 
1960
 
 
1961
#endif /* CPUEMU_0 */
 
1962
 
 
1963
 
 
1964
static void exception2_handle (uaecptr addr, uaecptr fault)
 
1965
{
 
1966
    last_addr_for_exception_3 = addr;
 
1967
    last_fault_for_exception_3 = fault;
 
1968
    last_writeaccess_for_exception_3 = 0;
 
1969
    last_instructionaccess_for_exception_3 = 0;
 
1970
    Exception (2, &regs, addr);
 
1971
}
 
1972
 
 
1973
void m68k_go (int may_quit)
 
1974
{
 
1975
    for (;;) {
 
1976
        void (*run_func)(void);
 
1977
 
 
1978
#ifdef DEBUGGER
 
1979
        if (debugging)
 
1980
            debug ();
 
1981
#endif
 
1982
 
 
1983
        if (regs.panic) {
 
1984
            regs.panic = 0;
 
1985
            /* program jumped to non-existing memory and cpu was >= 68020 */
 
1986
            get_real_address (regs.isp); /* stack in no one's land? -> reboot */
 
1987
            if (regs.isp & 1)
 
1988
                regs.panic = 1;
 
1989
            if (!regs.panic)
 
1990
                exception2_handle (regs.panic_pc, regs.panic_addr);
 
1991
            if (regs.panic) {
 
1992
                /* system is very badly confused */
 
1993
                write_log ("double bus error or corrupted stack, forcing reboot..\n");
 
1994
                regs.panic = 0;
 
1995
                uae_reset (1);
 
1996
            }
 
1997
        }
 
1998
 
 
1999
#ifndef JIT
 
2000
        run_func = (currprefs.cpu_level == 0 && currprefs.cpu_cycle_exact       ? m68k_run_1_ce :
 
2001
                    currprefs.cpu_level == 0 && currprefs.cpu_compatible        ? m68k_run_1 :
 
2002
                    currprefs.cpu_compatible                                    ? m68k_run_2p :
 
2003
                                                                                  m68k_run_2);
 
2004
#else
 
2005
        run_func = (currprefs.cpu_cycle_exact && currprefs.cpu_level == 0       ? m68k_run_1_ce :
 
2006
                    currprefs.cpu_compatible > 0 && currprefs.cpu_level == 0    ? m68k_run_1 :
 
2007
                    currprefs.cpu_level >= 2 && currprefs.cachesize             ? m68k_run_2a :
 
2008
                    currprefs.cpu_compatible                                    ? m68k_run_2p :
 
2009
                                                                                  m68k_run_2);
 
2010
#endif
 
2011
        run_func ();
 
2012
 
 
2013
        if (uae_state_change_pending ())
 
2014
            break;
 
2015
    }
 
2016
}
 
2017
 
 
2018
 
 
2019
#if defined(DEBUGGER) || defined (ENFORCER)
 
2020
 
 
2021
static const char * const ccnames[] =
 
2022
{ "T","F","HI","LS","CC","CS","NE","EQ",
 
2023
  "VC","VS","PL","MI","GE","LT","GT","LE" };
 
2024
 
 
2025
static void m68k_disasm_2 (void *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
 
2026
{
 
2027
    uaecptr newpc = 0;
 
2028
    m68kpc_offset = addr - m68k_getpc (&regs);
 
2029
 
 
2030
    while (cnt-- > 0) {
 
2031
        char instrname[100], *ccpt;
 
2032
        int i;
 
2033
        uae_u32 opcode;
 
2034
        struct mnemolookup *lookup;
 
2035
        struct instr *dp;
 
2036
        int oldpc;
 
2037
 
 
2038
        oldpc = m68kpc_offset;
 
2039
        opcode = get_iword_1 (&regs, m68kpc_offset);
 
2040
        if (cpufunctbl[opcode] == op_illg_1) {
 
2041
            opcode = 0x4AFC;
 
2042
        }
 
2043
        dp = table68k + opcode;
 
2044
        for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
 
2045
            ;
 
2046
 
 
2047
        f_out (f, "%08x ", m68k_getpc (&regs) + m68kpc_offset);
 
2048
        m68kpc_offset += 2;
 
2049
 
 
2050
        strcpy (instrname, lookup->name);
 
2051
        ccpt = strstr (instrname, "cc");
 
2052
        if (ccpt != 0) {
 
2053
            strncpy (ccpt, ccnames[dp->cc], 2);
 
2054
        }
 
2055
        switch (dp->size){
 
2056
         case sz_byte: strcat (instrname, ".B "); break;
 
2057
         case sz_word: strcat (instrname, ".W "); break;
 
2058
         case sz_long: strcat (instrname, ".L "); break;
 
2059
         default: strcat (instrname, "   "); break;
 
2060
        }
 
2061
 
 
2062
        if (dp->suse) {
 
2063
            newpc = m68k_getpc (&regs) + m68kpc_offset;
 
2064
            newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr, safemode);
 
2065
        }
 
2066
        if (dp->suse && dp->duse)
 
2067
            strcat (instrname, ",");
 
2068
        if (dp->duse) {
 
2069
            newpc = m68k_getpc (&regs) + m68kpc_offset;
 
2070
            newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
 
2071
        }
 
2072
 
 
2073
        for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++) {
 
2074
            f_out (f, "%04x ", get_iword_1 (&regs, oldpc + i * 2));
 
2075
        }
 
2076
        while (i++ < 5)
 
2077
            f_out (f, "     ");
 
2078
        f_out (f, instrname);
 
2079
 
 
2080
        if (ccpt != 0) {
 
2081
            if (deaddr)
 
2082
                *deaddr = newpc;
 
2083
            if (cctrue (&regs.ccrflags, dp->cc))
 
2084
                f_out (f, " == %08x (TRUE)", newpc);
 
2085
            else
 
2086
                f_out (f, " == %08x (FALSE)", newpc);
 
2087
        } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
 
2088
            if (deaddr)
 
2089
                *deaddr = newpc;
 
2090
            f_out (f, " == %08x", newpc);
 
2091
        }
 
2092
        f_out (f, "\n");
 
2093
    }
 
2094
    if (nextpc)
 
2095
        *nextpc = m68k_getpc (&regs) + m68kpc_offset;
 
2096
}
 
2097
 
 
2098
void m68k_disasm_ea (void *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
 
2099
{
 
2100
    m68k_disasm_2 (f, addr, nextpc, cnt, seaddr, deaddr, 1);
 
2101
}
 
2102
void m68k_disasm (void *f, uaecptr addr, uaecptr *nextpc, int cnt)
 
2103
{
 
2104
    m68k_disasm_2 (f, addr, nextpc, cnt, NULL, NULL, 0);
 
2105
}
 
2106
 
 
2107
/*************************************************************
 
2108
 Disasm the m68kcode at the given address into instrname
 
2109
 and instrcode
 
2110
*************************************************************/
 
2111
void sm68k_disasm (char *instrname, char *instrcode, uaecptr addr, uaecptr *nextpc)
 
2112
{
 
2113
    char *ccpt;
 
2114
    uae_u32 opcode;
 
2115
    struct mnemolookup *lookup;
 
2116
    struct instr *dp;
 
2117
    int oldpc;
 
2118
 
 
2119
    uaecptr newpc = 0;
 
2120
 
 
2121
    m68kpc_offset = addr - m68k_getpc (&regs);
 
2122
 
 
2123
    oldpc = m68kpc_offset;
 
2124
    opcode = get_iword_1 (&regs, m68kpc_offset);
 
2125
    if (cpufunctbl[opcode] == op_illg_1) {
 
2126
        opcode = 0x4AFC;
 
2127
    }
 
2128
    dp = table68k + opcode;
 
2129
    for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
 
2130
 
 
2131
    m68kpc_offset += 2;
 
2132
 
 
2133
    strcpy (instrname, lookup->name);
 
2134
    ccpt = strstr (instrname, "cc");
 
2135
    if (ccpt != 0) {
 
2136
        strncpy (ccpt, ccnames[dp->cc], 2);
 
2137
    }
 
2138
    switch (dp->size){
 
2139
        case sz_byte: strcat (instrname, ".B "); break;
 
2140
        case sz_word: strcat (instrname, ".W "); break;
 
2141
        case sz_long: strcat (instrname, ".L "); break;
 
2142
        default: strcat (instrname, "   "); break;
 
2143
    }
 
2144
 
 
2145
    if (dp->suse) {
 
2146
        newpc = m68k_getpc (&regs) + m68kpc_offset;
 
2147
        newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
 
2148
    }
 
2149
    if (dp->suse && dp->duse)
 
2150
        strcat (instrname, ",");
 
2151
    if (dp->duse) {
 
2152
        newpc = m68k_getpc (&regs) + m68kpc_offset;
 
2153
        newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
 
2154
    }
 
2155
 
 
2156
    if (instrcode)
 
2157
    {
 
2158
        int i;
 
2159
        for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++)
 
2160
        {
 
2161
            sprintf (instrcode, "%04x ", get_iword_1 (&regs, oldpc + i * 2));
 
2162
            instrcode += strlen(instrcode);
 
2163
        }
 
2164
    }
 
2165
 
 
2166
    if (nextpc)
 
2167
        *nextpc = m68k_getpc (&regs) + m68kpc_offset;
 
2168
}
 
2169
 
 
2170
void m68k_dumpstate (void *f, uaecptr *nextpc)
 
2171
{
 
2172
    int i;
 
2173
 
 
2174
#ifndef WIN32
 
2175
    if (!f)
 
2176
        f = stderr;
 
2177
#endif
 
2178
 
 
2179
    for (i = 0; i < 8; i++){
 
2180
        f_out (f, "D%d: %08x ", i, m68k_dreg (&regs, i));
 
2181
        if ((i & 3) == 3) f_out (f, "\n");
 
2182
    }
 
2183
    for (i = 0; i < 8; i++){
 
2184
        f_out (f, "A%d: %08x ", i, m68k_areg (&regs, i));
 
2185
        if ((i & 3) == 3) f_out (f, "\n");
 
2186
    }
 
2187
    if (regs.s == 0) regs.usp = m68k_areg (&regs, 7);
 
2188
    if (regs.s && regs.m) regs.msp = m68k_areg (&regs, 7);
 
2189
    if (regs.s && regs.m == 0) regs.isp = m68k_areg (&regs, 7);
 
2190
    f_out (f, "USP=%08x ISP=%08x MSP=%08x VBR=%08x\n",
 
2191
             regs.usp,regs.isp,regs.msp,regs.vbr);
 
2192
    f_out (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
 
2193
             regs.t1, regs.t0, regs.s, regs.m,
 
2194
             GET_XFLG(&regs.ccrflags), GET_NFLG(&regs.ccrflags),
 
2195
             GET_ZFLG(&regs.ccrflags), GET_VFLG(&regs.ccrflags),
 
2196
             GET_CFLG(&regs.ccrflags), regs.intmask);
 
2197
#ifdef FPUEMU
 
2198
    if (currprefs.cpu_level >= 2) {
 
2199
        uae_u32 fpsr;
 
2200
        for (i = 0; i < 8; i++){
 
2201
            f_out (f, "FP%d: %g ", i, regs.fp[i]);
 
2202
            if ((i & 3) == 3) f_out (f, "\n");
 
2203
        }
 
2204
        fpsr = fpp_get_fpsr (&regs);
 
2205
        f_out (f, "N=%d Z=%d I=%d NAN=%d\n",
 
2206
                (fpsr & 0x8000000) != 0,
 
2207
                (fpsr & 0x4000000) != 0,
 
2208
                (fpsr & 0x2000000) != 0,
 
2209
                (fpsr & 0x1000000) != 0);
 
2210
    }
 
2211
#endif
 
2212
    if (currprefs.cpu_compatible) {
 
2213
        struct instr *dp;
 
2214
        struct mnemolookup *lookup1, *lookup2;
 
2215
        dp = table68k + regs.irc;
 
2216
        for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
 
2217
        dp = table68k + regs.ir;
 
2218
        for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
 
2219
        f_out (f, "prefetch %04x (%s) %04x (%s)\n", regs.irc, lookup1->name, regs.ir, lookup2->name);
 
2220
    }
 
2221
 
 
2222
    m68k_disasm (f, m68k_getpc (&regs), nextpc, 1);
 
2223
    if (nextpc)
 
2224
        f_out (f, "next PC: %08x\n", *nextpc);
 
2225
}
 
2226
 
 
2227
#else
 
2228
 
 
2229
void m68k_dumpstate (void *f, uaecptr *nextpc)
 
2230
{
 
2231
}
 
2232
 
 
2233
#endif
 
2234
 
 
2235
 
 
2236
#ifdef SAVESTATE
 
2237
 
 
2238
/* CPU save/restore code */
 
2239
 
 
2240
#define CPUTYPE_EC 1
 
2241
#define CPUMODE_HALT 1
 
2242
 
 
2243
const uae_u8 *restore_cpu (const uae_u8 *src)
 
2244
{
 
2245
    unsigned int i, model, flags;
 
2246
    uae_u32 l;
 
2247
 
 
2248
    model = restore_u32 ();
 
2249
    switch (model) {
 
2250
    case 68000:
 
2251
        changed_prefs.cpu_level = 0;
 
2252
        break;
 
2253
    case 68010:
 
2254
        changed_prefs.cpu_level = 1;
 
2255
        break;
 
2256
    case 68020:
 
2257
        changed_prefs.cpu_level = 2;
 
2258
        break;
 
2259
    case 68040:
 
2260
        changed_prefs.cpu_level = 4;
 
2261
        break;
 
2262
    case 68060:
 
2263
        changed_prefs.cpu_level = 6;
 
2264
        break;
 
2265
    default:
 
2266
        write_log ("Unknown cpu type %d\n", model);
 
2267
        break;
 
2268
    }
 
2269
 
 
2270
    flags = restore_u32 ();
 
2271
    changed_prefs.address_space_24 = 0;
 
2272
    if (flags & CPUTYPE_EC)
 
2273
        changed_prefs.address_space_24 = 1;
 
2274
    if (model > 68000)
 
2275
        changed_prefs.cpu_compatible = 0;
 
2276
    currprefs.cpu_level = changed_prefs.cpu_level;
 
2277
    currprefs.address_space_24 = changed_prefs.address_space_24;
 
2278
    currprefs.cpu_compatible = changed_prefs.cpu_compatible;
 
2279
    currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
 
2280
    currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
 
2281
    for (i = 0; i < 15; i++)
 
2282
        regs.regs[i] = restore_u32 ();
 
2283
    regs.pc = restore_u32 ();
 
2284
    regs.irc = restore_u16 ();
 
2285
    regs.ir = restore_u16 ();
 
2286
    regs.usp = restore_u32 ();
 
2287
    regs.isp = restore_u32 ();
 
2288
    regs.sr = restore_u16 ();
 
2289
    l = restore_u32 ();
 
2290
    if (l & CPUMODE_HALT) {
 
2291
        regs.stopped = 1;
 
2292
        set_special (&regs, SPCFLAG_STOP);
 
2293
    } else
 
2294
        regs.stopped = 0;
 
2295
    if (model >= 68010) {
 
2296
        regs.dfc = restore_u32 ();
 
2297
        regs.sfc = restore_u32 ();
 
2298
        regs.vbr = restore_u32 ();
 
2299
    }
 
2300
    if (model >= 68020) {
 
2301
        caar = restore_u32 ();
 
2302
        cacr = restore_u32 ();
 
2303
        regs.msp = restore_u32 ();
 
2304
        /* A500 speed in 68020 mode isn't too logical.. */
 
2305
        if (changed_prefs.m68k_speed == 0)
 
2306
            currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
 
2307
    }
 
2308
    write_log ("CPU %d%s%03d, PC=%08x\n",
 
2309
               model / 1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
 
2310
 
 
2311
    return src;
 
2312
}
 
2313
 
 
2314
void restore_cpu_finish (void)
 
2315
{
 
2316
    init_m68k ();
 
2317
    m68k_setpc (&regs, regs.pc);
 
2318
}
 
2319
 
 
2320
static const int cpumodel[] = { 68000, 68010, 68020, 68020, 68040, 68060 };
 
2321
 
 
2322
uae_u8 *save_cpu (uae_u32 *len, uae_u8 *dstptr)
 
2323
{
 
2324
    uae_u8 *dstbak, *dst;
 
2325
    unsigned int model, i;
 
2326
 
 
2327
    if (dstptr)
 
2328
        dstbak = dst = dstptr;
 
2329
    else
 
2330
        dstbak = dst = malloc(4+4+15*4+4+4+4+4+2+4+4+4+4+4+4+4);
 
2331
    model = cpumodel[currprefs.cpu_level];
 
2332
    save_u32 (model);                                   /* MODEL */
 
2333
    save_u32 (currprefs.address_space_24 ? 1 : 0);      /* FLAGS */
 
2334
    for (i = 0; i < 15; i++) save_u32 (regs.regs[i]);   /* D0-D7 A0-A6 */
 
2335
    save_u32 (m68k_getpc (&regs));                      /* PC */
 
2336
    save_u16 (regs.irc);                                /* prefetch */
 
2337
    save_u16 (regs.ir);                                 /* instruction prefetch */
 
2338
    MakeSR (&regs);
 
2339
    save_u32 (!regs.s ? regs.regs[15] : regs.usp);      /* USP */
 
2340
    save_u32 (regs.s ? regs.regs[15] : regs.isp);       /* ISP */
 
2341
    save_u16 (regs.sr);                         /* SR/CCR */
 
2342
    save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
 
2343
    if (model >= 68010) {
 
2344
        save_u32 (regs.dfc);                            /* DFC */
 
2345
        save_u32 (regs.sfc);                            /* SFC */
 
2346
        save_u32 (regs.vbr);                            /* VBR */
 
2347
    }
 
2348
    if (model >= 68020) {
 
2349
        save_u32 (caar);                                /* CAAR */
 
2350
        save_u32 (cacr);                                /* CACR */
 
2351
        save_u32 (regs.msp);                            /* MSP */
 
2352
    }
 
2353
    *len = dst - dstbak;
 
2354
    return dstbak;
 
2355
}
 
2356
 
 
2357
#endif /* SAVESTATE */
 
2358
 
 
2359
static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess)
 
2360
{
 
2361
    last_addr_for_exception_3 = addr;
 
2362
    last_fault_for_exception_3 = fault;
 
2363
    last_op_for_exception_3 = opcode;
 
2364
    last_writeaccess_for_exception_3 = writeaccess;
 
2365
    last_instructionaccess_for_exception_3 = instructionaccess;
 
2366
    Exception (3, &regs, fault);
 
2367
}
 
2368
 
 
2369
void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault)
 
2370
{
 
2371
    exception3f (opcode, addr, fault, 0, 0);
 
2372
}
 
2373
 
 
2374
void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault)
 
2375
{
 
2376
    exception3f (opcode, addr, fault, 0, 1);
 
2377
}
 
2378
 
 
2379
void exception2 (uaecptr addr, uaecptr fault)
 
2380
{
 
2381
    write_log ("delayed exception2!\n");
 
2382
    regs.panic_pc = m68k_getpc (&regs);
 
2383
    regs.panic_addr = addr;
 
2384
    regs.panic = 2;
 
2385
    set_special (&regs, SPCFLAG_BRK);
 
2386
    m68k_setpc (&regs, 0xf80000);
 
2387
#ifdef JIT
 
2388
    set_special (&regs, SPCFLAG_END_COMPILE);
 
2389
#endif
 
2390
    fill_prefetch_slow (&regs);
 
2391
}
 
2392
 
 
2393
void cpureset (void)
 
2394
{
 
2395
    customreset ();
 
2396
#if 0
 
2397
    uae_u16 ins;
 
2398
    if (currprefs.cpu_level == 0 && (currprefs.cpu_compatible || currprefs.cpu_cycle_exact)) {
 
2399
        customreset ();
 
2400
        return;
 
2401
    }
 
2402
    ins = get_word (m68k_getpc (&regs) + 2);
 
2403
    if ((ins & ~7) == 0x4ed0) {
 
2404
        int reg = ins & 7;
 
2405
        uae_u32 addr = m68k_areg (regs, reg);
 
2406
        write_log ("reset/jmp (ax) combination emulated\n");
 
2407
        customreset ();
 
2408
        if (addr < 0x80000)
 
2409
            addr += 0xf80000;
 
2410
        m68k_setpc (&regs, addr);
 
2411
    }
 
2412
#endif
 
2413
}
 
2414
 
 
2415
 
 
2416
/*
 
2417
 
 
2418
 The routines below take dividend and divisor as parameters.
 
2419
 They return 0 if division by zero, or exact number of cycles otherwise.
 
2420
 
 
2421
 The number of cycles returned assumes a register operand.
 
2422
 Effective address time must be added if memory operand.
 
2423
 
 
2424
 For 68000 only (not 68010, 68012, 68020, etc).
 
2425
 Probably valid for 68008 after adding the extra prefetch cycle.
 
2426
 
 
2427
 
 
2428
 Best and worst cases are for register operand:
 
2429
 (Note the difference with the documented range.)
 
2430
 
 
2431
 
 
2432
 DIVU:
 
2433
 
 
2434
 Overflow (always): 10 cycles.
 
2435
 Worst case: 136 cycles.
 
2436
 Best case: 76 cycles.
 
2437
 
 
2438
 
 
2439
 DIVS:
 
2440
 
 
2441
 Absolute overflow: 16-18 cycles.
 
2442
 Signed overflow is not detected prematurely.
 
2443
 
 
2444
 Worst case: 156 cycles.
 
2445
 Best case without signed overflow: 122 cycles.
 
2446
 Best case with signed overflow: 120 cycles
 
2447
 
 
2448
 
 
2449
 */
 
2450
 
 
2451
 
 
2452
//
 
2453
// DIVU
 
2454
// Unsigned division
 
2455
//
 
2456
 
 
2457
STATIC_INLINE int getDivu68kCycles_2(uae_u32 dividend, uae_u16 divisor)
 
2458
{
 
2459
        int mcycles;
 
2460
        uae_u32 hdivisor;
 
2461
        int i;
 
2462
 
 
2463
        if(divisor == 0)
 
2464
                return 0;
 
2465
 
 
2466
        // Overflow
 
2467
        if((dividend >> 16) >= divisor)
 
2468
                return (mcycles = 5) * 2;
 
2469
 
 
2470
        mcycles = 38;
 
2471
        hdivisor = divisor << 16;
 
2472
 
 
2473
        for( i = 0; i < 15; i++)
 
2474
        {
 
2475
                uae_u32 temp;
 
2476
                temp = dividend;
 
2477
 
 
2478
                dividend <<= 1;
 
2479
 
 
2480
                // If carry from shift
 
2481
                if((uae_s32)temp < 0)
 
2482
                {
 
2483
                        dividend -= hdivisor;
 
2484
                }
 
2485
                else
 
2486
                {
 
2487
                        mcycles += 2;
 
2488
                        if(dividend >= hdivisor)
 
2489
                        {
 
2490
                                dividend -= hdivisor;
 
2491
                                mcycles--;
 
2492
                        }
 
2493
                }
 
2494
        }
 
2495
        return mcycles * 2;
 
2496
}
 
2497
int getDivu68kCycles(uae_u32 dividend, uae_u16 divisor)
 
2498
{
 
2499
    int v = getDivu68kCycles_2(dividend, divisor) - 4;
 
2500
//    write_log ("U%d ", v);
 
2501
    return v;
 
2502
}
 
2503
 
 
2504
//
 
2505
// DIVS
 
2506
// Signed division
 
2507
//
 
2508
 
 
2509
STATIC_INLINE int getDivs68kCycles_2(uae_s32 dividend, uae_s16 divisor)
 
2510
{
 
2511
        int mcycles;
 
2512
        uae_u32 aquot;
 
2513
        int i;
 
2514
 
 
2515
        if(divisor == 0)
 
2516
                return 0;
 
2517
 
 
2518
        mcycles = 6;
 
2519
 
 
2520
        if( dividend < 0)
 
2521
                mcycles++;
 
2522
 
 
2523
        // Check for absolute overflow
 
2524
        if(((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
 
2525
        {
 
2526
                return (mcycles + 2) * 2;
 
2527
        }
 
2528
 
 
2529
        // Absolute quotient
 
2530
        aquot = (uae_u32) abs(dividend) / (uae_u16)abs(divisor);
 
2531
 
 
2532
        mcycles += 55;
 
2533
 
 
2534
        if(divisor >= 0)
 
2535
        {
 
2536
                if(dividend >= 0)
 
2537
                        mcycles--;
 
2538
                else
 
2539
                        mcycles++;
 
2540
        }
 
2541
 
 
2542
        // Count 15 msbits in absolute of quotient
 
2543
 
 
2544
        for( i = 0; i < 15; i++)
 
2545
        {
 
2546
                if((uae_s16)aquot >= 0)
 
2547
                        mcycles++;
 
2548
                aquot <<= 1;
 
2549
        }
 
2550
 
 
2551
        return mcycles * 2;
 
2552
}
 
2553
int getDivs68kCycles(uae_s32 dividend, uae_s16 divisor)
 
2554
{
 
2555
    int v = getDivs68kCycles_2(dividend, divisor) - 4;
 
2556
//    write_log ("S%d ", v);
 
2557
    return v;
 
2558
}