Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ a4625612

History | View | Annotate | Download (10.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_bf_s(void)
41
{
42
    env->delayed_pc = PARAM1;
43
    if (!(env->sr & SR_T)) {
44
        env->flags |= DELAY_SLOT_TRUE;
45
    }
46
    RETURN();
47
}
48

    
49
void OPPROTO op_bt_s(void)
50
{
51
    env->delayed_pc = PARAM1;
52
    if (env->sr & SR_T) {
53
        env->flags |= DELAY_SLOT_TRUE;
54
    }
55
    RETURN();
56
}
57

    
58
void OPPROTO op_store_flags(void)
59
{
60
    env->flags &= DELAY_SLOT_TRUE;
61
    env->flags |= PARAM1;
62
    RETURN();
63
}
64

    
65
void OPPROTO op_bra(void)
66
{
67
    env->delayed_pc = PARAM1;
68
    RETURN();
69
}
70

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

    
77
void OPPROTO op_bsr(void)
78
{
79
    env->pr = PARAM1;
80
    env->delayed_pc = PARAM2;
81
    RETURN();
82
}
83

    
84
void OPPROTO op_bsrf_T0(void)
85
{
86
    env->pr = PARAM1;
87
    env->delayed_pc = PARAM1 + T0;
88
    RETURN();
89
}
90

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

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

    
104
void OPPROTO op_ldtlb(void)
105
{
106
    helper_ldtlb();
107
    RETURN();
108
}
109

    
110
void OPPROTO op_frchg(void)
111
{
112
    env->fpscr ^= FPSCR_FR;
113
    RETURN();
114
}
115

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

    
122
void OPPROTO op_rte(void)
123
{
124
    env->sr = env->ssr;
125
    env->delayed_pc = env->spc;
126
    RETURN();
127
}
128

    
129
void OPPROTO op_addc_T0_T1(void)
130
{
131
    helper_addc_T0_T1();
132
    RETURN();
133
}
134

    
135
void OPPROTO op_addv_T0_T1(void)
136
{
137
    helper_addv_T0_T1();
138
    RETURN();
139
}
140

    
141
void OPPROTO op_cmp_str_T0_T1(void)
142
{
143
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
144
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
145
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
146
           (T0 & 0xff000000) == (T1 & 0xff000000));
147
    RETURN();
148
}
149

    
150
void OPPROTO op_div0s_T0_T1(void)
151
{
152
    if (T1 & 0x80000000)
153
        env->sr |= SR_Q;
154
    else
155
        env->sr &= ~SR_Q;
156
    if (T0 & 0x80000000)
157
        env->sr |= SR_M;
158
    else
159
        env->sr &= ~SR_M;
160
    cond_t((T1 ^ T0) & 0x80000000);
161
    RETURN();
162
}
163

    
164
void OPPROTO op_div1_T0_T1(void)
165
{
166
    helper_div1_T0_T1();
167
    RETURN();
168
}
169

    
170
void OPPROTO op_dmulsl_T0_T1(void)
171
{
172
    helper_dmulsl_T0_T1();
173
    RETURN();
174
}
175

    
176
void OPPROTO op_dmulul_T0_T1(void)
177
{
178
    helper_dmulul_T0_T1();
179
    RETURN();
180
}
181

    
182
void OPPROTO op_macl_T0_T1(void)
183
{
184
    helper_macl_T0_T1();
185
    RETURN();
186
}
187

    
188
void OPPROTO op_macw_T0_T1(void)
189
{
190
    helper_macw_T0_T1();
191
    RETURN();
192
}
193

    
194
void OPPROTO op_mull_T0_T1(void)
195
{
196
    env->macl = (T0 * T1) & 0xffffffff;
197
    RETURN();
198
}
199

    
200
void OPPROTO op_mulsw_T0_T1(void)
201
{
202
    env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
203
    RETURN();
204
}
205

    
206
void OPPROTO op_muluw_T0_T1(void)
207
{
208
    env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
209
    RETURN();
210
}
211

    
212
void OPPROTO op_negc_T0(void)
213
{
214
    helper_negc_T0();
215
    RETURN();
216
}
217

    
218
void OPPROTO op_shad_T0_T1(void)
219
{
220
    if ((T0 & 0x80000000) == 0)
221
        T1 <<= (T0 & 0x1f);
222
    else if ((T0 & 0x1f) == 0)
223
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
224
    else
225
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
226
    RETURN();
227
}
228

    
229
void OPPROTO op_shld_T0_T1(void)
230
{
231
    if ((T0 & 0x80000000) == 0)
232
        T1 <<= (T0 & 0x1f);
233
    else if ((T0 & 0x1f) == 0)
234
        T1 = 0;
235
    else
236
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
237
    RETURN();
238
}
239

    
240
void OPPROTO op_subc_T0_T1(void)
241
{
242
    helper_subc_T0_T1();
243
    RETURN();
244
}
245

    
246
void OPPROTO op_subv_T0_T1(void)
247
{
248
    helper_subv_T0_T1();
249
    RETURN();
250
}
251

    
252
void OPPROTO op_trapa(void)
253
{
254
    env->tra = PARAM1 << 2;
255
    env->exception_index = 0x160;
256
    do_raise_exception();
257
    RETURN();
258
}
259

    
260
void OPPROTO op_jmp_T0(void)
261
{
262
    env->delayed_pc = T0;
263
    RETURN();
264
}
265

    
266
void OPPROTO op_ldcl_rMplus_rN_bank(void)
267
{
268
    env->gregs[PARAM2] = env->gregs[PARAM1];
269
    env->gregs[PARAM1] += 4;
270
    RETURN();
271
}
272

    
273
void OPPROTO op_ldc_T0_sr(void)
274
{
275
    env->sr = T0 & 0x700083f3;
276
    RETURN();
277
}
278

    
279
void OPPROTO op_stc_sr_T0(void)
280
{
281
    T0 = env->sr;
282
    RETURN();
283
}
284

    
285
#define LDSTOPS(target,load,store) \
286
void OPPROTO op_##load##_T0_##target (void) \
287
{ env ->target = T0;   RETURN(); \
288
} \
289
void OPPROTO op_##store##_##target##_T0 (void) \
290
{ T0 = env->target;   RETURN(); \
291
} \
292

    
293
    LDSTOPS(gbr, ldc, stc)
