Statistics
| Branch: | Revision:

root / target-m68k / op.c @ a7037b29

History | View | Annotate | Download (20.7 kB)

1
/*
2
 *  m68k micro operations
3
 * 
4
 *  Copyright (c) 2006-2007 CodeSourcery
5
 *  Written by Paul Brook
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21

    
22
#include "exec.h"
23
#include "m68k-qreg.h"
24

    
25
#ifndef offsetof
26
#define offsetof(type, field) ((size_t) &((type *)0)->field)
27
#endif
28

    
29
static long qreg_offsets[] = {
30
#define DEFO32(name, offset) offsetof(CPUState, offset),
31
#define DEFR(name, reg, mode) -1,
32
#define DEFF64(name, offset) offsetof(CPUState, offset),
33
    0,
34
#include "qregs.def"
35
};
36

    
37
#define CPU_FP_STATUS env->fp_status
38

    
39
#define RAISE_EXCEPTION(n) do { \
40
    env->exception_index = n; \
41
    cpu_loop_exit(); \
42
    } while(0)
43

    
44
#define get_op helper_get_op
45
#define set_op helper_set_op
46
#define get_opf64 helper_get_opf64
47
#define set_opf64 helper_set_opf64
48
uint32_t
49
get_op(int qreg)
50
{
51
    if (qreg >= TARGET_NUM_QREGS) {
52
        return env->qregs[qreg - TARGET_NUM_QREGS];
53
    } else if (qreg == QREG_T0) {
54
        return T0;
55
    } else {
56
        return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
57
    }
58
}
59

    
60
void set_op(int qreg, uint32_t val)
61
{
62
    if (qreg >= TARGET_NUM_QREGS) {
63
        env->qregs[qreg - TARGET_NUM_QREGS] = val;
64
    } else if (qreg == QREG_T0) {
65
        T0 = val;
66
    } else {
67
        *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
68
    }
69
}
70

    
71
float64 get_opf64(int qreg)
72
{
73
    if (qreg < TARGET_NUM_QREGS) {
74
        return *(float64 *)(((long)env) + qreg_offsets[qreg]);
75
    } else {
76
        return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
77
    }
78
}
79

    
80
void set_opf64(int qreg, float64 val)
81
{
82
    if (qreg < TARGET_NUM_QREGS) {
83
        *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
84
    } else {
85
        *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
86
    }
87
}
88

    
89
#define OP(name) void OPPROTO glue(op_,name) (void)
90

    
91
OP(mov32)
92
{
93
    set_op(PARAM1, get_op(PARAM2));
94
    FORCE_RET();
95
}
96

    
97
OP(mov32_im)
98
{
99
    set_op(PARAM1, PARAM2);
100
    FORCE_RET();
101
}
102

    
103
OP(movf64)
104
{
105
    set_opf64(PARAM1, get_opf64(PARAM2));
106
    FORCE_RET();
107
}
108

    
109
OP(zerof64)
110
{
111
    set_opf64(PARAM1, 0);
112
    FORCE_RET();
113
}
114

    
115
OP(add32)
116
{
117
    uint32_t op2 = get_op(PARAM2);
118
    uint32_t op3 = get_op(PARAM3);
119
    set_op(PARAM1, op2 + op3);
120
    FORCE_RET();
121
}
122

    
123
OP(sub32)
124
{
125
    uint32_t op2 = get_op(PARAM2);
126
    uint32_t op3 = get_op(PARAM3);
127
    set_op(PARAM1, op2 - op3);
128
    FORCE_RET();
129
}
130

    
131
OP(mul32)
132
{
133
    uint32_t op2 = get_op(PARAM2);
134
    uint32_t op3 = get_op(PARAM3);
135
    set_op(PARAM1, op2 * op3);
136
    FORCE_RET();
137
}
138

    
139
OP(not32)
140
{
141
    uint32_t arg = get_op(PARAM2);
142
    set_op(PARAM1, ~arg);
143
    FORCE_RET();
144
}
145

    
146
OP(neg32)
147
{
148
    uint32_t arg = get_op(PARAM2);
149
    set_op(PARAM1, -arg);
150
    FORCE_RET();
151
}
152

    
153
OP(bswap32)
154
{
155
    uint32_t arg = get_op(PARAM2);
156
    arg = (arg >> 24) | (arg << 24)
157
          | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
158
    set_op(PARAM1, arg);
159
    FORCE_RET();
160
}
161

    
162
OP(btest)
163
{
164
    uint32_t op1 = get_op(PARAM1);
165
    uint32_t op2 = get_op(PARAM2);
166
    if (op1 & op2)
167
        env->cc_dest &= ~CCF_Z;
168
    else
169
        env->cc_dest |= CCF_Z;
170
    FORCE_RET();
171
}
172

    
173
OP(ff1)
174
{
175
    uint32_t arg = get_op(PARAM2);
176
    int n;
177
    for (n = 32; arg; n--)
178
        arg >>= 1;
179
    set_op(PARAM1, n);
180
    FORCE_RET();
181
}
182

    
183
OP(subx_cc)
184
{
185
    uint32_t op1 = get_op(PARAM1);
186
    uint32_t op2 = get_op(PARAM2);
187
    uint32_t res;
188
    if (env->cc_x) {
189
        env->cc_x = (op1 <= op2);
190
        env->cc_op = CC_OP_SUBX;
191
        res = op1 - (op2 + 1);
192
    } else {
193
        env->cc_x = (op1 < op2);
194
        env->cc_op = CC_OP_SUB;
195
        res = op1 - op2;
196
    }
197
    set_op(PARAM1, res);
198
    FORCE_RET();
199
}
200

    
201
OP(addx_cc)
202
{
203
    uint32_t op1 = get_op(PARAM1);
204
    uint32_t op2 = get_op(PARAM2);
205
    uint32_t res;
206
    if (env->cc_x) {
207
        res = op1 + op2 + 1;
208
        env->cc_x = (res <= op2);
209
        env->cc_op = CC_OP_ADDX;
210
    } else {
211
        res = op1 + op2;
212
        env->cc_x = (res < op2);
213
        env->cc_op = CC_OP_ADD;
214
    }
215
    set_op(PARAM1, res);
216
    FORCE_RET();
217
}
218

    
219
/* Logic ops.  */
220

    
221
OP(and32)
222
{
223
    uint32_t op2 = get_op(PARAM2);
224
    uint32_t op3 = get_op(PARAM3);
225
    set_op(PARAM1, op2 & op3);
226
    FORCE_RET();
227
}
228

    
229
OP(or32)
230
{
231
    uint32_t op2 = get_op(PARAM2);
232
    uint32_t op3 = get_op(PARAM3);
233
    set_op(PARAM1, op2 | op3);
234
    FORCE_RET();
235
}
236

    
237
OP(xor32)
238
{
239
    uint32_t op2 = get_op(PARAM2);
240
    uint32_t op3 = get_op(PARAM3);
241
    set_op(PARAM1, op2 ^ op3);
242
    FORCE_RET();
243
}
244

    
245
/* Shifts.  */
246
OP(shl32)
247
{
248
    uint32_t op2 = get_op(PARAM2);
249
    uint32_t op3 = get_op(PARAM3);
250
    uint32_t result;
251
    result = op2 << op3;
252
    set_op(PARAM1, result);
253
    FORCE_RET();
254
}
255

    
256
OP(shl_cc)
257
{
258
    uint32_t op1 = get_op(PARAM1);
259
    uint32_t op2 = get_op(PARAM2);
260
    uint32_t result;
261
    result = op1 << op2;
262
    set_op(PARAM1, result);
263
    env->cc_x = (op1 << (op2 - 1)) & 1;
264
    FORCE_RET();
265
}
266

    
267
OP(shr32)
268
{
269
    uint32_t op2 = get_op(PARAM2);
270
    uint32_t op3 = get_op(PARAM3);
271
    uint32_t result;
272
    result = op2 >> op3;
273
    set_op(PARAM1, result);
274
    FORCE_RET();
275
}
276

    
277
OP(shr_cc)
278
{
279
    uint32_t op1 = get_op(PARAM1);
280
    uint32_t op2 = get_op(PARAM2);
281
    uint32_t result;
282
    result = op1 >> op2;
283
    set_op(PARAM1, result);
284
    env->cc_x = (op1 >> (op2 - 1)) & 1;
285
    FORCE_RET();
286
}
287

    
288
OP(sar32)
289
{
290
    int32_t op2 = get_op(PARAM2);
291
    uint32_t op3 = get_op(PARAM3);
292
    uint32_t result;
293
    result = op2 >> op3;
294
    set_op(PARAM1, result);
295
    FORCE_RET();
296
}
297

    
298
OP(sar_cc)
299
{
300
    int32_t op1 = get_op(PARAM1);
301
    uint32_t op2 = get_op(PARAM2);
302
    uint32_t result;
303
    result = op1 >> op2;
304
    set_op(PARAM1, result);
305
    env->cc_x = (op1 >> (op2 - 1)) & 1;
306
    FORCE_RET();
307
}
308

    
309
/* Value extend.  */
310

    
311
OP(ext8u32)
312
{
313
    uint32_t op2 = get_op(PARAM2);
314
    set_op(PARAM1, (uint8_t)op2);
315
    FORCE_RET();
316
}
317

    
318
OP(ext8s32)
319
{
320
    uint32_t op2 = get_op(PARAM2);
321
    set_op(PARAM1, (int8_t)op2);
322
    FORCE_RET();
323
}
324

    
325
OP(ext16u32)
326
{
327
    uint32_t op2 = get_op(PARAM2);
328
    set_op(PARAM1, (uint16_t)op2);
329
    FORCE_RET();
330
}
331

    
332
OP(ext16s32)
333
{
334
    uint32_t op2 = get_op(PARAM2);
335
    set_op(PARAM1, (int16_t)op2);
336
    FORCE_RET();
337
}
338

    
339
OP(flush_flags)
340
{
341
    int cc_op  = PARAM1;
342
    if (cc_op == CC_OP_DYNAMIC)
343
        cc_op = env->cc_op;
344
    cpu_m68k_flush_flags(env, cc_op);
345
    FORCE_RET();
346
}
347

    
348
OP(divu)
349
{
350
    uint32_t num;
351
    uint32_t den;
352
    uint32_t quot;
353
    uint32_t rem;
354
    uint32_t flags;
355
    
356
    num = env->div1;
357
    den = env->div2;
358
    /* ??? This needs to make sure the throwing location is accurate.  */
359
    if (den == 0)
360
        RAISE_EXCEPTION(EXCP_DIV0);
361
    quot = num / den;
362
    rem = num % den;
363
    flags = 0;
364
    /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
365
       the address of a symbol, and gcc knows symbols can't have address
366
       zero.  */
367
    if (PARAM1 == 2 && quot > 0xffff)
368
        flags |= CCF_V;
369
    if (quot == 0)
370
        flags |= CCF_Z;
371
    else if ((int32_t)quot < 0)
372
        flags |= CCF_N;
373
    env->div1 = quot;
374
    env->div2 = rem;
375
    env->cc_dest = flags;
376
    FORCE_RET();
377
}
378

    
379
OP(divs)
380
{
381
    int32_t num;
382
    int32_t den;
383
    int32_t quot;
384
    int32_t rem;
385
    int32_t flags;
386
    
387
    num = env->div1;
388
    den = env->div2;
389
    if (den == 0)
390
        RAISE_EXCEPTION(EXCP_DIV0);
391
    quot = num / den;
392
    rem = num % den;
393
    flags = 0;
394
    if (PARAM1 == 2 && quot != (int16_t)quot)
395
        flags |= CCF_V;
396
    if (quot == 0)
397
        flags |= CCF_Z;
398
    else if (quot < 0)
399
        flags |= CCF_N;
400
    env->div1 = quot;
401
    env->div2 = rem;
402
    env->cc_dest = flags;
403
    FORCE_RET();
404
}
405

    
406
/* Halt is special because it may be a semihosting call.  */
407
OP(halt)
408
{
409
    RAISE_EXCEPTION(EXCP_HALT_INSN);
410
    FORCE_RET();
411
}
412

    
413
OP(stop)
414
{
415
    env->halted = 1;
416
    RAISE_EXCEPTION(EXCP_HLT);
417
    FORCE_RET();
418
}
419

    
420
OP(raise_exception)
421
{
422
    RAISE_EXCEPTION(PARAM1);
423
    FORCE_RET();
424
}
425

    
426
/* Floating point comparison sets flags differently to other instructions.  */
427

    
428
OP(sub_cmpf64)
429
{
430
    float64 src0;
431
    float64 src1;
432
    src0 = get_opf64(PARAM2);
433
    src1 = get_opf64(PARAM3);
434
    set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
435
    FORCE_RET();
436
}
437

    
438
OP(update_xflag_tst)
439
{
440
    uint32_t op1 = get_op(PARAM1);
441
    env->cc_x = op1;
442
    FORCE_RET();
443
}
444

    
445
OP(update_xflag_lt)
446
{
447
    uint32_t op1 = get_op(PARAM1);
448
    uint32_t op2 = get_op(PARAM2);
449
    env->cc_x = (op1 < op2);
450
    FORCE_RET();
451
}
452

    
453
OP(get_xflag)
454
{
455
    set_op(PARAM1, env->cc_x);
456
    FORCE_RET();
457
}
458

    
459
OP(logic_cc)
460
{
461
    uint32_t op1 = get_op(PARAM1);
462
    env->cc_dest = op1;
463
    FORCE_RET();
464
}
465

    
466
OP(update_cc_add)
467
{
468
    uint32_t op1 = get_op(PARAM1);
469
    uint32_t op2 = get_op(PARAM2);
470
    env->cc_dest = op1;
471
    env->cc_src = op2;
472
    FORCE_RET();
473
}
474

    
475
OP(fp_result)
476
{
477
    env->fp_result = get_opf64(PARAM1);
478
    FORCE_RET();
479
}
480

    
481
OP(jmp)
482
{
483
    GOTO_LABEL_PARAM(1);
484
}
485

    
486
/* These ops involve a function call, which probably requires a stack frame
487
   and breaks things on some hosts.  */
