Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ e1f3808e

History | View | Annotate | Download (21.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, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21

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

    
25
#include "config.h"
26
#include "cpu.h"
27
#include "exec-all.h"
28
#include "qemu-common.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
static void m68k_set_feature(CPUM68KState *env, int feature)
57
{
58
    env->features |= (1u << feature);
59
}
60

    
61
static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
62
{
63
    m68k_def_t *def;
64

    
65
    for (def = m68k_cpu_defs; def->name; def++) {
66
        if (strcmp(def->name, name) == 0)
67
            break;
68
    }
69
    if (!def->name)
70
        return -1;
71

    
72
    switch (def->id) {
73
    case M68K_CPUID_M5206:
74
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
75
        break;
76
    case M68K_CPUID_M5208:
77
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
78
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
79
        m68k_set_feature(env, M68K_FEATURE_BRAL);
80
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
81
        m68k_set_feature(env, M68K_FEATURE_USP);
82
        break;
83
    case M68K_CPUID_CFV4E:
84
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
85
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
86
        m68k_set_feature(env, M68K_FEATURE_BRAL);
87
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
88
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
89
        m68k_set_feature(env, M68K_FEATURE_USP);
90
        break;
91
    case M68K_CPUID_ANY:
92
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
93
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
94
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
95
        m68k_set_feature(env, M68K_FEATURE_BRAL);
96
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
97
        /* MAC and EMAC are mututally exclusive, so pick EMAC.
98
           It's mostly backwards compatible.  */
99
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
100
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
101
        m68k_set_feature(env, M68K_FEATURE_USP);
102
        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
103
        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
104
        break;
105
    }
106

    
107
    register_m68k_insns(env);
108
    return 0;
109
}
110

    
111
void cpu_reset(CPUM68KState *env)
112
{
113
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
114
#if !defined (CONFIG_USER_ONLY)
115
    env->sr = 0x2700;
116
#endif
117
    m68k_switch_sp(env);
118
    /* ??? FP regs should be initialized to NaN.  */
119
    env->cc_op = CC_OP_FLAGS;
120
    /* TODO: We should set PC from the interrupt vector.  */
121
    env->pc = 0;
122
    tlb_flush(env, 1);
123
}
124

    
125
CPUM68KState *cpu_m68k_init(const char *cpu_model)
126
{
127
    CPUM68KState *env;
128
    static int inited;
129

    
130
    env = malloc(sizeof(CPUM68KState));
131
    if (!env)
132
        return NULL;
133
    cpu_exec_init(env);
134
    if (!inited) {
135
        inited = 1;
136
        m68k_tcg_init();
137
    }
138

    
139
    env->cpu_model_str = cpu_model;
140

    
141
    if (cpu_m68k_set_model(env, cpu_model) < 0) {
142
        cpu_m68k_close(env);
143
        return NULL;
144
    }
145

    
146
    cpu_reset(env);
147
    return env;
148
}
149

    
150
void cpu_m68k_close(CPUM68KState *env)
151
{
152
    qemu_free(env);
153
}
154

    
155
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
156
{
157
    int flags;
158
    uint32_t src;
159
    uint32_t dest;
160
    uint32_t tmp;
161

    
162
#define HIGHBIT 0x80000000u
163

    
164
#define SET_NZ(x) do { \
165
    if ((x) == 0) \
166
        flags |= CCF_Z; \
167
    else if ((int32_t)(x) < 0) \
168
        flags |= CCF_N; \
169
    } while (0)
170

    
171
#define SET_FLAGS_SUB(type, utype) do { \
172
    SET_NZ((type)dest); \
173
    tmp = dest + src; \
174
    if ((utype) tmp < (utype) src) \
175
        flags |= CCF_C; \
176
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
177
        flags |= CCF_V; \
178
    } while (0)
179

    
180
    flags = 0;
181
    src = env->cc_src;
182
    dest = env->cc_dest;
