Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 0bf46a40

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
    qemu_init_vcpu(env);
184
    return env;
185
}
186

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

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

    
199
#define HIGHBIT 0x80000000u
200

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

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

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

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

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

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

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

    
337
/* MMU */
338

    
339
/* TODO: This will need fixing once the MMU is implemented.  */
340
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
341
{
342
    return addr;
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
int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
358
                               int mmu_idx, int is_softmmu)
359
{
360
    int prot;
361

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

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

    
381
#endif
382

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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