488
OP(jmp_z32)
489
{
490
    uint32_t arg = get_op(PARAM1);
491
    if (arg == 0)
492
        GOTO_LABEL_PARAM(2);
493
    FORCE_RET();
494
}
495

    
496
OP(jmp_nz32)
497
{
498
    uint32_t arg = get_op(PARAM1);
499
    if (arg != 0)
500
        GOTO_LABEL_PARAM(2);
501
    FORCE_RET();
502
}
503

    
504
OP(jmp_s32)
505
{
506
    int32_t arg = get_op(PARAM1);
507
    if (arg < 0)
508
        GOTO_LABEL_PARAM(2);
509
    FORCE_RET();
510
}
511

    
512
OP(jmp_ns32)
513
{
514
    int32_t arg = get_op(PARAM1);
515
    if (arg >= 0)
516
        GOTO_LABEL_PARAM(2);
517
    FORCE_RET();
518
}
519

    
520
void OPPROTO op_goto_tb0(void)
521
{
522
    GOTO_TB(op_goto_tb0, PARAM1, 0);
523
}
524

    
525
void OPPROTO op_goto_tb1(void)
526
{
527
    GOTO_TB(op_goto_tb1, PARAM1, 1);
528
}
529

    
530
OP(exit_tb)
531
{
532
    EXIT_TB();
533
}
534

    
535

    
536
/* Floating point.  */
537
OP(f64_to_i32)
538
{
539
    set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
540
    FORCE_RET();
541
}
542

    
543
OP(f64_to_f32)
544
{
545
    union {
546
        float32 f;
547
        uint32_t i;
548
    } u;
549
    u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
550
    set_op(PARAM1, u.i);
551
    FORCE_RET();
552
}
553

    
554
OP(i32_to_f64)
555
{
556
    set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
557
    FORCE_RET();
558
}
559

    
560
OP(f32_to_f64)
561
{
562
    union {
563
        float32 f;
564
        uint32_t i;
565
    } u;
566
    u.i = get_op(PARAM2);
567
    set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
568
    FORCE_RET();
569
}
570

    
571
OP(absf64)
572
{
573
    float64 op0 = get_opf64(PARAM2);
574
    set_opf64(PARAM1, float64_abs(op0));
575
    FORCE_RET();
576
}
577

    
578
OP(chsf64)
579
{
580
    float64 op0 = get_opf64(PARAM2);
581
    set_opf64(PARAM1, float64_chs(op0));
582
    FORCE_RET();
583
}
584

    
585
OP(sqrtf64)
586
{
587
    float64 op0 = get_opf64(PARAM2);
588
    set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
589
    FORCE_RET();
590
}
591

    
592
OP(addf64)
593
{
594
    float64 op0 = get_opf64(PARAM2);
595
    float64 op1 = get_opf64(PARAM3);
596
    set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
597
    FORCE_RET();
598
}
599

    
600
OP(subf64)
601
{
602
    float64 op0 = get_opf64(PARAM2);
603
    float64 op1 = get_opf64(PARAM3);
604
    set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
605
    FORCE_RET();
606
}
607

    
608
OP(mulf64)
609
{
610
    float64 op0 = get_opf64(PARAM2);
611
    float64 op1 = get_opf64(PARAM3);
612
    set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
613
    FORCE_RET();
614
}
615

    
616
OP(divf64)
617
{
618
    float64 op0 = get_opf64(PARAM2);
619
    float64 op1 = get_opf64(PARAM3);
620
    set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
621
    FORCE_RET();
622
}
623

    
624
OP(iround_f64)
625
{
626
    float64 op0 = get_opf64(PARAM2);
627
    set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
628
    FORCE_RET();
629
}
630

    
631
OP(itrunc_f64)
632
{
633
    float64 op0 = get_opf64(PARAM2);
634
    set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
635
    FORCE_RET();
636
}
637

    
638
OP(compare_quietf64)
639
{
640
    float64 op0 = get_opf64(PARAM2);
641
    float64 op1 = get_opf64(PARAM3);
642
    set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
643
    FORCE_RET();
644
}
645

    
646
OP(movec)
647
{
648
    int op1 = get_op(PARAM1);
649
    uint32_t op2 = get_op(PARAM2);
650
    helper_movec(env, op1, op2);
651
}
652

    
653
/* Memory access.  */
654

    
655
#define MEMSUFFIX _raw
656
#include "op_mem.h"
657

    
658
#if !defined(CONFIG_USER_ONLY)
659
#define MEMSUFFIX _user
660
#include "op_mem.h"
661
#define MEMSUFFIX _kernel
662
#include "op_mem.h"
663
#endif
664

    
665
/* MAC unit.  */
666
/* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
667
   This results in fairly large ops (and sometimes other issues) on 32-bit
668
   hosts.  Maybe move most of them into helpers.  */
