Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ 1000822b

History | View | Annotate | Download (9.3 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_ldtlb(void)
41
{
42
    helper_ldtlb();
43
    RETURN();
44
}
45

    
46
void OPPROTO op_frchg(void)
47
{
48
    env->fpscr ^= FPSCR_FR;
49
    RETURN();
50
}
51

    
52
void OPPROTO op_fschg(void)
53
{
54
    env->fpscr ^= FPSCR_SZ;
55
    RETURN();
56
}
57

    
58
void OPPROTO op_addc_T0_T1(void)
59
{
60
    helper_addc_T0_T1();
61
    RETURN();
62
}
63

    
64
void OPPROTO op_addv_T0_T1(void)
65
{
66
    helper_addv_T0_T1();
67
    RETURN();
68
}
69

    
70
void OPPROTO op_cmp_str_T0_T1(void)
71
{
72
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
73
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
74
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
75
           (T0 & 0xff000000) == (T1 & 0xff000000));
76
    RETURN();
77
}
78

    
79
void OPPROTO op_div0s_T0_T1(void)
80
{
81
    if (T1 & 0x80000000)
82
        env->sr |= SR_Q;
83
    else
84
        env->sr &= ~SR_Q;
85
    if (T0 & 0x80000000)
86
        env->sr |= SR_M;
87
    else
88
        env->sr &= ~SR_M;
89
    cond_t((T1 ^ T0) & 0x80000000);
90
    RETURN();
91
}
92

    
93
void OPPROTO op_div1_T0_T1(void)
94
{
95
    helper_div1_T0_T1();
96
    RETURN();
97
}
98

    
99
void OPPROTO op_dmulsl_T0_T1(void)
100
{
101
    helper_dmulsl_T0_T1();
102
    RETURN();
103
}
104

    
105
void OPPROTO op_dmulul_T0_T1(void)
106
{
107
    helper_dmulul_T0_T1();
108
    RETURN();
109
}
110

    
111
void OPPROTO op_macl_T0_T1(void)
112
{
113
    helper_macl_T0_T1();
114
    RETURN();
115
}
116

    
117
void OPPROTO op_macw_T0_T1(void)
118
{
119
    helper_macw_T0_T1();
120
    RETURN();
121
}
122

    
123
void OPPROTO op_mull_T0_T1(void)
124
{
125
    env->macl = (T0 * T1) & 0xffffffff;
126
    RETURN();
127
}
128

    
129
void OPPROTO op_mulsw_T0_T1(void)
130
{
131
    env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
132
    RETURN();
133
}
134

    
135
void OPPROTO op_muluw_T0_T1(void)
136
{
137
    env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
138
    RETURN();
139
}
140

    
141
void OPPROTO op_negc_T0(void)
142
{
143
    helper_negc_T0();
144
    RETURN();
145
}
146

    
147
void OPPROTO op_shad_T0_T1(void)
148
{
149
    if ((T0 & 0x80000000) == 0)
150
        T1 <<= (T0 & 0x1f);
151
    else if ((T0 & 0x1f) == 0)
152
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
153
    else
154
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
155
    RETURN();
156
}
157

    
158
void OPPROTO op_shld_T0_T1(void)
159
{
160
    if ((T0 & 0x80000000) == 0)
161
        T1 <<= (T0 & 0x1f);
162
    else if ((T0 & 0x1f) == 0)
163
        T1 = 0;
164
    else
165
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
166
    RETURN();
167
}
168

    
169
void OPPROTO op_subc_T0_T1(void)
170
{
171
    helper_subc_T0_T1();
172
    RETURN();
173
}
174

    
175
void OPPROTO op_subv_T0_T1(void)
176
{
177
    helper_subv_T0_T1();
178
    RETURN();
179
}
180

    
181
void OPPROTO op_trapa(void)
182
{
183
    env->tra = PARAM1 << 2;
184
    env->exception_index = 0x160;
185
    do_raise_exception();
186
    RETURN();
187
}
188

    
189
void OPPROTO op_ldcl_rMplus_rN_bank(void)
190
{
191
    env->gregs[PARAM2] = env->gregs[PARAM1];
192
    env->gregs[PARAM1] += 4;
193
    RETURN();
194
}
195

    
196
void OPPROTO op_ldc_T0_sr(void)
197
{
198
    env->sr = T0 & 0x700083f3;
199
    RETURN();
200
}
201

    
202
void OPPROTO op_stc_sr_T0(void)
203
{
204
    T0 = env->sr;
205
    RETURN();
206
}
207

    
208
#define LDSTOPS(target,load,store) \
209
void OPPROTO op_##load##_T0_##target (void) \
210
{ env ->target = T0;   RETURN(); \
211
} \
212
void OPPROTO op_##store##_##target##_T0 (void) \
213
{ T0 = env->target;   RETURN(); \
214
} \
215

    
216
    LDSTOPS(gbr, ldc, stc)
