Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 41db4607

History | View | Annotate | Download (22.5 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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 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
#include "gdbstub.h"
30

    
31
#include "helpers.h"
32

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

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

    
42
typedef struct m68k_def_t m68k_def_t;
43

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

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

    
57
static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
58
{
59
    if (n < 8) {
60
        stfq_p(mem_buf, env->fregs[n]);
61
        return 8;
62
    }
63
    if (n < 11) {
64
        /* FP control registers (not implemented)  */
65
        memset(mem_buf, 0, 4);
66
        return 4;
67
    }
68
    return 0;
69
}
70

    
71
static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
72
{
73
    if (n < 8) {
74
        env->fregs[n] = ldfq_p(mem_buf);
75
        return 8;
76
    }
77
    if (n < 11) {
78
        /* FP control registers (not implemented)  */
79
        return 4;
80
    }
81
    return 0;
82
}
83

    
84
static void m68k_set_feature(CPUM68KState *env, int feature)
85
{
86
    env->features |= (1u << feature);
87
}
88

    
89
static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
90
{
91
    m68k_def_t *def;
92

    
93
    for (def = m68k_cpu_defs; def->name; def++) {
94
        if (strcmp(def->name, name) == 0)
95
            break;
96
    }
97
    if (!def->name)
98
        return -1;
99

    
100
    switch (def->id) {
101
    case M68K_CPUID_M5206:
102
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
103
        break;
104
    case M68K_CPUID_M5208:
105
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
106
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
107
        m68k_set_feature(env, M68K_FEATURE_BRAL);
108
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
109
        m68k_set_feature(env, M68K_FEATURE_USP);
110
        break;
111
    case M68K_CPUID_CFV4E:
112
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
113
        m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
114
        m68k_set_feature(env, M68K_FEATURE_BRAL);
115
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
116
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117
        m68k_set_feature(env, M68K_FEATURE_USP);
118
        break;
119
    case M68K_CPUID_ANY:
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_CF_ISA_APLUSC);
123
        m68k_set_feature(env, M68K_FEATURE_BRAL);
124
        m68k_set_feature(env, M68K_FEATURE_CF_FPU);
125
        /* MAC and EMAC are mututally exclusive, so pick EMAC.
126
           It's mostly backwards compatible.  */
127
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
128
        m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
129
        m68k_set_feature(env, M68K_FEATURE_USP);
130
        m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
131
        m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
132
        break;
133
    }
134

    
135
    register_m68k_insns(env);
136
    if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
137
        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
138
                                 11, "cf-fp.xml", 18);
139
    }
140
    /* TODO: Add [E]MAC registers.  */
141
    return 0;
142
}
143

    
144
void cpu_reset(CPUM68KState *env)
145
{
146
    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
147
        qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
148
        log_cpu_state(env, 0);
149
    }
150

    
151
    memset(env, 0, offsetof(CPUM68KState, breakpoints));
152
#if !defined (CONFIG_USER_ONLY)
153
    env->sr = 0x2700;
154
#endif
155
    m68k_switch_sp(env);
156
    /* ??? FP regs should be initialized to NaN.  */
157
    env->cc_op = CC_OP_FLAGS;
158
    /* TODO: We should set PC from the interrupt vector.  */
159
    env->pc = 0;
160
    tlb_flush(env, 1);
161
}
162

    
163
CPUM68KState *cpu_m68k_init(const char *cpu_model)
164
{
165
    CPUM68KState *env;
166
    static int inited;
167

    
168
    env = qemu_mallocz(sizeof(CPUM68KState));
169
    cpu_exec_init(env);
170
    if (!inited) {
171
        inited = 1;
172
        m68k_tcg_init();
173
    }
174

    
175
    env->cpu_model_str = cpu_model;
176

    
177
    if (cpu_m68k_set_model(env, cpu_model) < 0) {
178
        cpu_m68k_close(env);
179
        return NULL;
180
    }
181

    
182
    cpu_reset(env);
183
    return env;
184
}
185

    
186
void cpu_m68k_close(CPUM68KState *env)
187
{
188
    qemu_free(env);
189
}
190

    
191
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
192
{
193
    int flags;
194
    uint32_t src;
195
    uint32_t dest;
196
    uint32_t tmp;
197

    
198
#define HIGHBIT 0x80000000u
199

    
200
#define SET_NZ(x) do { \
201
    if ((x) == 0) \
202
        flags |= CCF_Z; \
203
    else if ((int32_t)(x) < 0) \
204
        flags |= CCF_N; \
205
    } while (0)
