Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ d4c430a8

History | View | Annotate | Download (22.6 kB)

1
/*
2
 *  m68k op helpers
3
 *
4
 *  Copyright (c) 2006-2007 CodeSourcery
5
 *  Written by Paul Brook
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 */
20

    
21
#include <stdio.h>
22
#include <string.h>
23

    
24
#include "config.h"
25
#include "cpu.h"
26
#include "exec-all.h"
27
#include "qemu-common.h"
28
#include "gdbstub.h"
29

    
30
#include "helpers.h"
31

    
32
#define SIGNBIT (1u << 31)
33

    
34
enum m68k_cpuid {
35
    M68K_CPUID_M5206,
36
    M68K_CPUID_M5208,
37
    M68K_CPUID_CFV4E,
38
    M68K_CPUID_ANY,
39
};
40

    
41
typedef struct m68k_def_t m68k_def_t;
42

    
43
struct m68k_def_t {
44
    const char * name;
45
    enum m68k_cpuid id;
46
};
47

    
48
static m68k_def_t m68k_cpu_defs[] = {
49
    {"m5206", M68K_CPUID_M5206},
50
    {"m5208", M68K_CPUID_M5208},
51
    {"cfv4e", M68K_CPUID_CFV4E},
52
    {"any", M68K_CPUID_ANY},
53
    {NULL, 0},
54
};
55

    
56
void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
57
{
58
    unsigned int i;
59

    
60
    for (i = 0; m68k_cpu_defs[i].name; i++) {
61
        (*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
62
    }
63
}
64

    
65
static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
66
{
67
    if (n < 8) {
68
        stfq_p(mem_buf, env->fregs[n]);
69
        return 8;
70
    }
71
    if (n < 11) {
72
        /* FP control registers (not implemented)  */
73
        memset(mem_buf, 0, 4);
74
        return 4;
75
    }
76
    return 0;
77
}
78

    
79
static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
80
{
81
    if (n < 8) {
82
        env->fregs[n] = ldfq_p(mem_buf);
83
        return 8;
84
    }
85
    if (n < 11) {
86
        /* FP control registers (not implemented)  */
87
        return 4;
88
    }
89
    return 0;
90
}
91

    
92
static void m68k_set_feature(CPUM68KState *env, int feature)
93
{
94
    env->features |= (1u << feature);
95
}
96

    
97
static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
98
{
99
    m68k_def_t *def;
100

    
101
    for (def = m68k_cpu_defs; def->name; def++) {
102
        if (strcmp(def->name, name) == 0)
103
            break;
104
    }
105
    if (!def->name)
106
        return -1;
107

    
108
    switch (def->id) {
109
    case M68K_CPUID_M5206:
110
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
111
        break;
112
    case M68K_CPUID_M5208:
113
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
114
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115
        m68k_set_feature(env, M68K_FEATURE_BRAL);
116
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117
        m68k_set_feature(env, M68K_FEATURE_USP);
118
        break;
119
    case M68K_CPUID_CFV4E:
120
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
121
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
122
        m68k_set_feature(env, M68K_FEATURE_BRAL);
123
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
124
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
125
        m68k_set_feature(env, M68K_FEATURE_USP);
126
        break;
127
    case M68K_CPUID_ANY:
128
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
129
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
130
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
131
        m68k_set_feature(env, M68K_FEATURE_BRAL);
132
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
133
        /* MAC and EMAC are mututally exclusive, so pick EMAC.
134
           It's mostly backwards compatible.  */
135
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
136
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
137
        m68k_set_feature(env, M68K_FEATURE_USP);
138
        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
139
        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
140
        break;
141
    }
142

    
143
    register_m68k_insns(env);
144
    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
145
        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
146
                                 11, "cf-fp.xml", 18);
147
    }
148
    /* TODO: Add [E]MAC registers.  */
149
    return 0;
150
}
151

    
152
void cpu_reset(CPUM68KState *env)
153
{
154
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
155
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
156
        log_cpu_state(env, 0);
157
    }
158

    
159
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
160
#if !defined (CONFIG_USER_ONLY)
161
    env->sr = 0x2700;
162
#endif
163
    m68k_switch_sp(env);
164
    /* ??? FP regs should be initialized to NaN.  */
165
    env->cc_op = CC_OP_FLAGS;
166
    /* TODO: We should set PC from the interrupt vector.  */
167
    env->pc = 0;
