Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 4fcc562b

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;
372
    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
373
}
374

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

    
389
#endif
390

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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