183
    switch (cc_op) {
184
    case CC_OP_FLAGS:
185
        flags = dest;
186
        break;
187
    case CC_OP_LOGIC:
188
        SET_NZ(dest);
189
        break;
190
    case CC_OP_ADD:
191
        SET_NZ(dest);
192
        if (dest < src)
193
            flags |= CCF_C;
194
        tmp = dest - src;
195
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
196
            flags |= CCF_V;
197
        break;
198
    case CC_OP_SUB:
199
        SET_FLAGS_SUB(int32_t, uint32_t);
200
        break;
201
    case CC_OP_CMPB:
202
        SET_FLAGS_SUB(int8_t, uint8_t);
203
        break;
204
    case CC_OP_CMPW:
205
        SET_FLAGS_SUB(int16_t, uint16_t);
206
        break;
207
    case CC_OP_ADDX:
208
        SET_NZ(dest);
209
        if (dest <= src)
210
            flags |= CCF_C;
211
        tmp = dest - src - 1;
212
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
213
            flags |= CCF_V;
214
        break;
215
    case CC_OP_SUBX:
216
        SET_NZ(dest);
217
        tmp = dest + src + 1;
218
        if (tmp <= src)
219
            flags |= CCF_C;
220
        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
221
            flags |= CCF_V;
222
        break;
223
    case CC_OP_SHIFT:
224
        SET_NZ(dest);
225
        if (src)
226
            flags |= CCF_C;
227
        break;
228
    default:
229
        cpu_abort(env, "Bad CC_OP %d", cc_op);
230
    }
231
    env->cc_op = CC_OP_FLAGS;
232
    env->cc_dest = flags;
233
}
234

    
235
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
236
{
237
    switch (reg) {
238
    case 0x02: /* CACR */
239
        env->cacr = val;
240
        m68k_switch_sp(env);
241
        break;
242
    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
243
        /* TODO: Implement Access Control Registers.  */
244
        break;
245
    case 0x801: /* VBR */
246
        env->vbr = val;
247
        break;
248
    /* TODO: Implement control registers.  */
249
    default:
250
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
251
                  reg, val);
252
    }
253
}
254

    
255
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
256
{
257
    uint32_t acc;
258
    int8_t exthigh;
259
    uint8_t extlow;
260
    uint64_t regval;
261
    int i;
262
    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
263
        for (i = 0; i < 4; i++) {
264
            regval = env->macc[i];
265
            exthigh = regval >> 40;
266
            if (env->macsr & MACSR_FI) {
267
                acc = regval >> 8;
268
                extlow = regval;
269
            } else {
270
                acc = regval;
271
                extlow = regval >> 32;
272
            }
273
            if (env->macsr & MACSR_FI) {
274
                regval = (((uint64_t)acc) << 8) | extlow;
275
                regval |= ((int64_t)exthigh) << 40;
276
            } else if (env->macsr & MACSR_SU) {
277
                regval = acc | (((int64_t)extlow) << 32);
278
                regval |= ((int64_t)exthigh) << 40;
279
            } else {
280
                regval = acc | (((uint64_t)extlow) << 32);
281
                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
282
            }
283
            env->macc[i] = regval;
284
        }
285
    }
286
    env->macsr = val;
287
}
288

    
289
void m68k_switch_sp(CPUM68KState *env)
290
{
291
    int new_sp;
292

    
293
    env->sp[env->current_sp] = env->aregs[7];
294
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
295
             ? M68K_SSP : M68K_USP;
296
    env->aregs[7] = env->sp[new_sp];
297
    env->current_sp = new_sp;
298
}
299

    
300
/* MMU */
301

    
302
/* TODO: This will need fixing once the MMU is implemented.  */
303
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
304
{
305
    return addr;
306
}
307

    
308
#if defined(CONFIG_USER_ONLY)
309

    
310
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
311
                               int mmu_idx, int is_softmmu)
312
{
313
    env->exception_index = EXCP_ACCESS;
314
    env->mmu.ar = address;
315
    return 1;
316
}
317

    
318
#else
319

    
320
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
321
                               int mmu_idx, int is_softmmu)