669
OP(macmuls)
670
{
671
    uint32_t op1 = get_op(PARAM1);
672
    uint32_t op2 = get_op(PARAM2);
673
    int64_t product;
674
    int64_t res;
675

    
676
    product = (uint64_t)op1 * op2;
677
    res = (product << 24) >> 24;
678
    if (res != product) {
679
        env->macsr |= MACSR_V;
680
        if (env->macsr & MACSR_OMC) {
681
            /* Make sure the accumulate operation overflows.  */
682
            if (product < 0)
683
                res = ~(1ll << 50);
684
            else
685
                res = 1ll << 50;
686
        }
687
    }
688
    env->mactmp = res;
689
    FORCE_RET();
690
}
691

    
692
OP(macmulu)
693
{
694
    uint32_t op1 = get_op(PARAM1);
695
    uint32_t op2 = get_op(PARAM2);
696
    uint64_t product;
697

    
698
    product = (uint64_t)op1 * op2;
699
    if (product & (0xffffffull << 40)) {
700
        env->macsr |= MACSR_V;
701
        if (env->macsr & MACSR_OMC) {
702
            /* Make sure the accumulate operation overflows.  */
703
            product = 1ll << 50;
704
        } else {
705
            product &= ((1ull << 40) - 1);
706
        }
707
    }
708
    env->mactmp = product;
709
    FORCE_RET();
710
}
711

    
712
OP(macmulf)
713
{
714
    int32_t op1 = get_op(PARAM1);
715
    int32_t op2 = get_op(PARAM2);
716
    uint64_t product;
717
    uint32_t remainder;
718

    
719
    product = (uint64_t)op1 * op2;
720
    if (env->macsr & MACSR_RT) {
721
        remainder = product & 0xffffff;
722
        product >>= 24;
723
        if (remainder > 0x800000)
724
            product++;
725
        else if (remainder == 0x800000)
726
            product += (product & 1);
727
    } else {
728
        product >>= 24;
729
    }
730
    env->mactmp = product;
731
    FORCE_RET();
732
}
733

    
734
OP(macshl)
735
{
736
    env->mactmp <<= 1;
737
}
738

    
739
OP(macshr)
740
{
741
    env->mactmp >>= 1;
742
}
743

    
744
OP(macadd)
745
{
746
    int acc = PARAM1;
747
    env->macc[acc] += env->mactmp;
748
    FORCE_RET();
749
}
750

    
751
OP(macsub)
752
{
753
    int acc = PARAM1;
754
    env->macc[acc] -= env->mactmp;
755
    FORCE_RET();
756
}
757

    
758
OP(macsats)
759
{
760
    int acc = PARAM1;
761
    int64_t sum;
762
    int64_t result;
763

    
764
    sum = env->macc[acc];
765
    result = (sum << 16) >> 16;
766
    if (result != sum) {
767
        env->macsr |= MACSR_V;
768
    }
769
    if (env->macsr & MACSR_V) {
770
        env->macsr |= MACSR_PAV0 << acc;
771
        if (env->macsr & MACSR_OMC) {
772
            /* The result is saturated to 32 bits, despite overflow occuring
773
               at 48 bits.  Seems weird, but that's what the hardware docs
774
               say.  */
775
            result = (result >> 63) ^ 0x7fffffff;
776
        }
777
    }
778
    env->macc[acc] = result;
779
    FORCE_RET();
780
}
781

    
782
OP(macsatu)
783
{
784
    int acc = PARAM1;
785
    uint64_t sum;
786

    
787
    sum = env->macc[acc];
788
    if (sum & (0xffffull << 48)) {
789
        env->macsr |= MACSR_V;
790
    }
791
    if (env->macsr & MACSR_V) {
792
        env->macsr |= MACSR_PAV0 << acc;
793
        if (env->macsr & MACSR_OMC) {
794
            if (sum > (1ull << 53))
795
                sum = 0;
796
            else
797
                sum = (1ull << 48) - 1;
798
        } else {
799
            sum &= ((1ull << 48) - 1);
800
        }
801
    }
802
    FORCE_RET();
803
}
804

    
805
OP(macsatf)
806
{
807
    int acc = PARAM1;
808
    int64_t sum;
809
    int64_t result;
810

    
811
    sum = env->macc[acc];
812
    result = (sum << 16) >> 16;
813
    if (result != sum) {
814
        env->macsr |= MACSR_V;
815
    }
816
    if (env->macsr & MACSR_V) {
817
        env->macsr |= MACSR_PAV0 << acc;
818
        if (env->macsr & MACSR_OMC) {
819
            result = (result >> 63) ^ 0x7fffffffffffll;
820
        }
821
    }
822
    env->macc[acc] = result;
823
    FORCE_RET();
824
}
825

    
826
OP(mac_clear_flags)
827
{
828
    env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV);
