Statistics
| Branch: | Revision:

root / target-sh4 / op.c @ 6f06939b

History | View | Annotate | Download (7.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_cmp_str_T0_T1(void)
41
{
42
    cond_t((T0 & 0x000000ff) == (T1 & 0x000000ff) ||
43
           (T0 & 0x0000ff00) == (T1 & 0x0000ff00) ||
44
           (T0 & 0x00ff0000) == (T1 & 0x00ff0000) ||
45
           (T0 & 0xff000000) == (T1 & 0xff000000));
46
    RETURN();
47
}
48

    
49
void OPPROTO op_div0s_T0_T1(void)
50
{
51
    if (T1 & 0x80000000)
52
        env->sr |= SR_Q;
53
    else
54
        env->sr &= ~SR_Q;
55
    if (T0 & 0x80000000)
56
        env->sr |= SR_M;
57
    else
58
        env->sr &= ~SR_M;
59
    cond_t((T1 ^ T0) & 0x80000000);
60
    RETURN();
61
}
62

    
63
void OPPROTO op_div1_T0_T1(void)
64
{
65
    helper_div1_T0_T1();
66
    RETURN();
67
}
68

    
69
void OPPROTO op_shad_T0_T1(void)
70
{
71
    if ((T0 & 0x80000000) == 0)
72
        T1 <<= (T0 & 0x1f);
73
    else if ((T0 & 0x1f) == 0)
74
        T1 = (T1 & 0x80000000)? 0xffffffff : 0;
75
    else
76
        T1 = ((int32_t) T1) >> ((~T0 & 0x1f) + 1);
77
    RETURN();
78
}
79

    
80
void OPPROTO op_shld_T0_T1(void)
81
{
82
    if ((T0 & 0x80000000) == 0)
83
        T1 <<= (T0 & 0x1f);
84
    else if ((T0 & 0x1f) == 0)
85
        T1 = 0;
86
    else
87
        T1 = ((uint32_t) T1) >> ((~T0 & 0x1f) + 1);
88
    RETURN();
89
}
90

    
91
void OPPROTO op_ldc_T0_sr(void)
92
{
93
    env->sr = T0 & 0x700083f3;
94
    RETURN();
95
}
96

    
97
void OPPROTO op_stc_sr_T0(void)
98
{
99
    T0 = env->sr;
100
    RETURN();
101
}
102

    
103
#define LDSTOPS(target,load,store) \
104
void OPPROTO op_##load##_T0_##target (void) \
105
{ env ->target = T0;   RETURN(); \
106
} \
107
void OPPROTO op_##store##_##target##_T0 (void) \
108
{ T0 = env->target;   RETURN(); \
109
} \
110

    
111
    LDSTOPS(gbr, ldc, stc)
112
    LDSTOPS(vbr, ldc, stc)
113
    LDSTOPS(ssr, ldc, stc)
114
    LDSTOPS(spc, ldc, stc)
115
    LDSTOPS(sgr, ldc, stc)
116
    LDSTOPS(dbr, ldc, stc)
117
    LDSTOPS(mach, lds, sts)
118
    LDSTOPS(macl, lds, sts)
119
    LDSTOPS(pr, lds, sts)
120
    LDSTOPS(fpul, lds, sts)
121

    
122
void OPPROTO op_lds_T0_fpscr(void)
123
{
124
    env->fpscr = T0 & 0x003fffff;
125
    env->fp_status.float_rounding_mode = T0 & 0x01 ?
126
      float_round_to_zero : float_round_nearest_even;
127

    
128
    RETURN();
129
}
130

    
131
void OPPROTO op_sts_fpscr_T0(void)
132
{
133
    T0 = env->fpscr & 0x003fffff;
134
    RETURN();
135
}
136

    
137
void OPPROTO op_rotcl_Rn(void)
138
{
139
    helper_rotcl(&env->gregs[PARAM1]);
140
    RETURN();
141
}
142

    
143
void OPPROTO op_rotcr_Rn(void)
144
{
145
    helper_rotcr(&env->gregs[PARAM1]);
146
    RETURN();
147
}
148

    
149
void OPPROTO op_rotl_Rn(void) 
150
{
151
    cond_t(env->gregs[PARAM1] & 0x80000000);
152
    env->gregs[PARAM1] = (env->gregs[PARAM1] << 1) | (env->sr & SR_T);
153
    RETURN();
154
}
155

    
156
void OPPROTO op_rotr_Rn(void)
157
{
158
    cond_t(env->gregs[PARAM1] & 1);
159
    env->gregs[PARAM1] = (env->gregs[PARAM1] >> 1) |
160
        ((env->sr & SR_T) ? 0x80000000 : 0);
161
    RETURN();
162
}
163

    
164
void OPPROTO op_shal_Rn(void)
165
{
166
    cond_t(env->gregs[PARAM1] & 0x80000000);
167
    env->gregs[PARAM1] <<= 1;
168
    RETURN();
169
}
170

    
171
void OPPROTO op_shar_Rn(void)
172
{
173
    cond_t(env->gregs[PARAM1] & 1);
174
    *(int32_t *)&env->gregs[PARAM1] >>= 1;
175
    RETURN();
176
}
177

    
178
void OPPROTO op_shlr_Rn(void)
179
{
180
    cond_t(env->gregs[PARAM1] & 1);
181
    env->gregs[PARAM1] >>= 1;
182
    RETURN();
183
}
184

    
185
void OPPROTO op_fmov_frN_FT0(void)
186
{
187
    FT0 = env->fregs[PARAM1];
188
    RETURN();
189
}
190

    
191
void OPPROTO op_fmov_drN_DT0(void)
192
{
193
    CPU_DoubleU d;
194

    
195
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
196
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
197
    DT0 = d.d;
198
    RETURN();
199
}
200

    
201
void OPPROTO op_fmov_frN_FT1(void)
202
{
203
    FT1 = env->fregs[PARAM1];
204
    RETURN();
205
}
206

    
207
void OPPROTO op_fmov_drN_DT1(void)
208
{
209
    CPU_DoubleU d;
210

    
211
    d.l.upper = *(uint32_t *)&env->fregs[PARAM1];
212
    d.l.lower = *(uint32_t *)&env->fregs[PARAM1 + 1];
213
    DT1 = d.d;
214
    RETURN();
215
}
216

    
217
void OPPROTO op_fmov_FT0_frN(void)
218
{
219
    env->fregs[PARAM1] = FT0;
220
    RETURN();
221
}
222

    
223
void OPPROTO op_fmov_DT0_drN(void)
224
{
225
    CPU_DoubleU d;
226

    
227
    d.d = DT0;
228
    *(uint32_t *)&env->fregs[PARAM1] = d.l.upper;
229
    *(uint32_t *)&env->fregs[PARAM1 + 1] = d.l.lower;
230
    RETURN();
231
}
232

    
233
void OPPROTO op_fadd_FT(void)
234
{
235
    FT0 = float32_add(FT0, FT1, &env->fp_status);
236
    RETURN();
237
}
238

    
239
void OPPROTO op_fadd_DT(void)
240
{
241
    DT0 = float64_add(DT0, DT1, &env->fp_status);
242
    RETURN();
243
}
244

    
245
void OPPROTO op_fsub_FT(void)
246
{
247
    FT0 = float32_sub(FT0, FT1, &env->fp_status);
248
    RETURN();
249
}
250

    
251
void OPPROTO op_fsub_DT(void)
252
{
253
    DT0 = float64_sub(DT0, DT1, &env->fp_status);
254
    RETURN();
255
}
256

    
257
void OPPROTO op_fmul_FT(void)
258
{
259
    FT0 = float32_mul(FT0, FT1, &env->fp_status);
260
    RETURN();
261
}
262

    
263
void OPPROTO op_fmul_DT(void)
264
{
265
    DT0 = float64_mul(DT0, DT1, &env->fp_status);
266
    RETURN();
267
}
268

    
269
void OPPROTO op_fdiv_FT(void)
270
{
271
    FT0 = float32_div(FT0, FT1, &env->fp_status);
272
    RETURN();
273
}
274

    
275
void OPPROTO op_fdiv_DT(void)
276
{
277
    DT0 = float64_div(DT0, DT1, &env->fp_status);
278
    RETURN();
279
}
280

    
281
void OPPROTO op_fcmp_eq_FT(void)
282
{
283
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 0);
284
    RETURN();
285
}
286

    
287
void OPPROTO op_fcmp_eq_DT(void)
288
{
289
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 0);
290
    RETURN();