206

    
207
#define SET_FLAGS_SUB(type, utype) do { \
208
    SET_NZ((type)dest); \
209
    tmp = dest + src; \
210
    if ((utype) tmp < (utype) src) \
211
        flags |= CCF_C; \
212
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
213
        flags |= CCF_V; \
214
    } while (0)
215

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

    
271
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
272
{
273
    switch (reg) {
274
    case 0x02: /* CACR */
275
        env->cacr = val;
276
        m68k_switch_sp(env);
277
        break;
278
    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
279
        /* TODO: Implement Access Control Registers.  */
280
        break;
281
    case 0x801: /* VBR */
282
        env->vbr = val;
283
        break;
284
    /* TODO: Implement control registers.  */
285
    default:
286
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
287
                  reg, val);
288
    }
289
}
290

    
291
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
292
{
293
    uint32_t acc;
294
    int8_t exthigh;
295
    uint8_t extlow;
296
    uint64_t regval;
297
    int i;
298
    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
299
        for (i = 0; i < 4; i++) {
300
            regval = env->macc[i];
301
            exthigh = regval >> 40;
302
            if (env->macsr & MACSR_FI) {
303
                acc = regval >> 8;
304
                extlow = regval;
305
            } else {
306
                acc = regval;
307
                extlow = regval >> 32;
308
            }
309
            if (env->macsr & MACSR_FI) {
310
                regval = (((uint64_t)acc) << 8) | extlow;
311
                regval |= ((int64_t)exthigh) << 40;
312
            } else if (env->macsr & MACSR_SU) {
313
                regval = acc | (((int64_t)extlow) << 32);
314
                regval |= ((int64_t)exthigh) << 40;
315
            } else {
316
                regval = acc | (((uint64_t)extlow) << 32);
317
                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
318
            }
319
            env->macc[i] = regval;
320
        }
321
    }
322
    env->macsr = val;
323
}
324

    
325
void m68k_switch_sp(CPUM68KState *env)
326
{
327
    int new_sp;
328

    
329
    env->sp[env->current_sp] = env->aregs[7];
330
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
331
             ? M68K_SSP : M68K_USP;
332
    env->aregs[7] = env->sp[new_sp];
333
    env->current_sp = new_sp;
334
}
335

    
336
/* MMU */
337

    
338
/* TODO: This will need fixing once the MMU is implemented.  */
339
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
340
{
341
    return addr;
342
}
343

    
344
#if defined(CONFIG_USER_ONLY)
345

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

    
354
#else
355

    
356
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
357
                               int mmu_idx, int is_softmmu)
358
{
359
    int prot;
360

    
361
    address &= TARGET_PAGE_MASK;
362
    prot = PAGE_READ | PAGE_WRITE;
363
    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
364
}
365

    
366
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
367
   be handled by the interrupt controller.  Real hardware only requests
368
   the vector when the interrupt is acknowledged by the CPU.  For
369
   simplicitly we calculate it when the interrupt is signalled.  */