294
    LDSTOPS(vbr, ldc, stc)
295
    LDSTOPS(ssr, ldc, stc)
296
    LDSTOPS(spc, ldc, stc)
297
    LDSTOPS(sgr, ldc, stc)
298
    LDSTOPS(dbr, ldc, stc)
299
    LDSTOPS(mach, lds, sts)
300
    LDSTOPS(macl, lds, sts)
301
    LDSTOPS(pr, lds, sts)
302
    LDSTOPS(fpul, lds, sts)
303

    
304
void OPPROTO op_lds_T0_fpscr(void)
305
{
306
    env->fpscr = T0 & 0x003fffff;
307
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
308
      float_round_to_zero : float_round_nearest_even;
309

    
310
    RETURN();
311
}
312

    
313
void OPPROTO op_sts_fpscr_T0(void)
314
{
315
    T0 = env->fpscr & 0x003fffff;
316
    RETURN();
317
}
318

    
319
void OPPROTO op_rotcl_Rn(void)
320
{
321
    helper_rotcl(&env->gregs[PARAM1]);
322
    RETURN();
323
}
324

    
325
void OPPROTO op_rotcr_Rn(void)
326
{
327
    helper_rotcr(&env->gregs[PARAM1]);
328
    RETURN();
329
}
330

    
331
void OPPROTO op_rotl_Rn(void)
332
{
333
    cond_t(env->gregs[PARAM1] & 0x80000000);
334
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
335
    RETURN();
336
}
337

    
338
void OPPROTO op_rotr_Rn(void)
339
{
340
    cond_t(env->gregs[PARAM1] & 1);
341
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
342
        ((env->sr & SR_T) ? 0x80000000 : 0);
343
    RETURN();
344
}
345

    
346
void OPPROTO op_shal_Rn(void)
347
{
348
    cond_t(env->gregs[PARAM1] & 0x80000000);
349
    env->gregs[PARAM1] <<= 1;
350
    RETURN();
351
}
352

    
353
void OPPROTO op_shar_Rn(void)
354
{
355
    cond_t(env->gregs[PARAM1] & 1);
356
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
357
    RETURN();
358
}
359

    
360
void OPPROTO op_shlr_Rn(void)
361
{
362
    cond_t(env->gregs[PARAM1] & 1);
363
    env->gregs[PARAM1] >>= 1;
364
    RETURN();
365
}
366

    
367
void OPPROTO op_fmov_frN_FT0(void)
368
{
369
    FT0 = env->fregs[PARAM1];
370
    RETURN();
371
}
372

    
373
void OPPROTO op_fmov_drN_DT0(void)
374
{
375
    CPU_DoubleU d;
376

    
377
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
378
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
379
    DT0 = d.d;
380
    RETURN();
381
}
382

    
383
void OPPROTO op_fmov_frN_FT1(void)
384
{
385
    FT1 = env->fregs[PARAM1];
386
    RETURN();
387
}
388

    
389
void OPPROTO op_fmov_drN_DT1(void)
390
{
391
    CPU_DoubleU d;
392

    
393
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
394
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
395
    DT1 = d.d;
396
    RETURN();
397
}
398

    
399
void OPPROTO op_fmov_FT0_frN(void)
400
{
401
    env->fregs[PARAM1] = FT0;
402
    RETURN();
403
}
404

    
405
void OPPROTO op_fmov_DT0_drN(void)
406
{
407
    CPU_DoubleU d;
408

    
409
    d.d = DT0;
410
    *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
411
    *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
412
    RETURN();
413
}
414

    
415
void OPPROTO op_fadd_FT(void)
416
{
417
    FT0 = float32_add(FT0, FT1, &env->fp_status);
418
    RETURN();
419
}
420

    
421
void OPPROTO op_fadd_DT(void)
422
{
423
    DT0 = float64_add(DT0, DT1, &env->fp_status);
424
    RETURN();
425
}
426

    
427
void OPPROTO op_fsub_FT(void)
428
{
429
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
430
    RETURN();
431
}
432

    
433
void OPPROTO op_fsub_DT(void)
434
{
435
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
436
    RETURN();
437
}
438

    
439
void OPPROTO op_fmul_FT(void)
440
{
441
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
442
    RETURN();
443
}
444

    
445
void OPPROTO op_fmul_DT(void)
446
{
447
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
448
    RETURN();
449
}
450

    
451
void OPPROTO op_fdiv_FT(void)
452
{
453
    FT0 = float32_div(FT0, FT1, &env->fp_status);
454
    RETURN();
455
}
456

    
457
void OPPROTO op_fdiv_DT(void)
458
{
459
    DT0 = float64_div(DT0, DT1, &env->fp_status);
460
    RETURN();
461
}
462

    
463
void OPPROTO op_fcmp_eq_FT(void)
464
{
465
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
466
    RETURN();
467
}
468

    
469
void OPPROTO op_fcmp_eq_DT(void)
470
{
471
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
472
    RETURN();
473
}
474

    
475
void OPPROTO op_fcmp_gt_FT(void)
476
{
477
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
478
    RETURN();
479
}
480

    
481
void OPPROTO op_fcmp_gt_DT(void)
482
{
483
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
484
    RETURN();
485
}
486

    
487
void OPPROTO op_float_FT(void)
488
{
489
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
490
    RETURN();
491
}
492

    
493
void OPPROTO op_float_DT(void)
494
{
495
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
496
    RETURN();
497
}
498

    
499
void OPPROTO op_ftrc_FT(void)
500
{
501
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
502
    RETURN();
503
}
504

    
505
void OPPROTO op_ftrc_DT(void)
506
{
507
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
508
    RETURN();
509
}
510

    
511
void OPPROTO op_fneg_frN(void)
512
{
513
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
514
    RETURN();
515
}
516

    
517
void OPPROTO op_fabs_FT(void)
518
{
519
    FT0 = float32_abs(FT0);
520
    RETURN();
521
}
522

    
523
void OPPROTO op_fabs_DT(void)
524
{
525
    DT0 = float64_abs(DT0);
526
    RETURN();
527
}
528

    
529
void OPPROTO op_fcnvsd_FT_DT(void)
530
{
531
    DT0 = float32_to_float64(FT0, &env->fp_status);
532
    RETURN();
533
}
534

    
535
void OPPROTO op_fcnvds_DT_FT(void)
536
{
537
    FT0 = float64_to_float32(DT0, &env->fp_status);
538
    RETURN();
539
}
540

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

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

    
553
void OPPROTO op_fmov_T0_frN(void)
554
{
555
    *(uint32_t *)&env->fregs[PARAM1] = T0;
556
    RETURN();
557
}
558

    
559
void OPPROTO op_movl_fpul_FT0(void)
560
{
561
    FT0 = *(float32 *)&env->fpul;
562
    RETURN();
563
}
564

    
565
void OPPROTO op_movl_FT0_fpul(void)
566
{
567
    *(float32 *)&env->fpul = FT0;
568
    RETURN();
569
}
570

    
571
void OPPROTO op_jT(void)
572
{
573
    if (env->sr & SR_T)
574
        GOTO_LABEL_PARAM(1);
575
    RETURN();
576
}
577

    
578
void OPPROTO op_jdelayed(void)
579
{
580
    if (env->flags & DELAY_SLOT_TRUE) {
581
        env->flags &= ~DELAY_SLOT_TRUE;
582
        GOTO_LABEL_PARAM(1);
583
    }
584
    RETURN();
585
}
586

    
587
void OPPROTO op_movl_delayed_pc_PC(void)
588
{
589
    env->pc = env->delayed_pc;
590
    RETURN();
591
}
592

    
593
void OPPROTO op_raise_illegal_instruction(void)
594
{
595
    env->exception_index = 0x180;
596
    do_raise_exception();
597
    RETURN();
598
}
599

    
600
void OPPROTO op_raise_slot_illegal_instruction(void)
601
{
602
    env->exception_index = 0x1a0;
603
    do_raise_exception();
604
    RETURN();
605
}
606

    
607
void OPPROTO op_debug(void)
608
{
609
    env->exception_index = EXCP_DEBUG;
610
    cpu_loop_exit();
611
}
612

    
613
void OPPROTO op_sleep(void)
614
{
615
    env->halted = 1;
616
    env->exception_index = EXCP_HLT;
617
    cpu_loop_exit();
618
}
619

    
620
/* Load and store */
621
#define MEMSUFFIX _raw
622
#include "op_mem.c"
623
#undef MEMSUFFIX
624
#if !defined(CONFIG_USER_ONLY)
625
#define MEMSUFFIX _user
626
#include "op_mem.c"
627
#undef MEMSUFFIX
628

    
629
#define MEMSUFFIX _kernel
630
#include "op_mem.c"
631
#undef MEMSUFFIX
632
#endif