291
}
292

    
293
void OPPROTO op_fcmp_gt_FT(void)
294
{
295
    cond_t(float32_compare(FT0, FT1, &env->fp_status) == 1);
296
    RETURN();
297
}
298

    
299
void OPPROTO op_fcmp_gt_DT(void)
300
{
301
    cond_t(float64_compare(DT0, DT1, &env->fp_status) == 1);
302
    RETURN();
303
}
304

    
305
void OPPROTO op_float_FT(void)
306
{
307
    FT0 = int32_to_float32(env->fpul, &env->fp_status);
308
    RETURN();
309
}
310

    
311
void OPPROTO op_float_DT(void)
312
{
313
    DT0 = int32_to_float64(env->fpul, &env->fp_status);
314
    RETURN();
315
}
316

    
317
void OPPROTO op_ftrc_FT(void)
318
{
319
    env->fpul = float32_to_int32_round_to_zero(FT0, &env->fp_status);
320
    RETURN();
321
}
322

    
323
void OPPROTO op_ftrc_DT(void)
324
{
325
    env->fpul = float64_to_int32_round_to_zero(DT0, &env->fp_status);
326
    RETURN();
327
}
328

    
329
void OPPROTO op_fneg_frN(void)
330
{
331
    env->fregs[PARAM1] = float32_chs(env->fregs[PARAM1]);
332
    RETURN();
333
}
334

    
335
void OPPROTO op_fabs_FT(void)
336
{
337
    FT0 = float32_abs(FT0);
338
    RETURN();
339
}
340

    
341
void OPPROTO op_fabs_DT(void)
342
{
343
    DT0 = float64_abs(DT0);
344
    RETURN();
345
}
346

    
347
void OPPROTO op_fcnvsd_FT_DT(void)
348
{
349
    DT0 = float32_to_float64(FT0, &env->fp_status);
350
    RETURN();
351
}
352

    
353
void OPPROTO op_fcnvds_DT_FT(void)
354
{
355
    FT0 = float64_to_float32(DT0, &env->fp_status);
356
    RETURN();
357
}
358

    
359
void OPPROTO op_fsqrt_FT(void)
360
{
361
    FT0 = float32_sqrt(FT0, &env->fp_status);
362
    RETURN();
363
}
364

    
365
void OPPROTO op_fsqrt_DT(void)
366
{
367
    DT0 = float64_sqrt(DT0, &env->fp_status);
368
    RETURN();
369
}
370

    
371
void OPPROTO op_fmov_T0_frN(void)
372
{
373
    *(uint32_t *)&env->fregs[PARAM1] = T0;
374
    RETURN();
375
}
376

    
377
void OPPROTO op_movl_fpul_FT0(void)
378
{
379
    FT0 = *(float32 *)&env->fpul;
380
    RETURN();
381
}
382

    
383
void OPPROTO op_movl_FT0_fpul(void)
384
{
385
    *(float32 *)&env->fpul = FT0;
386
    RETURN();
387
}
388

    
389
/* Load and store */
390
#define MEMSUFFIX _raw
391
#include "op_mem.c"
392
#undef MEMSUFFIX
393
#if !defined(CONFIG_USER_ONLY)
394
#define MEMSUFFIX _user
395
#include "op_mem.c"
396
#undef MEMSUFFIX
397

    
398
#define MEMSUFFIX _kernel
399
#include "op_mem.c"
400
#undef MEMSUFFIX
401
#endif