370
void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
371
{
372
    env->pending_level = level;
373
    env->pending_vector = vector;
374
    if (level)
375
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
376
    else
377
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
378
}
379

    
380
#endif
381

    
382
uint32_t HELPER(bitrev)(uint32_t x)
383
{
384
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
385
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
386
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
387
    return bswap32(x);
388
}
389

    
390
uint32_t HELPER(ff1)(uint32_t x)
391
{
392
    int n;
393
    for (n = 32; x; n--)
394
        x >>= 1;
395
    return n;
396
}
397

    
398
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
399
{
400
    /* The result has the opposite sign to the original value.  */
401
    if (ccr & CCF_V)
402
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
403
    return val;
404
}
405

    
406
uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
407
{
408
    uint32_t res;
409
    uint32_t old_flags;
410

    
411
    old_flags = env->cc_dest;
412
    if (env->cc_x) {
413
        env->cc_x = (op1 <= op2);
414
        env->cc_op = CC_OP_SUBX;
415
        res = op1 - (op2 + 1);
416
    } else {
417
        env->cc_x = (op1 < op2);
418
        env->cc_op = CC_OP_SUB;
419
        res = op1 - op2;
420
    }
421
    env->cc_dest = res;
422
    env->cc_src = op2;
423
    cpu_m68k_flush_flags(env, env->cc_op);
424
    /* !Z is sticky.  */
425
    env->cc_dest &= (old_flags | ~CCF_Z);
426
    return res;
427
}
428

    
429
uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
430
{
431
    uint32_t res;
432
    uint32_t old_flags;
433

    
434
    old_flags = env->cc_dest;
435
    if (env->cc_x) {
436
        res = op1 + op2 + 1;
437
        env->cc_x = (res <= op2);
438
        env->cc_op = CC_OP_ADDX;
439
    } else {
440
        res = op1 + op2;
441
        env->cc_x = (res < op2);
442
        env->cc_op = CC_OP_ADD;
443
    }
444
    env->cc_dest = res;
445
    env->cc_src = op2;
446
    cpu_m68k_flush_flags(env, env->cc_op);
447
    /* !Z is sticky.  */
448
    env->cc_dest &= (old_flags | ~CCF_Z);
449
    return res;
450
}
451

    
452
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
453
{
454
    return a < b;
455
}
456

    
457
void HELPER(set_sr)(CPUState *env, uint32_t val)
458
{
459
    env->sr = val & 0xffff;
460
    m68k_switch_sp(env);
461
}
462

    
463
uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
464
{
465
    uint32_t result;
466
    uint32_t cf;
467

    
468
    shift &= 63;
469
    if (shift == 0) {
470
        result = val;
471
        cf = env->cc_src & CCF_C;
472
    } else if (shift < 32) {
473
        result = val << shift;
474
        cf = (val >> (32 - shift)) & 1;
475
    } else if (shift == 32) {
476
        result = 0;
477
        cf = val & 1;
478
    } else /* shift > 32 */ {
479
        result = 0;
480
        cf = 0;
481
    }
482
    env->cc_src = cf;
483
    env->cc_x = (cf != 0);
484
    env->cc_dest = result;
485
    return result;
486
}
487

    
488
uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
489
{
490
    uint32_t result;
491
    uint32_t cf;
492

    
493
    shift &= 63;
494
    if (shift == 0) {
495
        result = val;
496
        cf = env->cc_src & CCF_C;
497
    } else if (shift < 32) {
498
        result = val >> shift;
499
        cf = (val >> (shift - 1)) & 1;
500
    } else if (shift == 32) {
501
        result = 0;
502
        cf = val >> 31;
503
    } else /* shift > 32 */ {
504
        result = 0;
505
        cf = 0;
506
    }
507
    env->cc_src = cf;
508
    env->cc_x = (cf != 0);
509
    env->cc_dest = result;
510
    return result;
511
}
512

    
513
uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
514
{
515
    uint32_t result;
516
    uint32_t cf;
517

    
518
    shift &= 63;
519
    if (shift == 0) {
520
        result = val;
521
        cf = (env->cc_src & CCF_C) != 0;
522
    } else if (shift < 32) {
523
        result = (int32_t)val >> shift;
524
        cf = (val >> (shift - 1)) & 1;
525
    } else /* shift >= 32 */ {
526
        result = (int32_t)val >> 31;
527
        cf = val >> 31;
528
    }
529
    env->cc_src = cf;
530
    env->cc_x = cf;
531
    env->cc_dest = result;
532
    return result;
533
}
534

    
535
/* FPU helpers.  */
536
uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
537
{
538
    return float64_to_int32(val, &env->fp_status);
539
}
540

    
541
float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
542
{
543
    return float64_to_float32(val, &env->fp_status);
544
}
545

    
546
float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
547
{
548
    return int32_to_float64(val, &env->fp_status);
549
}
550

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

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

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

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

    
571
float64 HELPER(abs_f64)(float64 val)
572
{
573
    return float64_abs(val);
574
}
575

    
576
float64 HELPER(chs_f64)(float64 val)
577
{
578
    return float64_chs(val);
579
}
580

    
581
float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
582
{
583
    return float64_add(a, b, &env->fp_status);
584
}
585

    
586
float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
587
{
588
    return float64_sub(a, b, &env->fp_status);
589
}
590

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

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

    
601
float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
602
{
603
    /* ??? This may incorrectly raise exceptions.  */
604
    /* ??? Should flush denormals to zero.  */
605
    float64 res;
606
    res = float64_sub(a, b, &env->fp_status);
607
    if (float64_is_nan(res)) {
608
        /* +/-inf compares equal against itself, but sub returns nan.  */
609
        if (!float64_is_nan(a)
610
            && !float64_is_nan(b)) {
611
            res = float64_zero;
612
            if (float64_lt_quiet(a, res, &env->fp_status))
613
                res = float64_chs(res);
614
        }
615
    }
616
    return res;
617
}
618

    
619
uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
620
{
621
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
622
}
623

    
624
/* MAC unit.  */
625
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
626
   take values,  others take register numbers and manipulate the contents
