Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ 3a8a44c4

History | View | Annotate | Download (11.7 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_ldtlb(void)
111
{
112
    helper_ldtlb();
113
    RETURN();
114
}
115

    
116
void OPPROTO op_frchg(void)
117
{
118
    env->fpscr ^= FPSCR_FR;
119
    RETURN();
120
}
121

    
122
void OPPROTO op_fschg(void)
123
{
124
    env->fpscr ^= FPSCR_SZ;
125
    RETURN();
126
}
127

    
128
void OPPROTO op_rte(void)
129
{
130
    env->sr = env->ssr;
131
    env->delayed_pc = env->spc;
132
    RETURN();
133
}
134

    
135
void OPPROTO op_addc_T0_T1(void)
136
{
137
    helper_addc_T0_T1();
138
    RETURN();
139
}
140

    
141
void OPPROTO op_addv_T0_T1(void)
142
{
143
    helper_addv_T0_T1();
144
    RETURN();
145
}
146

    
147
void OPPROTO op_cmp_eq_T0_T1(void)
148
{
149
    cond_t(T1 == T0);
150
    RETURN();
151
}
152

    
153
void OPPROTO op_cmp_ge_T0_T1(void)
154
{
155
    cond_t((int32_t) T1 >= (int32_t) T0);
156
    RETURN();
157
}
158

    
159
void OPPROTO op_cmp_gt_T0_T1(void)
160
{
161
    cond_t((int32_t) T1 > (int32_t) T0);
162
    RETURN();
163
}
164

    
165
void OPPROTO op_cmp_hi_T0_T1(void)
166
{
167
    cond_t((uint32_t) T1 > (uint32_t) T0);
168
    RETURN();
169
}
170

    
171
void OPPROTO op_cmp_hs_T0_T1(void)
172
{
173
    cond_t((uint32_t) T1 >= (uint32_t) T0);
174
    RETURN();
175
}
176

    
177
void OPPROTO op_cmp_str_T0_T1(void)
178
{
179
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
180
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
181
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
182
           (T0 & 0xff000000) == (T1 & 0xff000000));
183
    RETURN();
184
}
185

    
186
void OPPROTO op_tst_T0_T1(void)
187
{
188
    cond_t((T1 & T0) == 0);
189
    RETURN();
190
}
191

    
192
void OPPROTO op_div0s_T0_T1(void)
193
{
194
    if (T1 & 0x80000000)
195
        env->sr |= SR_Q;
196
    else
197
        env->sr &= ~SR_Q;
198
    if (T0 & 0x80000000)
199
        env->sr |= SR_M;
200
    else
201
        env->sr &= ~SR_M;
202
    cond_t((T1 ^ T0) & 0x80000000);
203
    RETURN();
204
}
205

    
206
void OPPROTO op_div1_T0_T1(void)
207
{
208
    helper_div1_T0_T1();
209
    RETURN();
210
}
211

    
212
void OPPROTO op_dmulsl_T0_T1(void)
213
{
214
    helper_dmulsl_T0_T1();
215
    RETURN();
216
}
217

    
218
void OPPROTO op_dmulul_T0_T1(void)
219
{
220
    helper_dmulul_T0_T1();
221
    RETURN();
222
}
223

    
224
void OPPROTO op_macl_T0_T1(void)
225
{
226
    helper_macl_T0_T1();
227
    RETURN();
228
}
229

    
230
void OPPROTO op_macw_T0_T1(void)
231
{
232
    helper_macw_T0_T1();
233
    RETURN();
234
}
235

    
236
void OPPROTO op_mull_T0_T1(void)
237
{
238
    env->macl = (T0 * T1) & 0xffffffff;
239
    RETURN();
240
}
241

    
242
void OPPROTO op_mulsw_T0_T1(void)
243
{
244
    env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
245
    RETURN();
246
}
247

    
248
void OPPROTO op_muluw_T0_T1(void)
249
{
250
    env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
251
    RETURN();
252
}
253

    
254
void OPPROTO op_negc_T0(void)
255
{
256
    helper_negc_T0();
257
    RETURN();
258
}
259

    
260
void OPPROTO op_shad_T0_T1(void)
261
{
262
    if ((T0 & 0x80000000) == 0)
263
        T1 <<= (T0 & 0x1f);
264
    else if ((T0 & 0x1f) == 0)
265
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
266
    else
267
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
268
    RETURN();
269
}
270

    
271
void OPPROTO op_shld_T0_T1(void)
272
{
273
    if ((T0 & 0x80000000) == 0)
274
        T1 <<= (T0 & 0x1f);
275
    else if ((T0 & 0x1f) == 0)
276
        T1 = 0;
277
    else
278
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
279
    RETURN();
280
}
281

    
282
void OPPROTO op_subc_T0_T1(void)
283
{
284
    helper_subc_T0_T1();
285
    RETURN();
286
}
287

    
288
void OPPROTO op_subv_T0_T1(void)
289
{
290
    helper_subv_T0_T1();
291
    RETURN();
292
}
293

    
294
void OPPROTO op_trapa(void)
295
{
296
    env->tra = PARAM1 << 2;
297
    env->exception_index = 0x160;
298
    do_raise_exception();
299
    RETURN();
300
}
301

    
302
void OPPROTO op_cmp_pl_T0(void)
303
{
304
    cond_t((int32_t) T0 > 0);
305
    RETURN();
306
}
307

    
308
void OPPROTO op_cmp_pz_T0(void)
309
{
310
    cond_t((int32_t) T0 >= 0);
311
    RETURN();
312
}
313

    
314
void OPPROTO op_jmp_T0(void)
315
{
316
    env->delayed_pc = T0;
317
    RETURN();
318
}
319

    
320
void OPPROTO op_ldcl_rMplus_rN_bank(void)
321
{
322
    env->gregs[PARAM2] = env->gregs[PARAM1];
323
    env->gregs[PARAM1] += 4;
324
    RETURN();
325
}
326

    
327
void OPPROTO op_ldc_T0_sr(void)
328
{
329
    env->sr = T0 & 0x700083f3;
330
    RETURN();
331
}
332

    
333
void OPPROTO op_stc_sr_T0(void)
334
{
335
    T0 = env->sr;
336
    RETURN();
337
}
338

    
339
#define LDSTOPS(target,load,store) \
340
void OPPROTO op_##load##_T0_##target (void) \
341
{ env ->target = T0;   RETURN(); \
342
} \
343
void OPPROTO op_##store##_##target##_T0 (void) \
344
{ T0 = env->target;   RETURN(); \
345
} \
346

    
347
    LDSTOPS(gbr, ldc, stc)