322
{
323
    int prot;
324

    
325
    address &= TARGET_PAGE_MASK;
326
    prot = PAGE_READ | PAGE_WRITE;
327
    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
328
}
329

    
330
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
331
   be handled by the interrupt controller.  Real hardware only requests
332
   the vector when the interrupt is acknowledged by the CPU.  For
333
   simplicitly we calculate it when the interrupt is signalled.  */
334
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
335
{
336
    env->pending_level = level;
337
    env->pending_vector = vector;
338
    if (level)
339
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
340
    else
341
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
342
}
343

    
344
#endif
345

    
346
uint32_t HELPER(bitrev)(uint32_t x)
347
{
348
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
349
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
350
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
351
    return bswap32(x);
352
}
353

    
354
uint32_t HELPER(ff1)(uint32_t x)
355
{
356
    int n;
357
    for (n = 32; x; n--)
358
        x >>= 1;
359
    return n;
360
}
361

    
362
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
363
{
364
    /* The result has the opposite sign to the original value.  */
365
    if (ccr & CCF_V)
366
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
367
    return val;
368
}
369

    
370
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
371
{
372
    uint32_t res;
373
    uint32_t old_flags;
374

    
375
    old_flags = env->cc_dest;
376
    if (env->cc_x) {
377
        env->cc_x = (op1 <= op2);
378
        env->cc_op = CC_OP_SUBX;
379
        res = op1 - (op2 + 1);
380
    } else {
381
        env->cc_x = (op1 < op2);
382
        env->cc_op = CC_OP_SUB;
383
        res = op1 - op2;
384
    }
385
    env->cc_dest = res;
386
    env->cc_src = op2;
387
    cpu_m68k_flush_flags(env, env->cc_op);
388
    /* !Z is sticky.  */
389
    env->cc_dest &= (old_flags | ~CCF_Z);
390
    return res;
391
}
392

    
393
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
394
{
395
    uint32_t res;
396
    uint32_t old_flags;
397

    
398
    old_flags = env->cc_dest;
399
    if (env->cc_x) {
400
        res = op1 + op2 + 1;
401
        env->cc_x = (res <= op2);
402
        env->cc_op = CC_OP_ADDX;
403
    } else {
404
        res = op1 + op2;
405
        env->cc_x = (res < op2);
406
        env->cc_op = CC_OP_ADD;
407
    }
408
    env->cc_dest = res;
409
    env->cc_src = op2;
410
    cpu_m68k_flush_flags(env, env->cc_op);
411
    /* !Z is sticky.  */
412
    env->cc_dest &= (old_flags | ~CCF_Z);
413
    return res;
414
}
415

    
416
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
417
{
418
    return a < b;
419
}
420

    
421
uint32_t HELPER(btest)(uint32_t x)
422
{
423
    return x != 0;
424
}
425

    
426
void HELPER(set_sr)(CPUState *env, uint32_t val)
427
{
428
    env->sr = val & 0xffff;
429
    m68k_switch_sp(env);
430
}
431

    
432
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
433
{
434
    uint32_t result;
435
    uint32_t cf;
436

    
437
    shift &= 63;
438
    if (shift == 0) {
439
        result = val;
440
        cf = env->cc_src & CCF_C;
441
    } else if (shift < 32) {
442
        result = val << shift;
443
        cf = (val >> (32 - shift)) & 1;
444
    } else if (shift == 32) {
445
        result = 0;
446
        cf = val & 1;
447
    } else /* shift > 32 */ {
448
        result = 0;
449
        cf = 0;
450
    }
451
    env->cc_src = cf;
452
    env->cc_x = (cf != 0);
453
    env->cc_dest = result;
454
    return result;
455
}
456

    
457
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
458
{
459
    uint32_t result;
460
    uint32_t cf;
461

    
462
    shift &= 63;
463
    if (shift == 0) {
464
        result = val;
465
        cf = env->cc_src & CCF_C;
466
    } else if (shift < 32) {
467
        result = val >> shift;
468
        cf = (val >> (shift - 1)) & 1;
469
    } else if (shift == 32) {
470
        result = 0;
471
        cf = val >> 31;
472
    } else /* shift > 32 */ {
473
        result = 0;
474
        cf = 0;
475
    }
476
    env->cc_src = cf;
477
    env->cc_x = (cf != 0);
478
    env->cc_dest = result;
479
    return result;
480
}
481

    
482
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
483
{
484
    uint32_t result;
485
    uint32_t cf;
486

    
487
    shift &= 63;
488
    if (shift == 0) {
489
        result = val;
490
        cf = (env->cc_src & CCF_C) != 0;
491
    } else if (shift < 32) {
492
        result = (int32_t)val >> shift;
493
        cf = (val >> (shift - 1)) & 1;
494
    } else /* shift >= 32 */ {
495
        result = (int32_t)val >> 31;
496
        cf = val >> 31;
497
    }
498
    env->cc_src = cf;
499
    env->cc_x = cf;
500
    env->cc_dest = result;
501
    return result;
502
}
503

    
504
/* FPU helpers.  */
505
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
506
{
507
    return float64_to_int32(val, &env->fp_status);
508
}
509

    
510
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
511
{
512
    return float64_to_float32(val, &env->fp_status);
513
}
514

    
515
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
516
{
517
    return int32_to_float64(val, &env->fp_status);
518
}
519

    
520
float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
521
{
522
    return float32_to_float64(val, &env->fp_status);
523
}
524

    
525
float64 HELPER(iround_f64)(CPUState *env, float64 val)
526
{
527
    return float64_round_to_int(val, &env->fp_status);
528
}
529

    
530
float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
531
{
532
    return float64_trunc_to_int(val, &env->fp_status);
533
}
534

    
535
float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
536
{
537
    return float64_sqrt(val, &env->fp_status);
538
}
539

    
540
float64 HELPER(abs_f64)(float64 val)
541
{
542
    return float64_abs(val);
543
}
544

    
545
float64 HELPER(chs_f64)(float64 val)
546
{
547
    return float64_chs(val);
548
}
549

    
550
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
551
{
552
    return float64_add(a, b, &env->fp_status);
553
}
554

    
555
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
556
{
557
    return float64_sub(a, b, &env->fp_status);
558
}
559

    
560
float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
561
{
562
    return float64_mul(a, b, &env->fp_status);
563
}
564

    
565
float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
566
{
567
    return float64_div(a, b, &env->fp_status);
568
}
569

    
570
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
571
{
572
    /* ??? This may incorrectly raise exceptions.  */
573
    /* ??? Should flush denormals to zero.  */
574
    float64 res;
575
    res = float64_sub(a, b, &env->fp_status);
576
    if (float64_is_nan(res)) {
577
        /* +/-inf compares equal against itself, but sub returns nan.  */
578
        if (!float64_is_nan(a)
579
            && !float64_is_nan(b)) {
580
            res = float64_zero;
581
            if (float64_lt_quiet(a, res, &env->fp_status))
582
                res = float64_chs(res);
583
        }
584
    }
585
    return res;
586
}
587

    
588
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
589
{
590
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
591
}
592

    
593
/* MAC unit.  */
594
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
595
   take values,  others take register numbers and manipulate the contents
