Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ e6afc2f4

History | View | Annotate | Download (8.6 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_frchg(void)
41
{
42
    env->fpscr ^= FPSCR_FR;
43
    RETURN();
44
}
45

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

    
52
void OPPROTO op_addc_T0_T1(void)
53
{
54
    helper_addc_T0_T1();
55
    RETURN();
56
}
57

    
58
void OPPROTO op_addv_T0_T1(void)
59
{
60
    helper_addv_T0_T1();
61
    RETURN();
62
}
63

    
64
void OPPROTO op_cmp_str_T0_T1(void)
65
{
66
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
67
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
68
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
69
           (T0 & 0xff000000) == (T1 & 0xff000000));
70
    RETURN();
71
}
72

    
73
void OPPROTO op_div0s_T0_T1(void)
74
{
75
    if (T1 & 0x80000000)
76
        env->sr |= SR_Q;
77
    else
78
        env->sr &= ~SR_Q;
79
    if (T0 & 0x80000000)
80
        env->sr |= SR_M;
81
    else
82
        env->sr &= ~SR_M;
83
    cond_t((T1 ^ T0) & 0x80000000);
84
    RETURN();
85
}
86

    
87
void OPPROTO op_div1_T0_T1(void)
88
{
89
    helper_div1_T0_T1();
90
    RETURN();
91
}
92

    
93
void OPPROTO op_dmulsl_T0_T1(void)
94
{
95
    helper_dmulsl_T0_T1();
96
    RETURN();
97
}
98

    
99
void OPPROTO op_dmulul_T0_T1(void)
100
{
101
    helper_dmulul_T0_T1();
102
    RETURN();
103
}
104

    
105
void OPPROTO op_macl_T0_T1(void)
106
{
107
    helper_macl_T0_T1();
108
    RETURN();
109
}
110

    
111
void OPPROTO op_macw_T0_T1(void)
112
{
113
    helper_macw_T0_T1();
114
    RETURN();
115
}
116

    
117
void OPPROTO op_mull_T0_T1(void)
118
{
119
    env->macl = (T0 * T1) & 0xffffffff;
120
    RETURN();
121
}
122

    
123
void OPPROTO op_mulsw_T0_T1(void)
124
{
125
    env->macl = (int32_t)(int16_t) T0 *(int32_t)(int16_t) T1;
126
    RETURN();
127
}
128

    
129
void OPPROTO op_muluw_T0_T1(void)
130
{
131
    env->macl = (uint32_t)(uint16_t) T0 *(uint32_t)(uint16_t) T1;
132
    RETURN();
133
}
134

    
135
void OPPROTO op_negc_T0(void)
136
{
137
    helper_negc_T0();
138
    RETURN();
139
}
140

    
141
void OPPROTO op_shad_T0_T1(void)
142
{
143
    if ((T0 & 0x80000000) == 0)
144
        T1 <<= (T0 & 0x1f);
145
    else if ((T0 & 0x1f) == 0)
146
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
147
    else
148
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
149
    RETURN();
150
}
151

    
152
void OPPROTO op_shld_T0_T1(void)
153
{
154
    if ((T0 & 0x80000000) == 0)
155
        T1 <<= (T0 & 0x1f);
156
    else if ((T0 & 0x1f) == 0)
157
        T1 = 0;
158
    else
159
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
160
    RETURN();
161
}
162

    
163
void OPPROTO op_subc_T0_T1(void)
164
{
165
    helper_subc_T0_T1();
166
    RETURN();
167
}
168

    
169
void OPPROTO op_subv_T0_T1(void)
170
{
171
    helper_subv_T0_T1();
172
    RETURN();
173
}
174

    
175
void OPPROTO op_ldcl_rMplus_rN_bank(void)
176
{
177
    env->gregs[PARAM2] = env->gregs[PARAM1];
178
    env->gregs[PARAM1] += 4;
179
    RETURN();
180
}
181

    
182
void OPPROTO op_ldc_T0_sr(void)
183
{
184
    env->sr = T0 & 0x700083f3;
185
    RETURN();
186
}
187

    
188
void OPPROTO op_stc_sr_T0(void)
189
{
190
    T0 = env->sr;
191
    RETURN();
192
}
193

    
194
#define LDSTOPS(target,load,store) \
195
void OPPROTO op_##load##_T0_##target (void) \
196
{ env ->target = T0;   RETURN(); \
197
} \
198
void OPPROTO op_##store##_##target##_T0 (void) \
199
{ T0 = env->target;   RETURN(); \
200
} \
201

    
202
    LDSTOPS(gbr, ldc, stc)