829
}
830

    
831
OP(mac_set_flags)
832
{
833
    int acc = PARAM1;
834
    uint64_t val;
835
    val = env->macc[acc];
836
    if (val == 0)
837
        env->macsr |= MACSR_Z;
838
    else if (val & (1ull << 47));
839
        env->macsr |= MACSR_N;
840
    if (env->macsr & (MACSR_PAV0 << acc)) {
841
        env->macsr |= MACSR_V;
842
    }
843
    if (env->macsr & MACSR_FI) {
844
        val = ((int64_t)val) >> 40;
845
        if (val != 0 && val != -1)
846
            env->macsr |= MACSR_EV;
847
    } else if (env->macsr & MACSR_SU) {
848
        val = ((int64_t)val) >> 32;
849
        if (val != 0 && val != -1)
850
            env->macsr |= MACSR_EV;
851
    } else {
852
        if ((val >> 32) != 0)
853
            env->macsr |= MACSR_EV;
854
    }
855
    FORCE_RET();
856
}
857

    
858
OP(get_macf)
859
{
860
    int acc = PARAM2;
861
    int64_t val;
862
    int rem;
863
    uint32_t result;
864

    
865
    val = env->macc[acc];
866
    if (env->macsr & MACSR_SU) {
867
        /* 16-bit rounding.  */
868
        rem = val & 0xffffff;
869
        val = (val >> 24) & 0xffffu;
870
        if (rem > 0x800000)
871
            val++;
872
        else if (rem == 0x800000)
873
            val += (val & 1);
874
    } else if (env->macsr & MACSR_RT) {
875
        /* 32-bit rounding.  */
876
        rem = val & 0xff;
877
        val >>= 8;
878
        if (rem > 0x80)
879
            val++;
880
        else if (rem == 0x80)
881
            val += (val & 1);
882
    } else {
883
        /* No rounding.  */
884
        val >>= 8;
885
    }
886
    if (env->macsr & MACSR_OMC) {
887
        /* Saturate.  */
888
        if (env->macsr & MACSR_SU) {
889
            if (val != (uint16_t) val) {
890
                result = ((val >> 63) ^ 0x7fff) & 0xffff;
891
            } else {
892
                result = val & 0xffff;
893
            }
894
        } else {
895
            if (val != (uint32_t)val) {
896
                result = ((uint32_t)(val >> 63) & 0x7fffffff);
897
            } else {
898
                result = (uint32_t)val;
899
            }
900
        }
901
    } else {
902
        /* No saturation.  */
903
        if (env->macsr & MACSR_SU) {
904
            result = val & 0xffff;
905
        } else {
906
            result = (uint32_t)val;
907
        }
908
    }
909
    set_op(PARAM1, result);
910
    FORCE_RET();
911
}
912

    
913
OP(get_maci)
914
{
915
    int acc = PARAM2;
916
    set_op(PARAM1, (uint32_t)env->macc[acc]);
917
    FORCE_RET();
918
}
919

    
920
OP(get_macs)
921
{
922
    int acc = PARAM2;
923
    int64_t val = env->macc[acc];
924
    uint32_t result;
925
    if (val == (int32_t)val) {
926
        result = (int32_t)val;
927
    } else {
928
        result = (val >> 61) ^ 0x7fffffff;
929
    }
930
    set_op(PARAM1, result);
931
    FORCE_RET();
932
}
933

    
934
OP(get_macu)
935
{
936
    int acc = PARAM2;
937
    uint64_t val = env->macc[acc];
938
    uint32_t result;
939
    if ((val >> 32) == 0) {
940
        result = (uint32_t)val;
941
    } else {
942
        result = 0xffffffffu;
943
    }
944
    set_op(PARAM1, result);
945
    FORCE_RET();
946
}
947

    
948
OP(clear_mac)
949
{
950
    int acc = PARAM1;
951

    
952
    env->macc[acc] = 0;
953
    env->macsr &= ~(MACSR_PAV0 << acc);
954
    FORCE_RET();
955
}
956

    
957
OP(move_mac)
958
{
959
    int dest = PARAM1;
960
    int src = PARAM2;
961
    uint32_t mask;
962
    env->macc[dest] = env->macc[src];
963
    mask = MACSR_PAV0 << dest;
964
    if (env->macsr & (MACSR_PAV0 << src))
965
        env->macsr |= mask;
966
    else
967
        env->macsr &= ~mask;
968
    FORCE_RET();
969
}
970

    
971
OP(get_mac_extf)
972
{
973
    uint32_t val;
974
    int acc = PARAM2;
975
    val = env->macc[acc] & 0x00ff;
976
    val = (env->macc[acc] >> 32) & 0xff00;
977
    val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
978
    val |= (env->macc[acc + 1] >> 16) & 0xff000000;
979
    set_op(PARAM1, val);
980
    FORCE_RET();
981
}
982

    
983
OP(get_mac_exti)
984
{
985
    uint32_t val;
986
    int acc = PARAM2;
987
    val = (env->macc[acc] >> 32) & 0xffff;
988
    val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
989
    set_op(PARAM1, val);
990
    FORCE_RET();
991
}
992

    
993
OP(set_macf)
994
{
995
    int acc = PARAM2;
996
    int32_t val = get_op(PARAM1);
997
    env->macc[acc] = ((int64_t)val) << 8;
998
    env->macsr &= ~(MACSR_PAV0 << acc);
999
    FORCE_RET();
1000
}
1001

    
1002
OP(set_macs)
1003
{
1004
    int acc = PARAM2;
1005
    int32_t val = get_op(PARAM1);
1006
    env->macc[acc] = val;
1007
    env->macsr &= ~(MACSR_PAV0 << acc);
1008
    FORCE_RET();
1009
}
1010

    
1011
OP(set_macu)
1012
{
1013
    int acc = PARAM2;
1014
    uint32_t val = get_op(PARAM1);
1015
    env->macc[acc] = val;
1016
    env->macsr &= ~(MACSR_PAV0 << acc);
1017
    FORCE_RET();
1018
}
1019

    
1020
OP(set_mac_extf)
1021
{
1022
    int acc = PARAM2;
1023
    int32_t val = get_op(PARAM1);
1024
    int64_t res;
1025
    int32_t tmp;
1026
    res = env->macc[acc] & 0xffffffff00ull;
1027
    tmp = (int16_t)(val & 0xff00);
1028
    res |= ((int64_t)tmp) << 32;
1029
    res |= val & 0xff;
1030
    env->macc[acc] = res;
1031
    res = env->macc[acc + 1] & 0xffffffff00ull;
1032
    tmp = (val & 0xff000000);
1033
    res |= ((int64_t)tmp) << 16;
1034
    res |= (val >> 16) & 0xff;
1035
    env->macc[acc + 1] = res;
1036
}
1037

    
1038
OP(set_mac_exts)
1039
{
1040
    int acc = PARAM2;
1041
    int32_t val = get_op(PARAM1);
1042
    int64_t res;
1043
    int32_t tmp;
1044
    res = (uint32_t)env->macc[acc];
1045
    tmp = (int16_t)val;
1046
    res |= ((int64_t)tmp) << 32;
1047
    env->macc[acc] = res;
1048
    res = (uint32_t)env->macc[acc + 1];
1049
    tmp = val & 0xffff0000;
1050
    res |= (int64_t)tmp << 16;
1051
    env->macc[acc + 1] = res;
1052
}
1053

    
1054
OP(set_mac_extu)
1055
{
1056
    int acc = PARAM2;
1057
    int32_t val = get_op(PARAM1);
1058
    uint64_t res;
1059
    res = (uint32_t)env->macc[acc];
1060
    res |= ((uint64_t)(val & 0xffff)) << 32;
1061
    env->macc[acc] = res;
1062
    res = (uint32_t)env->macc[acc + 1];
1063
    res |= (uint64_t)(val & 0xffff0000) << 16;
1064
    env->macc[acc + 1] = res;
1065
}
1066

    
1067
OP(set_macsr)
1068
{
1069
    m68k_set_macsr(env, get_op(PARAM1));
1070
}