168
    tlb_flush(env, 1);
169
}
170

    
171
CPUM68KState *cpu_m68k_init(const char *cpu_model)
172
{
173
    CPUM68KState *env;
174
    static int inited;
175

    
176
    env = qemu_mallocz(sizeof(CPUM68KState));
177
    cpu_exec_init(env);
178
    if (!inited) {
179
        inited = 1;
180
        m68k_tcg_init();
181
    }
182

    
183
    env->cpu_model_str = cpu_model;
184

    
185
    if (cpu_m68k_set_model(env, cpu_model) < 0) {
186
        cpu_m68k_close(env);
187
        return NULL;
188
    }
189

    
190
    cpu_reset(env);
191
    qemu_init_vcpu(env);
192
    return env;
193
}
194

    
195
void cpu_m68k_close(CPUM68KState *env)
196
{
197
    qemu_free(env);
198
}
199

    
200
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
201
{
202
    int flags;
203
    uint32_t src;
204
    uint32_t dest;
205
    uint32_t tmp;
206

    
207
#define HIGHBIT 0x80000000u
208

    
209
#define SET_NZ(x) do { \
210
    if ((x) == 0) \
211
        flags |= CCF_Z; \
212
    else if ((int32_t)(x) < 0) \
213
        flags |= CCF_N; \
214
    } while (0)
215

    
216
#define SET_FLAGS_SUB(type, utype) do { \
217
    SET_NZ((type)dest); \
218
    tmp = dest + src; \
219
    if ((utype) tmp < (utype) src) \
220
        flags |= CCF_C; \
221
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
222
        flags |= CCF_V; \
223
    } while (0)
224

    
225
    flags = 0;
226
    src = env->cc_src;
227
    dest = env->cc_dest;
228
    switch (cc_op) {
229
    case CC_OP_FLAGS:
230
        flags = dest;
231
        break;
232
    case CC_OP_LOGIC:
233
        SET_NZ(dest);
234
        break;
235
    case CC_OP_ADD:
236
        SET_NZ(dest);
237
        if (dest < src)
238
            flags |= CCF_C;
239
        tmp = dest - src;
240
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
241
            flags |= CCF_V;
242
        break;
243
    case CC_OP_SUB:
244
        SET_FLAGS_SUB(int32_t, uint32_t);
245
        break;
246
    case CC_OP_CMPB:
247
        SET_FLAGS_SUB(int8_t, uint8_t);
248
        break;
249
    case CC_OP_CMPW:
250
        SET_FLAGS_SUB(int16_t, uint16_t);
251
        break;
252
    case CC_OP_ADDX:
253
        SET_NZ(dest);
254
        if (dest <= src)
255
            flags |= CCF_C;
256
        tmp = dest - src - 1;
257
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
258
            flags |= CCF_V;
259
        break;
260
    case CC_OP_SUBX:
261
        SET_NZ(dest);
262
        tmp = dest + src + 1;
263
        if (tmp <= src)
264
            flags |= CCF_C;
265
        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
266
            flags |= CCF_V;
267
        break;
268
    case CC_OP_SHIFT:
269
        SET_NZ(dest);
270
        if (src)
271
            flags |= CCF_C;
272
        break;
273
    default:
274
        cpu_abort(env, "Bad CC_OP %d", cc_op);
275
    }
276
    env->cc_op = CC_OP_FLAGS;
277
    env->cc_dest = flags;
278
}
279

    
280
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
281
{
282
    switch (reg) {
283
    case 0x02: /* CACR */
284
        env->cacr = val;
285
        m68k_switch_sp(env);
286
        break;
287
    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
288
        /* TODO: Implement Access Control Registers.  */
289
        break;
290
    case 0x801: /* VBR */
291
        env->vbr = val;
292
        break;
293
    /* TODO: Implement control registers.  */
294
    default:
295
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
296
                  reg, val);
297
    }
