Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ 7267c094

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 "qemu-common.h"
27
#include "gdbstub.h"
28

    
29
#include "helpers.h"
30

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

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

    
40
typedef struct m68k_def_t m68k_def_t;
41

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

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

    
55
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
56
{
57
    unsigned int i;
58

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

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

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

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

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

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

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

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

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

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

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

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

    
182
    env->cpu_model_str = cpu_model;
183

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

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

    
194
void cpu_m68k_close(CPUM68KState *env)
195
{
196
    g_free(env);
197
}
198

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

    
206
#define HIGHBIT 0x80000000u
207

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

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

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

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

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

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

    
337
    env->sp[env->current_sp] = env->aregs[7];
338
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
339
             ? M68K_SSP : M68K_USP;
340
    env->aregs[7] = env->sp[new_sp];
341
    env->current_sp = new_sp;
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)
348
{
349
    env->exception_index = EXCP_ACCESS;
350
    env->mmu.ar = address;
351
    return 1;
352
}
353

    
354
#else
355

    
356
/* MMU */
357

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

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

    
369
    address &= TARGET_PAGE_MASK;
370
    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
371
    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
372
    return 0;
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_quiet_nan(res)) {
617
        /* +/-inf compares equal against itself, but sub returns nan.  */
618
        if (!float64_is_quiet_nan(a)
619
            && !float64_is_quiet_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 occurring
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
    }
775
    if (env->macsr & (MACSR_PAV0 << acc)) {
776
        env->macsr |= MACSR_V;
777
    }
778
    if (env->macsr & MACSR_FI) {
779
        val = ((int64_t)val) >> 40;
780
        if (val != 0 && val != -1)
781
            env->macsr |= MACSR_EV;
782
    } else if (env->macsr & MACSR_SU) {
783
        val = ((int64_t)val) >> 32;
784
        if (val != 0 && val != -1)
785
            env->macsr |= MACSR_EV;
786
    } else {
787
        if ((val >> 32) != 0)
788
            env->macsr |= MACSR_EV;
789
    }
790
}
791

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

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

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

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

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

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

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

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

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

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