Statistics
| Branch: | Revision:

root / target-m68k / helper.c @ c94a7c69

History | View | Annotate | Download (21.1 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 "cpu.h"
22
#include "exec/gdbstub.h"
23

    
24
#include "helpers.h"
25

    
26
#define SIGNBIT (1u << 31)
27

    
28
/* Sort alphabetically, except for "any". */
29
static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
30
{
31
    ObjectClass *class_a = (ObjectClass *)a;
32
    ObjectClass *class_b = (ObjectClass *)b;
33
    const char *name_a, *name_b;
34

    
35
    name_a = object_class_get_name(class_a);
36
    name_b = object_class_get_name(class_b);
37
    if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
38
        return 1;
39
    } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
40
        return -1;
41
    } else {
42
        return strcasecmp(name_a, name_b);
43
    }
44
}
45

    
46
static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
47
{
48
    ObjectClass *c = data;
49
    CPUListState *s = user_data;
50
    const char *typename;
51
    char *name;
52

    
53
    typename = object_class_get_name(c);
54
    name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
55
    (*s->cpu_fprintf)(s->file, "%s\n",
56
                      name);
57
    g_free(name);
58
}
59

    
60
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
61
{
62
    CPUListState s = {
63
        .file = f,
64
        .cpu_fprintf = cpu_fprintf,
65
    };
66
    GSList *list;
67

    
68
    list = object_class_get_list(TYPE_M68K_CPU, false);
69
    list = g_slist_sort(list, m68k_cpu_list_compare);
70
    g_slist_foreach(list, m68k_cpu_list_entry, &s);
71
    g_slist_free(list);
72
}
73

    
74
static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
75
{
76
    if (n < 8) {
77
        stfq_p(mem_buf, env->fregs[n]);
78
        return 8;
79
    }
80
    if (n < 11) {
81
        /* FP control registers (not implemented)  */
82
        memset(mem_buf, 0, 4);
83
        return 4;
84
    }
85
    return 0;
86
}
87

    
88
static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
89
{
90
    if (n < 8) {
91
        env->fregs[n] = ldfq_p(mem_buf);
92
        return 8;
93
    }
94
    if (n < 11) {
95
        /* FP control registers (not implemented)  */
96
        return 4;
97
    }
98
    return 0;
99
}
100

    
101
M68kCPU *cpu_m68k_init(const char *cpu_model)
102
{
103
    M68kCPU *cpu;
104
    CPUM68KState *env;
105
    ObjectClass *oc;
106

    
107
    oc = cpu_class_by_name(TYPE_M68K_CPU, cpu_model);
108
    if (oc == NULL) {
109
        return NULL;
110
    }
111
    cpu = M68K_CPU(object_new(object_class_get_name(oc)));
112
    env = &cpu->env;
113
    env->cpu_model_str = cpu_model;
114

    
115
    register_m68k_insns(env);
116

    
117
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
118

    
119
    return cpu;
120
}
121

    
122
void m68k_cpu_init_gdb(M68kCPU *cpu)
123
{
124
    CPUM68KState *env = &cpu->env;
125

    
126
    if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
127
        gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
128
                                 11, "cf-fp.xml", 18);
129
    }
130
    /* TODO: Add [E]MAC registers.  */
131
}
132

    
133
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
134
{
135
    int flags;
136
    uint32_t src;
137
    uint32_t dest;
138
    uint32_t tmp;
139

    
140
#define HIGHBIT 0x80000000u
141

    
142
#define SET_NZ(x) do { \
143
    if ((x) == 0) \
144
        flags |= CCF_Z; \
145
    else if ((int32_t)(x) < 0) \
146
        flags |= CCF_N; \
147
    } while (0)
148

    
149
#define SET_FLAGS_SUB(type, utype) do { \
150
    SET_NZ((type)dest); \
151
    tmp = dest + src; \
152
    if ((utype) tmp < (utype) src) \
153
        flags |= CCF_C; \
