Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ 559dd74d

History | View | Annotate | Download (12.4 kB)

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

    
22
static inline void set_t(void)
23
{
24
    env->sr |= SR_T;
25
}
26

    
27
static inline void clr_t(void)
28
{
29
    env->sr &= ~SR_T;
30
}
31

    
32
static inline void cond_t(int cond)
33
{
34
    if (cond)
35
        set_t();
36
    else
37
        clr_t();
38
}
39

    
40
void OPPROTO op_cmp_eq_imm_T0(void)
41
{
42
    cond_t((int32_t) T0 == (int32_t) PARAM1);
43
    RETURN();
44
}
45

    
46
void OPPROTO op_bf_s(void)
47
{
48
    env->delayed_pc = PARAM1;
49
    if (!(env->sr & SR_T)) {
50
        env->flags |= DELAY_SLOT_TRUE;
51
    }
52
    RETURN();
53
}
54

    
55
void OPPROTO op_bt_s(void)
56
{
57
    env->delayed_pc = PARAM1;
58
    if (env->sr & SR_T) {
59
        env->flags |= DELAY_SLOT_TRUE;
60
    }
61
    RETURN();
62
}
63

    
64
void OPPROTO op_store_flags(void)
65
{
66
    env->flags &= DELAY_SLOT_TRUE;
67
    env->flags |= PARAM1;
68
    RETURN();
69
}
70

    
71
void OPPROTO op_bra(void)
72
{
73
    env->delayed_pc = PARAM1;
74
    RETURN();
75
}
76

    
77
void OPPROTO op_braf_T0(void)
78
{
79
    env->delayed_pc = PARAM1 + T0;
80
    RETURN();
81
}
82

    
83
void OPPROTO op_bsr(void)
84
{
85
    env->pr = PARAM1;
86
    env->delayed_pc = PARAM2;
87
    RETURN();
88
}
89

    
90
void OPPROTO op_bsrf_T0(void)
91
{
92
    env->pr = PARAM1;
93
    env->delayed_pc = PARAM1 + T0;
94
    RETURN();
95
}
96

    
97
void OPPROTO op_jsr_T0(void)
98
{
99
    env->pr = PARAM1;
100
    env->delayed_pc = T0;
101
    RETURN();
102
}
103

    
104
void OPPROTO op_rts(void)
105
{
106
    env->delayed_pc = env->pr;
107
    RETURN();
108
}
109

    
110
void OPPROTO op_clrmac(void)
111
{
112
    env->mach = env->macl = 0;
113
    RETURN();
114
}
115

    
116
void OPPROTO op_clrs(void)
117
{
118
    env->sr &= ~SR_S;
119
    RETURN();
120
}
121

    
122
void OPPROTO op_clrt(void)
123
{
124
    env->sr &= ~SR_T;
125
    RETURN();
126
}
127

    
128
void OPPROTO op_ldtlb(void)
129
{
130
    helper_ldtlb();
131
    RETURN();
132
}
133

    
134
void OPPROTO op_sets(void)
135
{
136
    env->sr |= SR_S;
137
    RETURN();
138
}
139

    
140
void OPPROTO op_sett(void)
141
{
142
    env->sr |= SR_T;
143
    RETURN();
144
}
145

    
146
void OPPROTO op_frchg(void)
147
{
148
    env->fpscr ^= FPSCR_FR;
149
    RETURN();
150
}
151

    
152
void OPPROTO op_fschg(void)
153
{
154
    env->fpscr ^= FPSCR_SZ;
155
    RETURN();
156
}
157

    
158
void OPPROTO op_rte(void)
159
{
160
    env->sr = env->ssr;
161
    env->delayed_pc = env->spc;
162
    RETURN();
163
}
164

    
165
void OPPROTO op_addc_T0_T1(void)
166
{
167
    helper_addc_T0_T1();
168
    RETURN();
169
}
170

    
171
void OPPROTO op_addv_T0_T1(void)
172
{
173
    helper_addv_T0_T1();
174
    RETURN();
175
}
176

    
177
void OPPROTO op_cmp_eq_T0_T1(void)
178
{
179
    cond_t(T1 == T0);
180
    RETURN();
181
}
182

    
183
void OPPROTO op_cmp_ge_T0_T1(void)
184
{
185
    cond_t((int32_t) T1 >= (int32_t) T0);
186
    RETURN();
187
}
188

    
189
void OPPROTO op_cmp_gt_T0_T1(void)
190
{
191
    cond_t((int32_t) T1 > (int32_t) T0);
192
    RETURN();
193
}
194

    
195
void OPPROTO op_cmp_hi_T0_T1(void)
196
{
197
    cond_t((uint32_t) T1 > (uint32_t) T0);
198
    RETURN();
199
}
200

    
201
void OPPROTO op_cmp_hs_T0_T1(void)
202
{
203
    cond_t((uint32_t) T1 >= (uint32_t) T0);
204
    RETURN();
205
}
206

    
207
void OPPROTO op_cmp_str_T0_T1(void)
208
{
209
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
210
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
211
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
212
           (T0 & 0xff000000) == (T1 & 0xff000000));