298
}
299

    
300
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
301
{
302
    uint32_t acc;
303
    int8_t exthigh;
304
    uint8_t extlow;
305
    uint64_t regval;
306
    int i;
307
    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
308
        for (i = 0; i < 4; i++) {
309
            regval = env->macc[i];
310
            exthigh = regval >> 40;
311
            if (env->macsr & MACSR_FI) {
312
                acc = regval >> 8;
313
                extlow = regval;
314
            } else {
315
                acc = regval;
316
                extlow = regval >> 32;
317
            }
318
            if (env->macsr & MACSR_FI) {
319
                regval = (((uint64_t)acc) << 8) | extlow;
320
                regval |= ((int64_t)exthigh) << 40;
321
            } else if (env->macsr & MACSR_SU) {
322
                regval = acc | (((int64_t)extlow) << 32);
323
                regval |= ((int64_t)exthigh) << 40;
324
            } else {
325
                regval = acc | (((uint64_t)extlow) << 32);
326
                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
327
            }
328
            env->macc[i] = regval;
329
        }
330
    }
331
    env->macsr = val;
332
}
333

    
334
void m68k_switch_sp(CPUM68KState *env)
335
{
336
    int new_sp;
337

    
338
    env->sp[env->current_sp] = env->aregs[7];
339
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
340
             ? M68K_SSP : M68K_USP;
341
    env->aregs[7] = env->sp[new_sp];
342
    env->current_sp = new_sp;
343
}
344

    
345
#if defined(CONFIG_USER_ONLY)
346

    
347
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
348
                               int mmu_idx, int is_softmmu)
349
{
350
    env->exception_index = EXCP_ACCESS;
351
    env->mmu.ar = address;
352
    return 1;
353
}
354

    
355
#else
356

    
357
/* MMU */
358

    
359
/* TODO: This will need fixing once the MMU is implemented.  */
360
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
361
{
362
    return addr;
363
}
364

    
365
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
366
                               int mmu_idx, int is_softmmu)
367
{
368
    int prot;
369

    
370
    address &= TARGET_PAGE_MASK;
371
    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
372
    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
373
    return 0;
374
}
375

    
376
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
377
   be handled by the interrupt controller.  Real hardware only requests
378
   the vector when the interrupt is acknowledged by the CPU.  For
379
   simplicitly we calculate it when the interrupt is signalled.  */