154
    if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
155
        flags |= CCF_V; \
156
    } while (0)
157

    
158
    flags = 0;
159
    src = env->cc_src;
160
    dest = env->cc_dest;
161
    switch (cc_op) {
162
    case CC_OP_FLAGS:
163
        flags = dest;
164
        break;
165
    case CC_OP_LOGIC:
166
        SET_NZ(dest);
167
        break;
168
    case CC_OP_ADD:
169
        SET_NZ(dest);
170
        if (dest < src)
171
            flags |= CCF_C;
172
        tmp = dest - src;
173
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
174
            flags |= CCF_V;
175
        break;
176
    case CC_OP_SUB:
177
        SET_FLAGS_SUB(int32_t, uint32_t);
178
        break;
179
    case CC_OP_CMPB:
180
        SET_FLAGS_SUB(int8_t, uint8_t);
181
        break;
182
    case CC_OP_CMPW:
183
        SET_FLAGS_SUB(int16_t, uint16_t);
184
        break;
185
    case CC_OP_ADDX:
186
        SET_NZ(dest);
187
        if (dest <= src)
188
            flags |= CCF_C;
189
        tmp = dest - src - 1;
190
        if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
191
            flags |= CCF_V;
192
        break;
193
    case CC_OP_SUBX:
194
        SET_NZ(dest);
195
        tmp = dest + src + 1;
196
        if (tmp <= src)
197
            flags |= CCF_C;
198
        if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
199
            flags |= CCF_V;
200
        break;
201
    case CC_OP_SHIFT:
202
        SET_NZ(dest);
203
        if (src)
204
            flags |= CCF_C;
205
        break;
206
    default:
207
        cpu_abort(env, "Bad CC_OP %d", cc_op);
208
    }
209
    env->cc_op = CC_OP_FLAGS;
210
    env->cc_dest = flags;
211
}
212

    
213
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
214
{
215
    switch (reg) {
216
    case 0x02: /* CACR */
217
        env->cacr = val;
218
        m68k_switch_sp(env);
219
        break;
220
    case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
221
        /* TODO: Implement Access Control Registers.  */
222
        break;
223
    case 0x801: /* VBR */
224
        env->vbr = val;
225
        break;
226
    /* TODO: Implement control registers.  */
227
    default:
228
        cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
229
                  reg, val);
230
    }
231
}
232

    
233
void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
234
{
235
    uint32_t acc;
236
    int8_t exthigh;
237
    uint8_t extlow;
238
    uint64_t regval;
239
    int i;
240
    if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
241
        for (i = 0; i < 4; i++) {
242
            regval = env->macc[i];
243
            exthigh = regval >> 40;
244
            if (env->macsr & MACSR_FI) {
245
                acc = regval >> 8;
246
                extlow = regval;
247
            } else {
248
                acc = regval;
249
                extlow = regval >> 32;
250
            }
251
            if (env->macsr & MACSR_FI) {
252
                regval = (((uint64_t)acc) << 8) | extlow;
253
                regval |= ((int64_t)exthigh) << 40;
254
            } else if (env->macsr & MACSR_SU) {
255
                regval = acc | (((int64_t)extlow) << 32);
256
                regval |= ((int64_t)exthigh) << 40;
257
            } else {
258
                regval = acc | (((uint64_t)extlow) << 32);
259
                regval |= ((uint64_t)(uint8_t)exthigh) << 40;
260
            }
261
            env->macc[i] = regval;
262
        }
263
    }
264
    env->macsr = val;
265
}
266

    
267
void m68k_switch_sp(CPUM68KState *env)
268
{
269
    int new_sp;
270

    
271
    env->sp[env->current_sp] = env->aregs[7];
272
    new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
273
             ? M68K_SSP : M68K_USP;
274
    env->aregs[7] = env->sp[new_sp];
275
    env->current_sp = new_sp;
276
}
277

    
278
#if defined(CONFIG_USER_ONLY)
279

    
280
int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
281
                               int mmu_idx)