213
    RETURN();
214
}
215

    
216
void OPPROTO op_tst_T0_T1(void)
217
{
218
    cond_t((T1 & T0) == 0);
219
    RETURN();
220
}
221

    
222
void OPPROTO op_div0s_T0_T1(void)
223
{
224
    if (T1 & 0x80000000)
225
        env->sr |= SR_Q;
226
    else
227
        env->sr &= ~SR_Q;
228
    if (T0 & 0x80000000)
229
        env->sr |= SR_M;
230
    else
231
        env->sr &= ~SR_M;
232
    cond_t((T1 ^ T0) & 0x80000000);
233
    RETURN();
234
}
235

    
236
void OPPROTO op_div0u(void)
237
{
238
    env->sr &= ~(SR_M | SR_Q | SR_T);
239
    RETURN();
240
}
241

    
242
void OPPROTO op_div1_T0_T1(void)
243
{
244
    helper_div1_T0_T1();
245
    RETURN();
246
}
247

    
248
void OPPROTO op_dmulsl_T0_T1(void)
249
{
250
    helper_dmulsl_T0_T1();
251
    RETURN();
252
}
253

    
254
void OPPROTO op_dmulul_T0_T1(void)
255
{
256
    helper_dmulul_T0_T1();
257
    RETURN();
258
}
259

    
260
void OPPROTO op_macl_T0_T1(void)
261
{
262
    helper_macl_T0_T1();
263
    RETURN();
264
}
265

    
266
void OPPROTO op_macw_T0_T1(void)
267
{
268
    helper_macw_T0_T1();
269
    RETURN();
270
}
271

    
272
void OPPROTO op_mull_T0_T1(void)
273
{
274
    env->macl = (T0 * T1) & 0xffffffff;
275
    RETURN();
276
}
277

    
278
void OPPROTO op_mulsw_T0_T1(void)
279
{
280
    env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
281
    RETURN();
282
}
283

    
284
void OPPROTO op_muluw_T0_T1(void)
285
{
286
    env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
287
    RETURN();
288
}
289

    
290
void OPPROTO op_negc_T0(void)
291
{
292
    helper_negc_T0();
293
    RETURN();
294
}
295

    
296
void OPPROTO op_shad_T0_T1(void)
297
{
298
    if ((T0 & 0x80000000) == 0)
299
        T1 <<= (T0 & 0x1f);
300
    else if ((T0 & 0x1f) == 0)
301
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
302
    else
303
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
304
    RETURN();
305
}
306

    
307
void OPPROTO op_shld_T0_T1(void)
308
{
309
    if ((T0 & 0x80000000) == 0)
310
        T1 <<= (T0 & 0x1f);
311
    else if ((T0 & 0x1f) == 0)
312
        T1 = 0;
313
    else
314
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
315
    RETURN();
316
}
317

    
318
void OPPROTO op_subc_T0_T1(void)
319
{
320
    helper_subc_T0_T1();
321
    RETURN();
322
}
323

    
324
void OPPROTO op_subv_T0_T1(void)
325
{
326
    helper_subv_T0_T1();
327
    RETURN();
328
}
329

    
330
void OPPROTO op_trapa(void)
331
{
332
    env->tra = PARAM1 << 2;
333
    env->exception_index = 0x160;
334
    do_raise_exception();
335
    RETURN();
336
}
337

    
338
void OPPROTO op_cmp_pl_T0(void)
339
{
340
    cond_t((int32_t) T0 > 0);
341
    RETURN();
342
}
343

    
344
void OPPROTO op_cmp_pz_T0(void)
345
{
346
    cond_t((int32_t) T0 >= 0);
347
    RETURN();
348
}
349

    
350
void OPPROTO op_jmp_T0(void)
351
{
352
    env->delayed_pc = T0;
353
    RETURN();
354
}
355

    
356
void OPPROTO op_ldcl_rMplus_rN_bank(void)
357
{
358
    env->gregs[PARAM2] = env->gregs[PARAM1];
359
    env->gregs[PARAM1] += 4;
360
    RETURN();
361
}
362

    
363
void OPPROTO op_ldc_T0_sr(void)
364
{
365
    env->sr = T0 & 0x700083f3;
366
    RETURN();
367
}
368

    
369
void OPPROTO op_stc_sr_T0(void)
370
{
371
    T0 = env->sr;
372
    RETURN();
373
}
374

    
375
#define LDSTOPS(target,load,store) \
376
void OPPROTO op_##load##_T0_##target (void) \
377
{ env ->target = T0;   RETURN(); \
378
} \
379
void OPPROTO op_##store##_##target##_T0 (void) \
380
{ T0 = env->target;   RETURN(); \
381
} \
382

    
383
    LDSTOPS(gbr, ldc, stc)