217
    LDSTOPS(vbr, ldc, stc)
218
    LDSTOPS(ssr, ldc, stc)
219
    LDSTOPS(spc, ldc, stc)
220
    LDSTOPS(sgr, ldc, stc)
221
    LDSTOPS(dbr, ldc, stc)
222
    LDSTOPS(mach, lds, sts)
223
    LDSTOPS(macl, lds, sts)
224
    LDSTOPS(pr, lds, sts)
225
    LDSTOPS(fpul, lds, sts)
226

    
227
void OPPROTO op_lds_T0_fpscr(void)
228
{
229
    env->fpscr = T0 & 0x003fffff;
230
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
231
      float_round_to_zero : float_round_nearest_even;
232

    
233
    RETURN();
234
}
235

    
236
void OPPROTO op_sts_fpscr_T0(void)
237
{
238
    T0 = env->fpscr & 0x003fffff;
239
    RETURN();
240
}
241

    
242
void OPPROTO op_rotcl_Rn(void)
243
{
244
    helper_rotcl(&env->gregs[PARAM1]);
245
    RETURN();
246
}
247

    
248
void OPPROTO op_rotcr_Rn(void)
249
{
250
    helper_rotcr(&env->gregs[PARAM1]);
251
    RETURN();
252
}
253

    
254
void OPPROTO op_rotl_Rn(void)
255
{
256
    cond_t(env->gregs[PARAM1] & 0x80000000);
257
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
258
    RETURN();
259
}
260

    
261
void OPPROTO op_rotr_Rn(void)
262
{
263
    cond_t(env->gregs[PARAM1] & 1);
264
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
265
        ((env->sr & SR_T) ? 0x80000000 : 0);
266
    RETURN();
267
}
268

    
269
void OPPROTO op_shal_Rn(void)
270
{
271
    cond_t(env->gregs[PARAM1] & 0x80000000);
272
    env->gregs[PARAM1] <<= 1;
273
    RETURN();
274
}
275

    
276
void OPPROTO op_shar_Rn(void)
277
{
278
    cond_t(env->gregs[PARAM1] & 1);
279
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
280
    RETURN();
281
}
282

    
283
void OPPROTO op_shlr_Rn(void)
284
{
285
    cond_t(env->gregs[PARAM1] & 1);
286
    env->gregs[PARAM1] >>= 1;
287
    RETURN();
288
}
289

    
290
void OPPROTO op_fmov_frN_FT0(void)
291
{
292
    FT0 = env->fregs[PARAM1];
293
    RETURN();
294
}
295

    
296
void OPPROTO op_fmov_drN_DT0(void)
297
{
298
    CPU_DoubleU d;
299

    
300
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
301
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
302
    DT0 = d.d;
303
    RETURN();
304
}
305

    
306
void OPPROTO op_fmov_frN_FT1(void)
307
{
308
    FT1 = env->fregs[PARAM1];
309
    RETURN();
310
}
311

    
312
void OPPROTO op_fmov_drN_DT1(void)
313
{
314
    CPU_DoubleU d;
315

    
316
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
317
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
318
    DT1 = d.d;
319
    RETURN();
320
}
321

    
322
void OPPROTO op_fmov_FT0_frN(void)
323
{
324
    env->fregs[PARAM1] = FT0;
325
    RETURN();
326
}
327

    
328
void OPPROTO op_fmov_DT0_drN(void)
329
{
330
    CPU_DoubleU d;
331

    
332
    d.d = DT0;
333
    *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
334
    *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
335
    RETURN();
336
}
337

    
338
void OPPROTO op_fadd_FT(void)
339
{
340
    FT0 = float32_add(FT0, FT1, &env->fp_status);
341
    RETURN();
342
}
343

    
344
void OPPROTO op_fadd_DT(void)
345
{
346
    DT0 = float64_add(DT0, DT1, &env->fp_status);
347
    RETURN();
348
}
349

    
350
void OPPROTO op_fsub_FT(void)
351
{
352
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
353
    RETURN();
354
}
355

    
356
void OPPROTO op_fsub_DT(void)
357
{
358
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
359
    RETURN();
360
}
361

    
362
void OPPROTO op_fmul_FT(void)
363
{
364
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
365
    RETURN();
366
}
367

    
368
void OPPROTO op_fmul_DT(void)
369
{
370
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
371
    RETURN();
372
}
373

    
374
void OPPROTO op_fdiv_FT(void)
375
{
376
    FT0 = float32_div(FT0, FT1, &env->fp_status);
377
    RETURN();
378
}
379

    
380
void OPPROTO op_fdiv_DT(void)
381
{
382
    DT0 = float64_div(DT0, DT1, &env->fp_status);
383
    RETURN();
384
}
385

    
386
void OPPROTO op_fcmp_eq_FT(void)
387
{
388
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
389
    RETURN();
390
}
391

    
392
void OPPROTO op_fcmp_eq_DT(void)
393
{
394
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
395
    RETURN();
396
}
397

    
398
void OPPROTO op_fcmp_gt_FT(void)
399
{
400
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
401
    RETURN();
402
}
403

    
404
void OPPROTO op_fcmp_gt_DT(void)
405
{
406
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
407
    RETURN();
408
}
409

    
410
void OPPROTO op_float_FT(void)
411
{
412
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
413
    RETURN();
414
}
415

    
416
void OPPROTO op_float_DT(void)
417
{
418
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
419
    RETURN();
420
}
421

    
422
void OPPROTO op_ftrc_FT(void)
423
{
424
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
425
    RETURN();
426
}
427

    
428
void OPPROTO op_ftrc_DT(void)
429
{
430
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
431
    RETURN();
432
}
433

    
434
void OPPROTO op_fneg_frN(void)
435
{
436
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
437
    RETURN();
438
}
439

    
440
void OPPROTO op_fabs_FT(void)
441
{
442
    FT0 = float32_abs(FT0);
443
    RETURN();
444
}
445

    
446
void OPPROTO op_fabs_DT(void)
447
{
448
    DT0 = float64_abs(DT0);
449
    RETURN();
450
}
451

    
452
void OPPROTO op_fcnvsd_FT_DT(void)
453
{
454
    DT0 = float32_to_float64(FT0, &env->fp_status);
455
    RETURN();
456
}
457

    
458
void OPPROTO op_fcnvds_DT_FT(void)
459
{
460
    FT0 = float64_to_float32(DT0, &env->fp_status);
461
    RETURN();
462
}
463

    
464
void OPPROTO op_fsqrt_FT(void)
465
{
466
    FT0 = float32_sqrt(FT0, &env->fp_status);
467
    RETURN();
468
}
469

    
470
void OPPROTO op_fsqrt_DT(void)
471
{
472
    DT0 = float64_sqrt(DT0, &env->fp_status);
473
    RETURN();
474
}
475

    
476
void OPPROTO op_fmov_T0_frN(void)
477
{
478
    *(uint32_t *)&env->fregs[PARAM1] = T0;
479
    RETURN();
480
}
481

    
482
void OPPROTO op_movl_fpul_FT0(void)
483
{
484
    FT0 = *(float32 *)&env->fpul;
485
    RETURN();
486
}
487

    
488
void OPPROTO op_movl_FT0_fpul(void)
489
{
490
    *(float32 *)&env->fpul = FT0;
491
    RETURN();
492
}
493

    
494
void OPPROTO op_raise_illegal_instruction(void)
495
{
496
    env->exception_index = 0x180;
497
    do_raise_exception();
498
    RETURN();
499
}
500

    
501
void OPPROTO op_raise_slot_illegal_instruction(void)
502
{
503
    env->exception_index = 0x1a0;
504
    do_raise_exception();
505
    RETURN();
506
}
507

    
508
void OPPROTO op_debug(void)
509
{
510
    env->exception_index = EXCP_DEBUG;
511
    cpu_loop_exit();
512
}
513

    
514
void OPPROTO op_sleep(void)
515
{
516
    env->halted = 1;
517
    env->exception_index = EXCP_HLT;
518
    cpu_loop_exit();
519
}
520

    
521
/* Load and store */
522
#define MEMSUFFIX _raw
523
#include "op_mem.c"
524
#undef MEMSUFFIX
525
#if !defined(CONFIG_USER_ONLY)
526
#define MEMSUFFIX _user
527
#include "op_mem.c"
528
#undef MEMSUFFIX
529

    
530
#define MEMSUFFIX _kernel
531
#include "op_mem.c"
532
#undef MEMSUFFIX
533
#endif