282
{
283
    env->exception_index = EXCP_ACCESS;
284
    env->mmu.ar = address;
285
    return 1;
286
}
287

    
288
#else
289

    
290
/* MMU */
291

    
292
/* TODO: This will need fixing once the MMU is implemented.  */
293
hwaddr cpu_get_phys_page_debug(CPUM68KState *env, target_ulong addr)
294
{
295
    return addr;
296
}
297

    
298
int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
299
                               int mmu_idx)
300
{
301
    int prot;
302

    
303
    address &= TARGET_PAGE_MASK;
304
    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
305
    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
306
    return 0;
307
}
308

    
309
/* Notify CPU of a pending interrupt.  Prioritization and vectoring should
310
   be handled by the interrupt controller.  Real hardware only requests
311
   the vector when the interrupt is acknowledged by the CPU.  For
312
   simplicitly we calculate it when the interrupt is signalled.  */
313
void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
314
{
315
    CPUState *cs = CPU(cpu);
316
    CPUM68KState *env = &cpu->env;
317

    
318
    env->pending_level = level;
319
    env->pending_vector = vector;
320
    if (level) {
321
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
322
    } else {
323
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
324
    }
325
}
326

    
327
#endif
328

    
329
uint32_t HELPER(bitrev)(uint32_t x)
330
{
331
    x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
332
    x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
333
    x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
334
    return bswap32(x);
335
}
336

    
337
uint32_t HELPER(ff1)(uint32_t x)
338
{
339
    int n;
340
    for (n = 32; x; n--)
341
        x >>= 1;
342
    return n;
343
}
344

    
345
uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
346
{
347
    /* The result has the opposite sign to the original value.  */
348
    if (ccr & CCF_V)
349
        val = (((int32_t)val) >> 31) ^ SIGNBIT;
350
    return val;
351
}
352

    
353
uint32_t HELPER(subx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
354
{
355
    uint32_t res;
356
    uint32_t old_flags;
357

    
358
    old_flags = env->cc_dest;
359
    if (env->cc_x) {
360
        env->cc_x = (op1 <= op2);
361
        env->cc_op = CC_OP_SUBX;
362
        res = op1 - (op2 + 1);
363
    } else {
364
        env->cc_x = (op1 < op2);
365
        env->cc_op = CC_OP_SUB;
366
        res = op1 - op2;
367
    }
368
    env->cc_dest = res;
369
    env->cc_src = op2;
370
    cpu_m68k_flush_flags(env, env->cc_op);
371
    /* !Z is sticky.  */
372
    env->cc_dest &= (old_flags | ~CCF_Z);
373
    return res;
374
}
375

    
376
uint32_t HELPER(addx_cc)(CPUM68KState *env, uint32_t op1, uint32_t op2)
377
{
378
    uint32_t res;
379
    uint32_t old_flags;
380

    
381
    old_flags = env->cc_dest;
382
    if (env->cc_x) {
383
        res = op1 + op2 + 1;
384
        env->cc_x = (res <= op2);
385
        env->cc_op = CC_OP_ADDX;
386
    } else {
387
        res = op1 + op2;
388
        env->cc_x = (res < op2);
389
        env->cc_op = CC_OP_ADD;
390
    }
391
    env->cc_dest = res;
392
    env->cc_src = op2;
393
    cpu_m68k_flush_flags(env, env->cc_op);
394
    /* !Z is sticky.  */
395
    env->cc_dest &= (old_flags | ~CCF_Z);
396
    return res;
397
}
398

    
399
uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
400
{
401
    return a < b;
402
}
403

    
404
void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
405
{
406
    env->sr = val & 0xffff;
407
    m68k_switch_sp(env);
408
}
409

    
410
uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
411
{
412
    uint32_t result;
413
    uint32_t cf;
414

    
415
    shift &= 63;
416
    if (shift == 0) {
417
        result = val;
418
        cf = env->cc_src & CCF_C;
419
    } else if (shift < 32) {
420
        result = val << shift;
421
        cf = (val >> (32 - shift)) & 1;
422
    } else if (shift == 32) {
423
        result = 0;
424
        cf = val & 1;
425
    } else /* shift > 32 */ {
426
        result = 0;
427
        cf = 0;
428
    }
429
    env->cc_src = cf;
430
    env->cc_x = (cf != 0);
431
    env->cc_dest = result;
432
    return result;
433
}
434

    
435
uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
436
{
437
    uint32_t result;
438
    uint32_t cf;
439

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

    
460
uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
461
{
462
    uint32_t result;
463
    uint32_t cf;
464

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

    
482
/* FPU helpers.  */
483
uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val)
484
{
485
    return float64_to_int32(val, &env->fp_status);
486
}
487

    
488
float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val)
489
{
490
    return float64_to_float32(val, &env->fp_status);
491
}
492

    
493
float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val)
494
{
495
    return int32_to_float64(val, &env->fp_status);
496
}
497

    
498
float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val)
499
{
500
    return float32_to_float64(val, &env->fp_status);
501
}
502

    
503
float64 HELPER(iround_f64)(CPUM68KState *env, float64 val)
504
{
505
    return float64_round_to_int(val, &env->fp_status);
506
}
507

    
508
float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val)
509
{
510
    return float64_trunc_to_int(val, &env->fp_status);
511
}
512

    
513
float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val)
514
{
515
    return float64_sqrt(val, &env->fp_status);
516
}
517

    
518
float64 HELPER(abs_f64)(float64 val)
519
{
520
    return float64_abs(val);
521
}
522

    
523
float64 HELPER(chs_f64)(float64 val)
524
{
525
    return float64_chs(val);
526
}
527

    
528
float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b)
529
{
530
    return float64_add(a, b, &env->fp_status);
531
}
532

    
533
float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b)
534
{
535
    return float64_sub(a, b, &env->fp_status);
536
}
537

    
538
float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b)
539
{
540
    return float64_mul(a, b, &env->fp_status);
541
}
542

    
543
float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b)
544
{
545
    return float64_div(a, b, &env->fp_status);
546
}
547

    
548
float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b)
549
{
550
    /* ??? This may incorrectly raise exceptions.  */
551
    /* ??? Should flush denormals to zero.  */
552
    float64 res;
553
    res = float64_sub(a, b, &env->fp_status);
554
    if (float64_is_quiet_nan(res)) {
555
        /* +/-inf compares equal against itself, but sub returns nan.  */
556
        if (!float64_is_quiet_nan(a)
557
            && !float64_is_quiet_nan(b)) {
558
            res = float64_zero;
559
            if (float64_lt_quiet(a, res, &env->fp_status))
560
                res = float64_chs(res);
561
        }
562
    }
563
    return res;
564
}
565

    
566
uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val)
567
{
568
    return float64_compare_quiet(val, float64_zero, &env->fp_status);
569
}
570

    
571
/* MAC unit.  */
572
/* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
573
   take values,  others take register numbers and manipulate the contents
574
   in-place.  */