596
   in-place.  */
597
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
598
{
599
    uint32_t mask;
600
    env->macc[dest] = env->macc[src];
601
    mask = MACSR_PAV0 << dest;
602
    if (env->macsr & (MACSR_PAV0 << src))
603
        env->macsr |= mask;
604
    else
605
        env->macsr &= ~mask;
606
}
607

    
608
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
609
{
610
    int64_t product;
611
    int64_t res;
612

    
613
    product = (uint64_t)op1 * op2;
614
    res = (product << 24) >> 24;
615
    if (res != product) {
616
        env->macsr |= MACSR_V;
617
        if (env->macsr & MACSR_OMC) {
618
            /* Make sure the accumulate operation overflows.  */
619
            if (product < 0)
620
                res = ~(1ll << 50);
621
            else
622
                res = 1ll << 50;
623
        }
624
    }
625
    return res;
626
}
627

    
628
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
629
{
630
    uint64_t product;
631

    
632
    product = (uint64_t)op1 * op2;
633
    if (product & (0xffffffull << 40)) {
634
        env->macsr |= MACSR_V;
635
        if (env->macsr & MACSR_OMC) {
636
            /* Make sure the accumulate operation overflows.  */
637
            product = 1ll << 50;
638
        } else {
639
            product &= ((1ull << 40) - 1);
640
        }
641
    }
642
    return product;
643
}
644

    
645
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
646
{
647
    uint64_t product;
648
    uint32_t remainder;
649

    
650
    product = (uint64_t)op1 * op2;
651
    if (env->macsr & MACSR_RT) {
652
        remainder = product & 0xffffff;
653
        product >>= 24;
654
        if (remainder > 0x800000)
655
            product++;
656
        else if (remainder == 0x800000)
657
            product += (product & 1);
658
    } else {
659
        product >>= 24;
660
    }
661
    return product;
662
}
663

    
664
void HELPER(macsats)(CPUState *env, uint32_t acc)
665
{
666
    int64_t tmp;
667
    int64_t result;
668
    tmp = env->macc[acc];
669
    result = ((tmp << 16) >> 16);
670
    if (result != tmp) {
671
        env->macsr |= MACSR_V;
672
    }
673
    if (env->macsr & MACSR_V) {
674
        env->macsr |= MACSR_PAV0 << acc;
675
        if (env->macsr & MACSR_OMC) {
676
            /* The result is saturated to 32 bits, despite overflow occuring
677
               at 48 bits.  Seems weird, but that's what the hardware docs
678
               say.  */
679
            result = (result >> 63) ^ 0x7fffffff;
680
        }
681
    }
682
    env->macc[acc] = result;
683
}
684

    
685
void HELPER(macsatu)(CPUState *env, uint32_t acc)
686
{
687
    uint64_t val;
688

    
689
    val = env->macc[acc];
690
    if (val & (0xffffull << 48)) {
691
        env->macsr |= MACSR_V;
692
    }
693
    if (env->macsr & MACSR_V) {
694
        env->macsr |= MACSR_PAV0 << acc;
695
        if (env->macsr & MACSR_OMC) {
696
            if (val > (1ull << 53))
697
                val = 0;
698
            else
699
                val = (1ull << 48) - 1;
700
        } else {
701
            val &= ((1ull << 48) - 1);
702
        }
703
    }
704
    env->macc[acc] = val;
705
}
706

    
707
void HELPER(macsatf)(CPUState *env, uint32_t acc)
708
{
709
    int64_t sum;
710
    int64_t result;
711

    
712
    sum = env->macc[acc];
713
    result = (sum << 16) >> 16;
714
    if (result != sum) {
715
        env->macsr |= MACSR_V;
716
    }
717
    if (env->macsr & MACSR_V) {
718
        env->macsr |= MACSR_PAV0 << acc;
719
        if (env->macsr & MACSR_OMC) {
720
            result = (result >> 63) ^ 0x7fffffffffffll;
721
        }
722
    }
723
    env->macc[acc] = result;
724
}
725

    
726
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
727
{
728
    uint64_t val;
729
    val = env->macc[acc];
730
    if (val == 0)
731
        env->macsr |= MACSR_Z;
732
    else if (val & (1ull << 47));
733
        env->macsr |= MACSR_N;
734
    if (env->macsr & (MACSR_PAV0 << acc)) {
735
        env->macsr |= MACSR_V;
736
    }
737
    if (env->macsr & MACSR_FI) {
738
        val = ((int64_t)val) >> 40;
739
        if (val != 0 && val != -1)
740
            env->macsr |= MACSR_EV;
741
    } else if (env->macsr & MACSR_SU) {
742
        val = ((int64_t)val) >> 32;
743
        if (val != 0 && val != -1)
744
            env->macsr |= MACSR_EV;
745
    } else {
746
        if ((val >> 32) != 0)
747
            env->macsr |= MACSR_EV;
748
    }
749
}
750

    
751
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
752
{
753
    cpu_m68k_flush_flags(env, cc_op);
754
}
755

    
756
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
757
{
758
    int rem;
759
    uint32_t result;
760

    
761
    if (env->macsr & MACSR_SU) {
762
        /* 16-bit rounding.  */
763
        rem = val & 0xffffff;
764
        val = (val >> 24) & 0xffffu;
765
        if (rem > 0x800000)
766
            val++;
767
        else if (rem == 0x800000)
768
            val += (val & 1);
769
    } else if (env->macsr & MACSR_RT) {
770
        /* 32-bit rounding.  */
771
        rem = val & 0xff;
772
        val >>= 8;
773
        if (rem > 0x80)
774
            val++;
775
        else if (rem == 0x80)
776
            val += (val & 1);
777
    } else {
778
        /* No rounding.  */
779
        val >>= 8;
780
    }
781
    if (env->macsr & MACSR_OMC) {
782
        /* Saturate.  */
783
        if (env->macsr & MACSR_SU) {
784
            if (val != (uint16_t) val) {
785
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
786
            } else {
787
                result = val & 0xffff;
788
            }
789
        } else {
790
            if (val != (uint32_t)val) {
791
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
792
            } else {
793
                result = (uint32_t)val;
794
            }
795
        }
796
    } else {
797
        /* No saturation.  */
798
        if (env->macsr & MACSR_SU) {
799
            result = val & 0xffff;
800
        } else {
801
            result = (uint32_t)val;
802
        }
803
    }
804
    return result;
805
}
806

    
807
uint32_t HELPER(get_macs)(uint64_t val)
808
{
809
    if (val == (int32_t)val) {
810
        return (int32_t)val;
811
    } else {
812
        return (val >> 61) ^ ~SIGNBIT;
813
    }
814
}
815

    
816
uint32_t HELPER(get_macu)(uint64_t val)
817
{
818
    if ((val >> 32) == 0) {
819
        return (uint32_t)val;
820
    } else {
821
        return 0xffffffffu;
822
    }
823
}
824

    
825
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
826
{
827
    uint32_t val;
828
    val = env->macc[acc] & 0x00ff;
829
    val = (env->macc[acc] >> 32) & 0xff00;
830
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
831
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
832
    return val;
833
}
834

    
835
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
836
{
837
    uint32_t val;
838
    val = (env->macc[acc] >> 32) & 0xffff;
839
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
840
    return val;
841
}
842

    
843
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
844
{
845
    int64_t res;
846
    int32_t tmp;
847
    res = env->macc[acc] & 0xffffffff00ull;
848
    tmp = (int16_t)(val & 0xff00);
849
    res |= ((int64_t)tmp) << 32;
850
    res |= val & 0xff;
851
    env->macc[acc] = res;
852
    res = env->macc[acc + 1] & 0xffffffff00ull;
853
    tmp = (val & 0xff000000);
854
    res |= ((int64_t)tmp) << 16;
855
    res |= (val >> 16) & 0xff;
856
    env->macc[acc + 1] = res;
857
}
858

    
859
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
860
{
861
    int64_t res;
862
    int32_t tmp;
863
    res = (uint32_t)env->macc[acc];
864
    tmp = (int16_t)val;
865
    res |= ((int64_t)tmp) << 32;
866
    env->macc[acc] = res;
867
    res = (uint32_t)env->macc[acc + 1];
868
    tmp = val & 0xffff0000;
869
    res |= (int64_t)tmp << 16;
870
    env->macc[acc + 1] = res;
871
}
872

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