348
    LDSTOPS(vbr, ldc, stc)
349
    LDSTOPS(ssr, ldc, stc)
350
    LDSTOPS(spc, ldc, stc)
351
    LDSTOPS(sgr, ldc, stc)
352
    LDSTOPS(dbr, ldc, stc)
353
    LDSTOPS(mach, lds, sts)
354
    LDSTOPS(macl, lds, sts)
355
    LDSTOPS(pr, lds, sts)
356
    LDSTOPS(fpul, lds, sts)
357

    
358
void OPPROTO op_lds_T0_fpscr(void)
359
{
360
    env->fpscr = T0 & 0x003fffff;
361
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
362
      float_round_to_zero : float_round_nearest_even;
363

    
364
    RETURN();
365
}
366

    
367
void OPPROTO op_sts_fpscr_T0(void)
368
{
369
    T0 = env->fpscr & 0x003fffff;
370
    RETURN();
371
}
372

    
373
void OPPROTO op_rotcl_Rn(void)
374
{
375
    helper_rotcl(&env->gregs[PARAM1]);
376
    RETURN();
377
}
378

    
379
void OPPROTO op_rotcr_Rn(void)
380
{
381
    helper_rotcr(&env->gregs[PARAM1]);
382
    RETURN();
383
}
384

    
385
void OPPROTO op_rotl_Rn(void)
386
{
387
    cond_t(env->gregs[PARAM1] & 0x80000000);
388
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
389
    RETURN();
390
}
391

    
392
void OPPROTO op_rotr_Rn(void)
393
{
394
    cond_t(env->gregs[PARAM1] & 1);
395
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
396
        ((env->sr & SR_T) ? 0x80000000 : 0);
397
    RETURN();
398
}
399

    
400
void OPPROTO op_shal_Rn(void)
401
{
402
    cond_t(env->gregs[PARAM1] & 0x80000000);
403
    env->gregs[PARAM1] <<= 1;
404
    RETURN();
405
}
406

    
407
void OPPROTO op_shar_Rn(void)
408
{
409
    cond_t(env->gregs[PARAM1] & 1);
410
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
411
    RETURN();
412
}
413

    
414
void OPPROTO op_shlr_Rn(void)
415
{
416
    cond_t(env->gregs[PARAM1] & 1);
417
    env->gregs[PARAM1] >>= 1;
418
    RETURN();
419
}
420

    
421
void OPPROTO op_fmov_frN_FT0(void)
422
{
423
    FT0 = env->fregs[PARAM1];
424
    RETURN();
425
}
426

    
427
void OPPROTO op_fmov_drN_DT0(void)
428
{
429
    CPU_DoubleU d;
430

    
431
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
432
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
433
    DT0 = d.d;
434
    RETURN();
435
}
436

    
437
void OPPROTO op_fmov_frN_FT1(void)
438
{
439
    FT1 = env->fregs[PARAM1];
440
    RETURN();
441
}
442

    
443
void OPPROTO op_fmov_drN_DT1(void)
444
{
445
    CPU_DoubleU d;
446

    
447
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
448
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
449
    DT1 = d.d;
450
    RETURN();
451
}
452

    
453
void OPPROTO op_fmov_FT0_frN(void)
454
{
455
    env->fregs[PARAM1] = FT0;
456
    RETURN();
457
}
458

    
459
void OPPROTO op_fmov_DT0_drN(void)
460
{
461
    CPU_DoubleU d;
462

    
463
    d.d = DT0;
464
    *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
465
    *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
466
    RETURN();
467
}
468

    
469
void OPPROTO op_fadd_FT(void)
470
{
471
    FT0 = float32_add(FT0, FT1, &env->fp_status);
472
    RETURN();
473
}
474

    
475
void OPPROTO op_fadd_DT(void)
476
{
477
    DT0 = float64_add(DT0, DT1, &env->fp_status);
478
    RETURN();
479
}
480

    
481
void OPPROTO op_fsub_FT(void)
482
{
483
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
484
    RETURN();
485
}
486

    
487
void OPPROTO op_fsub_DT(void)
488
{
489
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
490
    RETURN();
491
}
492

    
493
void OPPROTO op_fmul_FT(void)
494
{
495
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
496
    RETURN();
497
}
498

    
499
void OPPROTO op_fmul_DT(void)
500
{
501
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
502
    RETURN();
503
}
504

    
505
void OPPROTO op_fdiv_FT(void)
506
{
507
    FT0 = float32_div(FT0, FT1, &env->fp_status);
508
    RETURN();
509
}
510

    
511
void OPPROTO op_fdiv_DT(void)
512
{
513
    DT0 = float64_div(DT0, DT1, &env->fp_status);
514
    RETURN();
515
}
516

    
517
void OPPROTO op_fcmp_eq_FT(void)
518
{
519
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
520
    RETURN();
521
}
522

    
523
void OPPROTO op_fcmp_eq_DT(void)
524
{
525
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
526
    RETURN();
527
}
528

    
529
void OPPROTO op_fcmp_gt_FT(void)
530
{
531
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
532
    RETURN();
533
}
534

    
535
void OPPROTO op_fcmp_gt_DT(void)
536
{
537
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
538
    RETURN();
539
}
540

    
541
void OPPROTO op_float_FT(void)
542
{
543
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
544
    RETURN();
545
}
546

    
547
void OPPROTO op_float_DT(void)
548
{
549
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
550
    RETURN();
551
}
552

    
553
void OPPROTO op_ftrc_FT(void)
554
{
555
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
556
    RETURN();
557
}
558

    
559
void OPPROTO op_ftrc_DT(void)
560
{
561
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
562
    RETURN();
563
}
564

    
565
void OPPROTO op_fneg_frN(void)
566
{
567
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
568
    RETURN();
569
}
570

    
571
void OPPROTO op_fabs_FT(void)
572
{
573
    FT0 = float32_abs(FT0);
574
    RETURN();
575
}
576

    
577
void OPPROTO op_fabs_DT(void)
578
{
579
    DT0 = float64_abs(DT0);
580
    RETURN();
581
}
582

    
583
void OPPROTO op_fcnvsd_FT_DT(void)
584
{
585
    DT0 = float32_to_float64(FT0, &env->fp_status);
586
    RETURN();
587
}
588

    
589
void OPPROTO op_fcnvds_DT_FT(void)
590
{
591
    FT0 = float64_to_float32(DT0, &env->fp_status);
592
    RETURN();
593
}
594

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

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

    
607
void OPPROTO op_fmov_T0_frN(void)
608
{
609
    *(uint32_t *)&env->fregs[PARAM1] = T0;
610
    RETURN();
611
}
612

    
613
void OPPROTO op_dt_rN(void)
614
{
615
    cond_t((--env->gregs[PARAM1]) == 0);
616
    RETURN();
617
}
618

    
619
void OPPROTO op_tst_imm_rN(void)
620
{
621
    cond_t((env->gregs[PARAM2] & PARAM1) == 0);
622
    RETURN();
623
}
624

    
625
void OPPROTO op_movl_fpul_FT0(void)
626
{
627
    FT0 = *(float32 *)&env->fpul;
628
    RETURN();
629
}
630

    
631
void OPPROTO op_movl_FT0_fpul(void)
632
{
633
    *(float32 *)&env->fpul = FT0;
634
    RETURN();
635
}
636

    
637
void OPPROTO op_jT(void)
638
{
639
    if (env->sr & SR_T)
640
        GOTO_LABEL_PARAM(1);
641
    RETURN();
642
}
643

    
644
void OPPROTO op_jdelayed(void)
645
{
646
    if (env->flags & DELAY_SLOT_TRUE) {
647
        env->flags &= ~DELAY_SLOT_TRUE;
648
        GOTO_LABEL_PARAM(1);
649
    }
650
    RETURN();
651
}
652

    
653
void OPPROTO op_movl_delayed_pc_PC(void)
654
{
655
    env->pc = env->delayed_pc;
656
    RETURN();
657
}
658

    
659
void OPPROTO op_tst_imm_T0(void)
660
{
661
    cond_t((T0 & PARAM1) == 0);
662
    RETURN();
663
}
664

    
665
void OPPROTO op_raise_illegal_instruction(void)
666
{
667
    env->exception_index = 0x180;
668
    do_raise_exception();
669
    RETURN();
670
}
671

    
672
void OPPROTO op_raise_slot_illegal_instruction(void)
673
{
674
    env->exception_index = 0x1a0;
675
    do_raise_exception();
676
    RETURN();
677
}
678

    
679
void OPPROTO op_debug(void)
680
{
681
    env->exception_index = EXCP_DEBUG;
682
    cpu_loop_exit();
683
}
684

    
685
void OPPROTO op_sleep(void)
686
{
687
    env->halted = 1;
688
    env->exception_index = EXCP_HLT;
689
    cpu_loop_exit();
690
}
691

    
692
/* Load and store */
693
#define MEMSUFFIX _raw
694
#include "op_mem.c"
695
#undef MEMSUFFIX
696
#if !defined(CONFIG_USER_ONLY)
697
#define MEMSUFFIX _user
698
#include "op_mem.c"
699
#undef MEMSUFFIX
700

    
701
#define MEMSUFFIX _kernel
702
#include "op_mem.c"
703
#undef MEMSUFFIX
704
#endif