380
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
381
{
382
    env->pending_level = level;
383
    env->pending_vector = vector;
384
    if (level)
385
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
386
    else
387
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
388
}
389

    
390
#endif
391

    
392
uint32_t HELPER(bitrev)(uint32_t x)
393
{
394
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
395
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
396
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
397
    return bswap32(x);
398
}
399

    
400
uint32_t HELPER(ff1)(uint32_t x)
401
{
402
    int n;
403
    for (n = 32; x; n--)
404
        x >>= 1;
405
    return n;
406
}
407

    
408
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
409
{
410
    /* The result has the opposite sign to the original value.  */
411
    if (ccr & CCF_V)
412
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
413
    return val;
414
}
415

    
416
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
417
{
418
    uint32_t res;
419
    uint32_t old_flags;
420

    
421
    old_flags = env->cc_dest;
422
    if (env->cc_x) {
423
        env->cc_x = (op1 <= op2);
424
        env->cc_op = CC_OP_SUBX;
425
        res = op1 - (op2 + 1);
426
    } else {
427
        env->cc_x = (op1 < op2);
428
        env->cc_op = CC_OP_SUB;
429
        res = op1 - op2;
430
    }
431
    env->cc_dest = res;
432
    env->cc_src = op2;
433
    cpu_m68k_flush_flags(env, env->cc_op);
434
    /* !Z is sticky.  */
435
    env->cc_dest &= (old_flags | ~CCF_Z);
436
    return res;
437
}
438

    
439
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
440
{
441
    uint32_t res;
442
    uint32_t old_flags;
443

    
444
    old_flags = env->cc_dest;
445
    if (env->cc_x) {
446
        res = op1 + op2 + 1;
447
        env->cc_x = (res <= op2);
448
        env->cc_op = CC_OP_ADDX;
449
    } else {
450
        res = op1 + op2;
451
        env->cc_x = (res < op2);
452
        env->cc_op = CC_OP_ADD;
453
    }
454
    env->cc_dest = res;
455
    env->cc_src = op2;
456
    cpu_m68k_flush_flags(env, env->cc_op);
457
    /* !Z is sticky.  */
458
    env->cc_dest &= (old_flags | ~CCF_Z);
459
    return res;
460
}
461

    
462
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
463
{
464
    return a < b;
465
}
466

    
467
void HELPER(set_sr)(CPUState *env, uint32_t val)
468
{
469
    env->sr = val & 0xffff;
470
    m68k_switch_sp(env);
471
}
472

    
473
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
474
{
475
    uint32_t result;
476
    uint32_t cf;
477

    
478
    shift &= 63;
479
    if (shift == 0) {
480
        result = val;
481
        cf = env->cc_src & CCF_C;
482
    } else if (shift < 32) {
483
        result = val << shift;
484
        cf = (val >> (32 - shift)) & 1;
485
    } else if (shift == 32) {
486
        result = 0;
487
        cf = val & 1;
488
    } else /* shift > 32 */ {
489
        result = 0;
490
        cf = 0;
491
    }
492
    env->cc_src = cf;
493
    env->cc_x = (cf != 0);
494
    env->cc_dest = result;
495
    return result;
496
}
497

    
498
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
499
{
500
    uint32_t result;
501
    uint32_t cf;
502

    
503
    shift &= 63;
504
    if (shift == 0) {
505
        result = val;
506
        cf = env->cc_src & CCF_C;
507
    } else if (shift < 32) {
508
        result = val >> shift;
509
        cf = (val >> (shift - 1)) & 1;
510
    } else if (shift == 32) {
511
        result = 0;
512
        cf = val >> 31;
513
    } else /* shift > 32 */ {
514
        result = 0;
515
        cf = 0;
516
    }
517
    env->cc_src = cf;
518
    env->cc_x = (cf != 0);
519
    env->cc_dest = result;
520
    return result;
521
}
522

    
523
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
524
{
525
    uint32_t result;
526
    uint32_t cf;
527

    
528
    shift &= 63;
529
    if (shift == 0) {
530
        result = val;
531
        cf = (env->cc_src & CCF_C) != 0;
532
    } else if (shift < 32) {
533
        result = (int32_t)val >> shift;
534
        cf = (val >> (shift - 1)) & 1;
535
    } else /* shift >= 32 */ {
536
        result = (int32_t)val >> 31;
537
        cf = val >> 31;
538
    }
539
    env->cc_src = cf;
540
    env->cc_x = cf;
541
    env->cc_dest = result;
542
    return result;
543
}
544

    
545
/* FPU helpers.  */
546
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
547
{
548
    return float64_to_int32(val, &env->fp_status);
549
}
550

    
551
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
552
{
553
    return float64_to_float32(val, &env->fp_status);
554
}
555

    
556
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
557
{
558
    return int32_to_float64(val, &env->fp_status);
559
}
560

    
561
float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
562
{
563
    return float32_to_float64(val, &env->fp_status);
564
}
565

    
566
float64 HELPER(iround_f64)(CPUState *env, float64 val)
567
{
568
    return float64_round_to_int(val, &env->fp_status);
569
}
570

    
571
float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
572
{
573
    return float64_trunc_to_int(val, &env->fp_status);
574
}
575

    
576
float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
577
{
578
    return float64_sqrt(val, &env->fp_status);
579
}
580

    
581
float64 HELPER(abs_f64)(float64 val)
582
{
583
    return float64_abs(val);
584
}
585

    
586
float64 HELPER(chs_f64)(float64 val)
587
{
588
    return float64_chs(val);
589
}
590

    
591
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
592
{
593
    return float64_add(a, b, &env->fp_status);
594
}
595

    
596
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
597
{
598
    return float64_sub(a, b, &env->fp_status);
599
}
600

    
601
float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
602
{
603
    return float64_mul(a, b, &env->fp_status);
604
}
605

    
606
float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
607
{
608
    return float64_div(a, b, &env->fp_status);
609
}
610

    
611
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
612
{
613
    /* ??? This may incorrectly raise exceptions.  */
614
    /* ??? Should flush denormals to zero.  */
615
    float64 res;
616
    res = float64_sub(a, b, &env->fp_status);
617
    if (float64_is_nan(res)) {
618
        /* +/-inf compares equal against itself, but sub returns nan.  */
619
        if (!float64_is_nan(a)
620
            && !float64_is_nan(b)) {
621
            res = float64_zero;
622
            if (float64_lt_quiet(a, res, &env->fp_status))
623
                res = float64_chs(res);
624
        }
625
    }
626
    return res;
627
}
628

    
629
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
630
{
631
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
632
}
633

    
634
/* MAC unit.  */
635
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
636
   take values,  others take register numbers and manipulate the contents
637
   in-place.  */