575
void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
576
{
577
    uint32_t mask;
578
    env->macc[dest] = env->macc[src];
579
    mask = MACSR_PAV0 << dest;
580
    if (env->macsr & (MACSR_PAV0 << src))
581
        env->macsr |= mask;
582
    else
583
        env->macsr &= ~mask;
584
}
585

    
586
uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
587
{
588
    int64_t product;
589
    int64_t res;
590

    
591
    product = (uint64_t)op1 * op2;
592
    res = (product << 24) >> 24;
593
    if (res != product) {
594
        env->macsr |= MACSR_V;
595
        if (env->macsr & MACSR_OMC) {
596
            /* Make sure the accumulate operation overflows.  */
597
            if (product < 0)
598
                res = ~(1ll << 50);
599
            else
600
                res = 1ll << 50;
601
        }
602
    }
603
    return res;
604
}
605

    
606
uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
607
{
608
    uint64_t product;
609

    
610
    product = (uint64_t)op1 * op2;
611
    if (product & (0xffffffull << 40)) {
612
        env->macsr |= MACSR_V;
613
        if (env->macsr & MACSR_OMC) {
614
            /* Make sure the accumulate operation overflows.  */
615
            product = 1ll << 50;
616
        } else {
617
            product &= ((1ull << 40) - 1);
618
        }
619
    }
620
    return product;
621
}
622

    
623
uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
624
{
625
    uint64_t product;
626
    uint32_t remainder;
627

    
628
    product = (uint64_t)op1 * op2;
629
    if (env->macsr & MACSR_RT) {
630
        remainder = product & 0xffffff;
631
        product >>= 24;
632
        if (remainder > 0x800000)
633
            product++;
634
        else if (remainder == 0x800000)
635
            product += (product & 1);
636
    } else {
637
        product >>= 24;
638
    }
639
    return product;
640
}
641

    
642
void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
643
{
644
    int64_t tmp;
645
    int64_t result;
646
    tmp = env->macc[acc];
647
    result = ((tmp << 16) >> 16);
648
    if (result != tmp) {
649
        env->macsr |= MACSR_V;
650
    }
651
    if (env->macsr & MACSR_V) {
652
        env->macsr |= MACSR_PAV0 << acc;
653
        if (env->macsr & MACSR_OMC) {
654
            /* The result is saturated to 32 bits, despite overflow occurring
655
               at 48 bits.  Seems weird, but that's what the hardware docs
656
               say.  */
657
            result = (result >> 63) ^ 0x7fffffff;
658
        }
659
    }
660
    env->macc[acc] = result;
661
}
662

    
663
void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
664
{
665
    uint64_t val;
666

    
667
    val = env->macc[acc];
668
    if (val & (0xffffull << 48)) {
669
        env->macsr |= MACSR_V;
670
    }
671
    if (env->macsr & MACSR_V) {
672
        env->macsr |= MACSR_PAV0 << acc;
673
        if (env->macsr & MACSR_OMC) {
674
            if (val > (1ull << 53))
675
                val = 0;
676
            else
677
                val = (1ull << 48) - 1;
678
        } else {
679
            val &= ((1ull << 48) - 1);
680
        }
681
    }
682
    env->macc[acc] = val;
683
}
684

    
685
void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
686
{
687
    int64_t sum;
688
    int64_t result;
689

    
690
    sum = env->macc[acc];
691
    result = (sum << 16) >> 16;
692
    if (result != sum) {
693
        env->macsr |= MACSR_V;
694
    }
695
    if (env->macsr & MACSR_V) {
696
        env->macsr |= MACSR_PAV0 << acc;
697
        if (env->macsr & MACSR_OMC) {
698
            result = (result >> 63) ^ 0x7fffffffffffll;
699
        }
700
    }
701
    env->macc[acc] = result;
702
}
703

    
704
void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
705
{
706
    uint64_t val;
707
    val = env->macc[acc];
708
    if (val == 0) {
709
        env->macsr |= MACSR_Z;
710
    } else if (val & (1ull << 47)) {
711
        env->macsr |= MACSR_N;
712
    }
713
    if (env->macsr & (MACSR_PAV0 << acc)) {
714
        env->macsr |= MACSR_V;
715
    }
716
    if (env->macsr & MACSR_FI) {
717
        val = ((int64_t)val) >> 40;
718
        if (val != 0 && val != -1)
719
            env->macsr |= MACSR_EV;
720
    } else if (env->macsr & MACSR_SU) {
721
        val = ((int64_t)val) >> 32;
722
        if (val != 0 && val != -1)
723
            env->macsr |= MACSR_EV;
724
    } else {
725
        if ((val >> 32) != 0)
726
            env->macsr |= MACSR_EV;
727
    }
728
}
729

    
730
void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
731
{
732
    cpu_m68k_flush_flags(env, cc_op);
733
}
734

    
735
uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
736
{
737
    int rem;
738
    uint32_t result;
739

    
740
    if (env->macsr & MACSR_SU) {
741
        /* 16-bit rounding.  */
742
        rem = val & 0xffffff;
743
        val = (val >> 24) & 0xffffu;
744
        if (rem > 0x800000)
745
            val++;
746
        else if (rem == 0x800000)
747
            val += (val & 1);
748
    } else if (env->macsr & MACSR_RT) {
749
        /* 32-bit rounding.  */
750
        rem = val & 0xff;
751
        val >>= 8;
752
        if (rem > 0x80)
753
            val++;
754
        else if (rem == 0x80)
755
            val += (val & 1);
756
    } else {
757
        /* No rounding.  */
758
        val >>= 8;
759
    }
760
    if (env->macsr & MACSR_OMC) {
761
        /* Saturate.  */
762
        if (env->macsr & MACSR_SU) {
763
            if (val != (uint16_t) val) {
764
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
765
            } else {
766
                result = val & 0xffff;
767
            }
768
        } else {
769
            if (val != (uint32_t)val) {
770
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
771
            } else {
772
                result = (uint32_t)val;
773
            }
774
        }
775
    } else {
776
        /* No saturation.  */
777
        if (env->macsr & MACSR_SU) {
778
            result = val & 0xffff;
779
        } else {
780
            result = (uint32_t)val;
781
        }
782
    }
783
    return result;
784
}
785

    
786
uint32_t HELPER(get_macs)(uint64_t val)
787
{
788
    if (val == (int32_t)val) {
789
        return (int32_t)val;
790
    } else {
791
        return (val >> 61) ^ ~SIGNBIT;
792
    }
793
}
794

    
795
uint32_t HELPER(get_macu)(uint64_t val)
796
{
797
    if ((val >> 32) == 0) {
798
        return (uint32_t)val;
799
    } else {
800
        return 0xffffffffu;
801
    }
802
}
803

    
804
uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
805
{
806
    uint32_t val;
807
    val = env->macc[acc] & 0x00ff;
808
    val = (env->macc[acc] >> 32) & 0xff00;
809
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
810
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
811
    return val;
812
}
813

    
814
uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
815
{
816
    uint32_t val;
817
    val = (env->macc[acc] >> 32) & 0xffff;
818
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
819
    return val;
820
}
821

    
822
void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
823
{
824
    int64_t res;
825
    int32_t tmp;
826
    res = env->macc[acc] & 0xffffffff00ull;
827
    tmp = (int16_t)(val & 0xff00);
828
    res |= ((int64_t)tmp) << 32;
829
    res |= val & 0xff;
830
    env->macc[acc] = res;
831
    res = env->macc[acc + 1] & 0xffffffff00ull;
832
    tmp = (val & 0xff000000);
833
    res |= ((int64_t)tmp) << 16;
834
    res |= (val >> 16) & 0xff;
835
    env->macc[acc + 1] = res;
836
}
837

    
838
void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
839
{
840
    int64_t res;
841
    int32_t tmp;
842
    res = (uint32_t)env->macc[acc];
843
    tmp = (int16_t)val;
844
    res |= ((int64_t)tmp) << 32;
845
    env->macc[acc] = res;
846
    res = (uint32_t)env->macc[acc + 1];
847
    tmp = val & 0xffff0000;
848
    res |= (int64_t)tmp << 16;
849
    env->macc[acc + 1] = res;
850
}
851

    
852
void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
853
{
854
    uint64_t res;
855
    res = (uint32_t)env->macc[acc];
856
    res |= ((uint64_t)(val & 0xffff)) << 32;
857
    env->macc[acc] = res;
858
    res = (uint32_t)env->macc[acc + 1];
859
    res |= (uint64_t)(val & 0xffff0000) << 16;
860
    env->macc[acc + 1] = res;
861
}