203
    LDSTOPS(vbr, ldc, stc)
204
    LDSTOPS(ssr, ldc, stc)
205
    LDSTOPS(spc, ldc, stc)
206
    LDSTOPS(sgr, ldc, stc)
207
    LDSTOPS(dbr, ldc, stc)
208
    LDSTOPS(mach, lds, sts)
209
    LDSTOPS(macl, lds, sts)
210
    LDSTOPS(pr, lds, sts)
211
    LDSTOPS(fpul, lds, sts)
212

    
213
void OPPROTO op_lds_T0_fpscr(void)
214
{
215
    env->fpscr = T0 & 0x003fffff;
216
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
217
      float_round_to_zero : float_round_nearest_even;
218

    
219
    RETURN();
220
}
221

    
222
void OPPROTO op_sts_fpscr_T0(void)
223
{
224
    T0 = env->fpscr & 0x003fffff;
225
    RETURN();
226
}
227

    
228
void OPPROTO op_rotcl_Rn(void)
229
{
230
    helper_rotcl(&env->gregs[PARAM1]);
231
    RETURN();
232
}
233

    
234
void OPPROTO op_rotcr_Rn(void)
235
{
236
    helper_rotcr(&env->gregs[PARAM1]);
237
    RETURN();
238
}
239

    
240
void OPPROTO op_rotl_Rn(void)
241
{
242
    cond_t(env->gregs[PARAM1] & 0x80000000);
243
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
244
    RETURN();
245
}
246

    
247
void OPPROTO op_rotr_Rn(void)
248
{
249
    cond_t(env->gregs[PARAM1] & 1);
250
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
251
        ((env->sr & SR_T) ? 0x80000000 : 0);
252
    RETURN();
253
}
254

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

    
262
void OPPROTO op_shar_Rn(void)
263
{
264
    cond_t(env->gregs[PARAM1] & 1);
265
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
266
    RETURN();
267
}
268

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

    
276
void OPPROTO op_fmov_frN_FT0(void)
277
{
278
    FT0 = env->fregs[PARAM1];
279
    RETURN();
280
}
281

    
282
void OPPROTO op_fmov_drN_DT0(void)
283
{
284
    CPU_DoubleU d;
285

    
286
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
287
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
288
    DT0 = d.d;
289
    RETURN();
290
}
291

    
292
void OPPROTO op_fmov_frN_FT1(void)
293
{
294
    FT1 = env->fregs[PARAM1];
295
    RETURN();
296
}
297

    
298
void OPPROTO op_fmov_drN_DT1(void)
299
{
300
    CPU_DoubleU d;
301

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

    
308
void OPPROTO op_fmov_FT0_frN(void)
309
{
310
    env->fregs[PARAM1] = FT0;
311
    RETURN();
312
}
313

    
314
void OPPROTO op_fmov_DT0_drN(void)
315
{
316
    CPU_DoubleU d;
317

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

    
324
void OPPROTO op_fadd_FT(void)
325
{
326
    FT0 = float32_add(FT0, FT1, &env->fp_status);
327
    RETURN();
328
}
329

    
330
void OPPROTO op_fadd_DT(void)
331
{
332
    DT0 = float64_add(DT0, DT1, &env->fp_status);
333
    RETURN();
334
}
335

    
336
void OPPROTO op_fsub_FT(void)
337
{
338
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
339
    RETURN();
340
}
341

    
342
void OPPROTO op_fsub_DT(void)
343
{
344
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
345
    RETURN();
346
}
347

    
348
void OPPROTO op_fmul_FT(void)
349
{
350
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
351
    RETURN();
352
}
353

    
354
void OPPROTO op_fmul_DT(void)
355
{
356
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
357
    RETURN();
358
}
359

    
360
void OPPROTO op_fdiv_FT(void)
361
{
362
    FT0 = float32_div(FT0, FT1, &env->fp_status);
363
    RETURN();
364
}
365

    
366
void OPPROTO op_fdiv_DT(void)
367
{
368
    DT0 = float64_div(DT0, DT1, &env->fp_status);
369
    RETURN();
370
}
371

    
372
void OPPROTO op_fcmp_eq_FT(void)
373
{
374
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
375
    RETURN();
376
}
377

    
378
void OPPROTO op_fcmp_eq_DT(void)
379
{
380
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
381
    RETURN();
382
}
383

    
384
void OPPROTO op_fcmp_gt_FT(void)
385
{
386
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
387
    RETURN();
388
}
389

    
390
void OPPROTO op_fcmp_gt_DT(void)
391
{
392
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
393
    RETURN();
394
}
395

    
396
void OPPROTO op_float_FT(void)
397
{
398
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
399
    RETURN();
400
}
401

    
402
void OPPROTO op_float_DT(void)
403
{
404
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
405
    RETURN();
406
}
407

    
408
void OPPROTO op_ftrc_FT(void)
409
{
410
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
411
    RETURN();
412
}
413

    
414
void OPPROTO op_ftrc_DT(void)
415
{
416
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
417
    RETURN();
418
}
419

    
420
void OPPROTO op_fneg_frN(void)
421
{
422
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
423
    RETURN();
424
}
425

    
426
void OPPROTO op_fabs_FT(void)
427
{
428
    FT0 = float32_abs(FT0);
429
    RETURN();
430
}
431

    
432
void OPPROTO op_fabs_DT(void)
433
{
434
    DT0 = float64_abs(DT0);
435
    RETURN();
436
}
437

    
438
void OPPROTO op_fcnvsd_FT_DT(void)
439
{
440
    DT0 = float32_to_float64(FT0, &env->fp_status);
441
    RETURN();
442
}
443

    
444
void OPPROTO op_fcnvds_DT_FT(void)
445
{
446
    FT0 = float64_to_float32(DT0, &env->fp_status);
447
    RETURN();
448
}
449

    
450
void OPPROTO op_fsqrt_FT(void)
451
{
452
    FT0 = float32_sqrt(FT0, &env->fp_status);
453
    RETURN();
454
}
455

    
456
void OPPROTO op_fsqrt_DT(void)
457
{
458
    DT0 = float64_sqrt(DT0, &env->fp_status);
459
    RETURN();
460
}
461

    
462
void OPPROTO op_fmov_T0_frN(void)
463
{
464
    *(uint32_t *)&env->fregs[PARAM1] = T0;
465
    RETURN();
466
}
467

    
468
void OPPROTO op_movl_fpul_FT0(void)
469
{
470
    FT0 = *(float32 *)&env->fpul;
471
    RETURN();
472
}
473

    
474
void OPPROTO op_movl_FT0_fpul(void)
475
{
476
    *(float32 *)&env->fpul = FT0;
477
    RETURN();
478
}
479

    
480
/* Load and store */
481
#define MEMSUFFIX _raw
482
#include "op_mem.c"
483
#undef MEMSUFFIX
484
#if !defined(CONFIG_USER_ONLY)
485
#define MEMSUFFIX _user
486
#include "op_mem.c"
487
#undef MEMSUFFIX
488

    
489
#define MEMSUFFIX _kernel
490
#include "op_mem.c"
491
#undef MEMSUFFIX
492
#endif