638
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
639
{
640
    uint32_t mask;
641
    env->macc[dest] = env->macc[src];
642
    mask = MACSR_PAV0 << dest;
643
    if (env->macsr & (MACSR_PAV0 << src))
644
        env->macsr |= mask;
645
    else
646
        env->macsr &= ~mask;
647
}
648

    
649
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
650
{
651
    int64_t product;
652
    int64_t res;
653

    
654
    product = (uint64_t)op1 * op2;
655
    res = (product << 24) >> 24;
656
    if (res != product) {
657
        env->macsr |= MACSR_V;
658
        if (env->macsr & MACSR_OMC) {
659
            /* Make sure the accumulate operation overflows.  */
660
            if (product < 0)
661
                res = ~(1ll << 50);
662
            else
663
                res = 1ll << 50;
664
        }
665
    }
666
    return res;
667
}
668

    
669
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
670
{
671
    uint64_t product;
672

    
673
    product = (uint64_t)op1 * op2;
674
    if (product & (0xffffffull << 40)) {
675
        env->macsr |= MACSR_V;
676
        if (env->macsr & MACSR_OMC) {
677
            /* Make sure the accumulate operation overflows.  */
678
            product = 1ll << 50;
679
        } else {
680
            product &= ((1ull << 40) - 1);
681
        }
682
    }
683
    return product;
684
}
685

    
686
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
687
{
688
    uint64_t product;
689
    uint32_t remainder;
690

    
691
    product = (uint64_t)op1 * op2;
692
    if (env->macsr & MACSR_RT) {
693
        remainder = product & 0xffffff;
694
        product >>= 24;
695
        if (remainder > 0x800000)
696
            product++;
697
        else if (remainder == 0x800000)
698
            product += (product & 1);
699
    } else {
700
        product >>= 24;
701
    }
702
    return product;
703
}
704

    
705
void HELPER(macsats)(CPUState *env, uint32_t acc)
706
{
707
    int64_t tmp;
708
    int64_t result;
709
    tmp = env->macc[acc];
710
    result = ((tmp << 16) >> 16);
711
    if (result != tmp) {
712
        env->macsr |= MACSR_V;
713
    }
714
    if (env->macsr & MACSR_V) {
715
        env->macsr |= MACSR_PAV0 << acc;
716
        if (env->macsr & MACSR_OMC) {
717
            /* The result is saturated to 32 bits, despite overflow occuring
718
               at 48 bits.  Seems weird, but that's what the hardware docs
719
               say.  */
720
            result = (result >> 63) ^ 0x7fffffff;
721
        }
722
    }
723
    env->macc[acc] = result;
724
}
725

    
726
void HELPER(macsatu)(CPUState *env, uint32_t acc)
727
{
728
    uint64_t val;
729

    
730
    val = env->macc[acc];
731
    if (val & (0xffffull << 48)) {
732
        env->macsr |= MACSR_V;
733
    }
734
    if (env->macsr & MACSR_V) {
735
        env->macsr |= MACSR_PAV0 << acc;
736
        if (env->macsr & MACSR_OMC) {
737
            if (val > (1ull << 53))
738
                val = 0;
739
            else
740
                val = (1ull << 48) - 1;
741
        } else {
742
            val &= ((1ull << 48) - 1);
743
        }
744
    }
745
    env->macc[acc] = val;
746
}
747

    
748
void HELPER(macsatf)(CPUState *env, uint32_t acc)
749
{
750
    int64_t sum;
751
    int64_t result;
752

    
753
    sum = env->macc[acc];
754
    result = (sum << 16) >> 16;
755
    if (result != sum) {
756
        env->macsr |= MACSR_V;
757
    }
758
    if (env->macsr & MACSR_V) {
759
        env->macsr |= MACSR_PAV0 << acc;
760
        if (env->macsr & MACSR_OMC) {
761
            result = (result >> 63) ^ 0x7fffffffffffll;
762
        }
763
    }
764
    env->macc[acc] = result;
765
}
766

    
767
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
768
{
769
    uint64_t val;
770
    val = env->macc[acc];
771
    if (val == 0)
772
        env->macsr |= MACSR_Z;
773
    else if (val & (1ull << 47));
774
        env->macsr |= MACSR_N;
775
    if (env->macsr & (MACSR_PAV0 << acc)) {
776
        env->macsr |= MACSR_V;
777
    }
778
    if (env->macsr & MACSR_FI) {
779
        val = ((int64_t)val) >> 40;
780
        if (val != 0 && val != -1)
781
            env->macsr |= MACSR_EV;
782
    } else if (env->macsr & MACSR_SU) {
783
        val = ((int64_t)val) >> 32;
784
        if (val != 0 && val != -1)
785
            env->macsr |= MACSR_EV;
786
    } else {
787
        if ((val >> 32) != 0)
788
            env->macsr |= MACSR_EV;
789
    }
790
}
791

    
792
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
793
{
794
    cpu_m68k_flush_flags(env, cc_op);
795
}
796

    
797
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
798
{
799
    int rem;
800
    uint32_t result;
801

    
802
    if (env->macsr & MACSR_SU) {
803
        /* 16-bit rounding.  */
804
        rem = val & 0xffffff;
805
        val = (val >> 24) & 0xffffu;
806
        if (rem > 0x800000)
807
            val++;
808
        else if (rem == 0x800000)
809
            val += (val & 1);
810
    } else if (env->macsr & MACSR_RT) {
811
        /* 32-bit rounding.  */
812
        rem = val & 0xff;
813
        val >>= 8;
814
        if (rem > 0x80)
815
            val++;
816
        else if (rem == 0x80)
817
            val += (val & 1);
818
    } else {
819
        /* No rounding.  */
820
        val >>= 8;
821
    }
822
    if (env->macsr & MACSR_OMC) {
823
        /* Saturate.  */
824
        if (env->macsr & MACSR_SU) {
825
            if (val != (uint16_t) val) {
826
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
827
            } else {
828
                result = val & 0xffff;
829
            }
830
        } else {
831
            if (val != (uint32_t)val) {
832
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
833
            } else {
834
                result = (uint32_t)val;
835
            }
836
        }
837
    } else {
838
        /* No saturation.  */
839
        if (env->macsr & MACSR_SU) {
840
            result = val & 0xffff;
841
        } else {
842
            result = (uint32_t)val;
843
        }
844
    }
845
    return result;
846
}
847

    
848
uint32_t HELPER(get_macs)(uint64_t val)
849
{
850
    if (val == (int32_t)val) {
851
        return (int32_t)val;
852
    } else {
853
        return (val >> 61) ^ ~SIGNBIT;
854
    }
855
}
856

    
857
uint32_t HELPER(get_macu)(uint64_t val)
858
{
859
    if ((val >> 32) == 0) {
860
        return (uint32_t)val;
861
    } else {
862
        return 0xffffffffu;
863
    }
864
}
865

    
866
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
867
{
868
    uint32_t val;
869
    val = env->macc[acc] & 0x00ff;
870
    val = (env->macc[acc] >> 32) & 0xff00;
871
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
872
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
873
    return val;
874
}
875

    
876
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
877
{
878
    uint32_t val;
879
    val = (env->macc[acc] >> 32) & 0xffff;
880
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
881
    return val;
882
}
883

    
884
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
885
{
886
    int64_t res;
887
    int32_t tmp;
888
    res = env->macc[acc] & 0xffffffff00ull;
889
    tmp = (int16_t)(val & 0xff00);
890
    res |= ((int64_t)tmp) << 32;
891
    res |= val & 0xff;
892
    env->macc[acc] = res;
893
    res = env->macc[acc + 1] & 0xffffffff00ull;
894
    tmp = (val & 0xff000000);
895
    res |= ((int64_t)tmp) << 16;
896
    res |= (val >> 16) & 0xff;
897
    env->macc[acc + 1] = res;
898
}
899

    
900
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
901
{
902
    int64_t res;
903
    int32_t tmp;
904
    res = (uint32_t)env->macc[acc];
905
    tmp = (int16_t)val;
906
    res |= ((int64_t)tmp) << 32;
907
    env->macc[acc] = res;
908
    res = (uint32_t)env->macc[acc + 1];
909
    tmp = val & 0xffff0000;
910
    res |= (int64_t)tmp << 16;
911
    env->macc[acc + 1] = res;
912
}
913

    
914
void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
915
{
916
    uint64_t res;
917
    res = (uint32_t)env->macc[acc];
918
    res |= ((uint64_t)(val & 0xffff)) << 32;
919
    env->macc[acc] = res;
920
    res = (uint32_t)env->macc[acc + 1];
921
    res |= (uint64_t)(val & 0xffff0000) << 16;
922
    env->macc[acc + 1] = res;
923
}