384
    LDSTOPS(vbr, ldc, stc)
385
    LDSTOPS(ssr, ldc, stc)
386
    LDSTOPS(spc, ldc, stc)
387
    LDSTOPS(sgr, ldc, stc)
388
    LDSTOPS(dbr, ldc, stc)
389
    LDSTOPS(mach, lds, sts)
390
    LDSTOPS(macl, lds, sts)
391
    LDSTOPS(pr, lds, sts)
392
    LDSTOPS(fpul, lds, sts)
393

    
394
void OPPROTO op_lds_T0_fpscr(void)
395
{
396
    env->fpscr = T0 & 0x003fffff;
397
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
398
      float_round_to_zero : float_round_nearest_even;
399

    
400
    RETURN();
401
}
402

    
403
void OPPROTO op_sts_fpscr_T0(void)
404
{
405
    T0 = env->fpscr & 0x003fffff;
406
    RETURN();
407
}
408

    
409
void OPPROTO op_movt_rN(void)
410
{
411
    env->gregs[PARAM1] = env->sr & SR_T;
412
    RETURN();
413
}
414

    
415
void OPPROTO op_rotcl_Rn(void)
416
{
417
    helper_rotcl(&env->gregs[PARAM1]);
418
    RETURN();
419
}
420

    
421
void OPPROTO op_rotcr_Rn(void)
422
{
423
    helper_rotcr(&env->gregs[PARAM1]);
424
    RETURN();
425
}
426

    
427
void OPPROTO op_rotl_Rn(void)
428
{
429
    cond_t(env->gregs[PARAM1] & 0x80000000);
430
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
431
    RETURN();
432
}
433

    
434
void OPPROTO op_rotr_Rn(void)
435
{
436
    cond_t(env->gregs[PARAM1] & 1);
437
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
438
        ((env->sr & SR_T) ? 0x80000000 : 0);
439
    RETURN();
440
}
441

    
442
void OPPROTO op_shal_Rn(void)
443
{
444
    cond_t(env->gregs[PARAM1] & 0x80000000);
445
    env->gregs[PARAM1] <<= 1;
446
    RETURN();
447
}
448

    
449
void OPPROTO op_shar_Rn(void)
450
{
451
    cond_t(env->gregs[PARAM1] & 1);
452
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
453
    RETURN();
454
}
455

    
456
void OPPROTO op_shlr_Rn(void)
457
{
458
    cond_t(env->gregs[PARAM1] & 1);
459
    env->gregs[PARAM1] >>= 1;
460
    RETURN();
461
}
462

    
463
void OPPROTO op_fmov_frN_FT0(void)
464
{
465
    FT0 = env->fregs[PARAM1];
466
    RETURN();
467
}
468

    
469
void OPPROTO op_fmov_drN_DT0(void)
470
{
471
    CPU_DoubleU d;
472

    
473
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
474
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
475
    DT0 = d.d;
476
    RETURN();
477
}
478

    
479
void OPPROTO op_fmov_frN_FT1(void)
480
{
481
    FT1 = env->fregs[PARAM1];
482
    RETURN();
483
}
484

    
485
void OPPROTO op_fmov_drN_DT1(void)
486
{
487
    CPU_DoubleU d;
488

    
489
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
490
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
491
    DT1 = d.d;
492
    RETURN();
493
}
494

    
495
void OPPROTO op_fmov_FT0_frN(void)
496
{
497
    env->fregs[PARAM1] = FT0;
498
    RETURN();
499
}
500

    
501
void OPPROTO op_fmov_DT0_drN(void)
502
{
503
    CPU_DoubleU d;
504

    
505
    d.d = DT0;
506
    *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
507
    *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
508
    RETURN();
509
}
510

    
511
void OPPROTO op_fadd_FT(void)
512
{
513
    FT0 = float32_add(FT0, FT1, &env->fp_status);
514
    RETURN();
515
}
516

    
517
void OPPROTO op_fadd_DT(void)
518
{
519
    DT0 = float64_add(DT0, DT1, &env->fp_status);
520
    RETURN();
521
}
522

    
523
void OPPROTO op_fsub_FT(void)
524
{
525
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
526
    RETURN();
527
}
528

    
529
void OPPROTO op_fsub_DT(void)
530
{
531
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
532
    RETURN();
533
}
534

    
535
void OPPROTO op_fmul_FT(void)
536
{
537
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
538
    RETURN();
539
}
540

    
541
void OPPROTO op_fmul_DT(void)
542
{
543
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
544
    RETURN();
545
}
546

    
547
void OPPROTO op_fdiv_FT(void)
548
{
549
    FT0 = float32_div(FT0, FT1, &env->fp_status);
550
    RETURN();
551
}
552

    
553
void OPPROTO op_fdiv_DT(void)
554
{
555
    DT0 = float64_div(DT0, DT1, &env->fp_status);
556
    RETURN();
557
}
558

    
559
void OPPROTO op_fcmp_eq_FT(void)
560
{
561
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
562
    RETURN();
563
}
564

    
565
void OPPROTO op_fcmp_eq_DT(void)
566
{
567
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
568
    RETURN();
569
}
570

    
571
void OPPROTO op_fcmp_gt_FT(void)
572
{
573
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
574
    RETURN();
575
}
576

    
577
void OPPROTO op_fcmp_gt_DT(void)
578
{
579
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
580
    RETURN();
581
}
582

    
583
void OPPROTO op_float_FT(void)
584
{
585
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
586
    RETURN();
587
}
588

    
589
void OPPROTO op_float_DT(void)
590
{
591
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
592
    RETURN();
593
}
594

    
595
void OPPROTO op_ftrc_FT(void)
596
{
597
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
598
    RETURN();
599
}
600

    
601
void OPPROTO op_ftrc_DT(void)
602
{
603
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
604
    RETURN();
605
}
606

    
607
void OPPROTO op_fneg_frN(void)
608
{
609
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
610
    RETURN();
611
}
612

    
613
void OPPROTO op_fabs_FT(void)
614
{
615
    FT0 = float32_abs(FT0);
616
    RETURN();
617
}
618

    
619
void OPPROTO op_fabs_DT(void)
620
{
621
    DT0 = float64_abs(DT0);
622
    RETURN();
623
}
624

    
625
void OPPROTO op_fcnvsd_FT_DT(void)
626
{
627
    DT0 = float32_to_float64(FT0, &env->fp_status);
628
    RETURN();
629
}
630

    
631
void OPPROTO op_fcnvds_DT_FT(void)
632
{
633
    FT0 = float64_to_float32(DT0, &env->fp_status);
634
    RETURN();
635
}
636

    
637
void OPPROTO op_fsqrt_FT(void)
638
{
639
    FT0 = float32_sqrt(FT0, &env->fp_status);
640
    RETURN();
641
}
642

    
643
void OPPROTO op_fsqrt_DT(void)
644
{
645
    DT0 = float64_sqrt(DT0, &env->fp_status);
646
    RETURN();
647
}
648

    
649
void OPPROTO op_fmov_T0_frN(void)
650
{
651
    *(uint32_t *)&env->fregs[PARAM1] = T0;
652
    RETURN();
653
}
654

    
655
void OPPROTO op_dt_rN(void)
656
{
657
    cond_t((--env->gregs[PARAM1]) == 0);
658
    RETURN();
659
}
660

    
661
void OPPROTO op_tst_imm_rN(void)
662
{
663
    cond_t((env->gregs[PARAM2] & PARAM1) == 0);
664
    RETURN();
665
}
666

    
667
void OPPROTO op_movl_fpul_FT0(void)
668
{
669
    FT0 = *(float32 *)&env->fpul;
670
    RETURN();
671
}
672

    
673
void OPPROTO op_movl_FT0_fpul(void)
674
{
675
    *(float32 *)&env->fpul = FT0;
676
    RETURN();
677
}
678

    
679
void OPPROTO op_movl_imm_PC(void)
680
{
681
    env->pc = PARAM1;
682
    RETURN();
683
}
684

    
685
void OPPROTO op_jT(void)
686
{
687
    if (env->sr & SR_T)
688
        GOTO_LABEL_PARAM(1);
689
    RETURN();
690
}
691

    
692
void OPPROTO op_jdelayed(void)
693
{
694
    if (env->flags & DELAY_SLOT_TRUE) {
695
        env->flags &= ~DELAY_SLOT_TRUE;
696
        GOTO_LABEL_PARAM(1);
697
    }
698
    RETURN();
699
}
700

    
701
void OPPROTO op_movl_delayed_pc_PC(void)
702
{
703
    env->pc = env->delayed_pc;
704
    RETURN();
705
}
706

    
707
void OPPROTO op_addl_GBR_T0(void)
708
{
709
    T0 += env->gbr;
710
    RETURN();
711
}
712

    
713
void OPPROTO op_tst_imm_T0(void)
714
{
715
    cond_t((T0 & PARAM1) == 0);
716
    RETURN();
717
}
718

    
719
void OPPROTO op_raise_illegal_instruction(void)
720
{
721
    env->exception_index = 0x180;
722
    do_raise_exception();
723
    RETURN();
724
}
725

    
726
void OPPROTO op_raise_slot_illegal_instruction(void)
727
{
728
    env->exception_index = 0x1a0;
729
    do_raise_exception();
730
    RETURN();
731
}
732

    
733
void OPPROTO op_debug(void)
734
{
735
    env->exception_index = EXCP_DEBUG;
736
    cpu_loop_exit();
737
}
738

    
739
void OPPROTO op_sleep(void)
740
{
741
    env->halted = 1;
742
    env->exception_index = EXCP_HLT;
743
    cpu_loop_exit();
744
}
745

    
746
/* Load and store */
747
#define MEMSUFFIX _raw
748
#include "op_mem.c"
749
#undef MEMSUFFIX
750
#if !defined(CONFIG_USER_ONLY)
751
#define MEMSUFFIX _user
752
#include "op_mem.c"
753
#undef MEMSUFFIX
754

    
755
#define MEMSUFFIX _kernel
756
#include "op_mem.c"
757
#undef MEMSUFFIX
758
#endif