627
   in-place.  */
628
void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
629
{
630
    uint32_t mask;
631
    env->macc[dest] = env->macc[src];
632
    mask = MACSR_PAV0 << dest;
633
    if (env->macsr & (MACSR_PAV0 << src))
634
        env->macsr |= mask;
635
    else
636
        env->macsr &= ~mask;
637
}
638

    
639
uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
640
{
641
    int64_t product;
642
    int64_t res;
643

    
644
    product = (uint64_t)op1 * op2;
645
    res = (product << 24) >> 24;
646
    if (res != product) {
647
        env->macsr |= MACSR_V;
648
        if (env->macsr & MACSR_OMC) {
649
            /* Make sure the accumulate operation overflows.  */
650
            if (product < 0)
651
                res = ~(1ll << 50);
652
            else
653
                res = 1ll << 50;
654
        }
655
    }
656
    return res;
657
}
658

    
659
uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
660
{
661
    uint64_t product;
662

    
663
    product = (uint64_t)op1 * op2;
664
    if (product & (0xffffffull << 40)) {
665
        env->macsr |= MACSR_V;
666
        if (env->macsr & MACSR_OMC) {
667
            /* Make sure the accumulate operation overflows.  */
668
            product = 1ll << 50;
669
        } else {
670
            product &= ((1ull << 40) - 1);
671
        }
672
    }
673
    return product;
674
}
675

    
676
uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
677
{
678
    uint64_t product;
679
    uint32_t remainder;
680

    
681
    product = (uint64_t)op1 * op2;
682
    if (env->macsr & MACSR_RT) {
683
        remainder = product & 0xffffff;
684
        product >>= 24;
685
        if (remainder > 0x800000)
686
            product++;
687
        else if (remainder == 0x800000)
688
            product += (product & 1);
689
    } else {
690
        product >>= 24;
691
    }
692
    return product;
693
}
694

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

    
716
void HELPER(macsatu)(CPUState *env, uint32_t acc)
717
{
718
    uint64_t val;
719

    
720
    val = env->macc[acc];
721
    if (val & (0xffffull << 48)) {
722
        env->macsr |= MACSR_V;
723
    }
724
    if (env->macsr & MACSR_V) {
725
        env->macsr |= MACSR_PAV0 << acc;
726
        if (env->macsr & MACSR_OMC) {
727
            if (val > (1ull << 53))
728
                val = 0;
729
            else
730
                val = (1ull << 48) - 1;
731
        } else {
732
            val &= ((1ull << 48) - 1);
733
        }
734
    }
735
    env->macc[acc] = val;
736
}
737

    
738
void HELPER(macsatf)(CPUState *env, uint32_t acc)
739
{
740
    int64_t sum;
741
    int64_t result;
742

    
743
    sum = env->macc[acc];
744
    result = (sum << 16) >> 16;
745
    if (result != sum) {
746
        env->macsr |= MACSR_V;
747
    }
748
    if (env->macsr & MACSR_V) {
749
        env->macsr |= MACSR_PAV0 << acc;
750
        if (env->macsr & MACSR_OMC) {
751
            result = (result >> 63) ^ 0x7fffffffffffll;
752
        }
753
    }
754
    env->macc[acc] = result;
755
}
756

    
757
void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
758
{
759
    uint64_t val;
760
    val = env->macc[acc];
761
    if (val == 0)
762
        env->macsr |= MACSR_Z;
763
    else if (val & (1ull << 47));
764
        env->macsr |= MACSR_N;
765
    if (env->macsr & (MACSR_PAV0 << acc)) {
766
        env->macsr |= MACSR_V;
767
    }
768
    if (env->macsr & MACSR_FI) {
769
        val = ((int64_t)val) >> 40;
770
        if (val != 0 && val != -1)
771
            env->macsr |= MACSR_EV;
772
    } else if (env->macsr & MACSR_SU) {
773
        val = ((int64_t)val) >> 32;
774
        if (val != 0 && val != -1)
775
            env->macsr |= MACSR_EV;
776
    } else {
777
        if ((val >> 32) != 0)
778
            env->macsr |= MACSR_EV;
779
    }
780
}
781

    
782
void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
783
{
784
    cpu_m68k_flush_flags(env, cc_op);
785
}
786

    
787
uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
788
{
789
    int rem;
790
    uint32_t result;
791

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

    
838
uint32_t HELPER(get_macs)(uint64_t val)
839
{
840
    if (val == (int32_t)val) {
841
        return (int32_t)val;
842
    } else {
843
        return (val >> 61) ^ ~SIGNBIT;
844
    }
845
}
846

    
847
uint32_t HELPER(get_macu)(uint64_t val)
848
{
849
    if ((val >> 32) == 0) {
850
        return (uint32_t)val;
851
    } else {
852
        return 0xffffffffu;
853
    }
854
}
855

    
856
uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
857
{
858
    uint32_t val;
859
    val = env->macc[acc] & 0x00ff;
860
    val = (env->macc[acc] >> 32) & 0xff00;
861
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
862
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
863
    return val;
864
}
865

    
866
uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
867
{
868
    uint32_t val;
869
    val = (env->macc[acc] >> 32) & 0xffff;
870
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
871
    return val;
872
}
873

    
874
void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
875
{
876
    int64_t res;
877
    int32_t tmp;
878
    res = env->macc[acc] & 0xffffffff00ull;
879
    tmp = (int16_t)(val & 0xff00);
880
    res |= ((int64_t)tmp) << 32;
881
    res |= val & 0xff;
882
    env->macc[acc] = res;
883
    res = env->macc[acc + 1] & 0xffffffff00ull;
884
    tmp = (val & 0xff000000);
885
    res |= ((int64_t)tmp) << 16;
886
    res |= (val >> 16) & 0xff;
887
    env->macc[acc + 1] = res;
888
}
889

    
890
void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
891
{
892
    int64_t res;
893
    int32_t tmp;
894
    res = (uint32_t)env->macc[acc];
895
    tmp = (int16_t)val;
896
    res |= ((int64_t)tmp) << 32;
897
    env->macc[acc] = res;
898
    res = (uint32_t)env->macc[acc + 1];
899
    tmp = val & 0xffff0000;
900
    res |= (int64_t)tmp << 16;
901
    env->macc[acc + 1] = res;
902
}
903

    
904
void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
905
{
906
    uint64_t res;
907
    res = (uint32_t)env->macc[acc];
908
    res |= ((uint64_t)(val & 0xffff)) << 32;
909
    env->macc[acc] = res;
910
    res = (uint32_t)env->macc[acc + 1];
911
    res |= (uint64_t)(val & 0xffff0000) << 16;
912
    env->macc[acc + 1] = res;
913
}