Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ f24f381b

History | View | Annotate | Download (10.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 <assert.h>
21
#include "exec.h"
22

    
23
#ifndef CONFIG_USER_ONLY
24

    
25
#define MMUSUFFIX _mmu
26

    
27
#define SHIFT 0
28
#include "softmmu_template.h"
29

    
30
#define SHIFT 1
31
#include "softmmu_template.h"
32

    
33
#define SHIFT 2
34
#include "softmmu_template.h"
35

    
36
#define SHIFT 3
37
#include "softmmu_template.h"
38

    
39
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
40
{
41
    TranslationBlock *tb;
42
    CPUState *saved_env;
43
    unsigned long pc;
44
    int ret;
45

    
46
    /* XXX: hack to restore env in all cases, even if not called from
47
       generated code */
48
    saved_env = env;
49
    env = cpu_single_env;
50
    ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
51
    if (ret) {
52
        if (retaddr) {
53
            /* now we have a real cpu fault */
54
            pc = (unsigned long) retaddr;
55
            tb = tb_find_pc(pc);
56
            if (tb) {
57
                /* the PC is inside the translated code. It means that we have
58
                   a virtual CPU fault */
59
                cpu_restore_state(tb, env, pc, NULL);
60
            }
61
        }
62
        cpu_loop_exit();
63
    }
64
    env = saved_env;
65
}
66

    
67
#endif
68

    
69
void helper_ldtlb(void)
70
{
71
#ifdef CONFIG_USER_ONLY
72
    /* XXXXX */
73
    assert(0);
74
#else
75
    cpu_load_tlb(env);
76
#endif
77
}
78

    
79
void helper_raise_illegal_instruction(void)
80
{
81
    env->exception_index = 0x180;
82
    cpu_loop_exit();
83
}
84

    
85
void helper_raise_slot_illegal_instruction(void)
86
{
87
    env->exception_index = 0x1a0;
88
    cpu_loop_exit();
89
}
90

    
91
void helper_debug(void)
92
{
93
    env->exception_index = EXCP_DEBUG;
94
    cpu_loop_exit();
95
}
96

    
97
void helper_sleep(uint32_t next_pc)
98
{
99
    env->halted = 1;
100
    env->exception_index = EXCP_HLT;
101
    env->pc = next_pc;
102
    cpu_loop_exit();
103
}
104

    
105
void helper_trapa(uint32_t tra)
106
{
107
    env->tra = tra << 2;
108
    env->exception_index = 0x160;
109
    cpu_loop_exit();
110
}
111

    
112
uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
113
{
114
    uint32_t tmp0, tmp1;
115

    
116
    tmp1 = arg0 + arg1;
117
    tmp0 = arg1;
118
    arg1 = tmp1 + (env->sr & 1);
119
    if (tmp0 > tmp1)
120
        env->sr |= SR_T;
121
    else
122
        env->sr &= ~SR_T;
123
    if (tmp1 > arg1)
124
        env->sr |= SR_T;
125
    return arg1;
126
}
127

    
128
uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
129
{
130
    uint32_t dest, src, ans;
131

    
132
    if ((int32_t) arg1 >= 0)
133
        dest = 0;
134
    else
135
        dest = 1;
136
    if ((int32_t) arg0 >= 0)
137
        src = 0;
138
    else
139
        src = 1;
140
    src += dest;
141
    arg1 += arg0;
142
    if ((int32_t) arg1 >= 0)
143
        ans = 0;
144
    else
145
        ans = 1;
146
    ans += dest;
147
    if (src == 0 || src == 2) {
148
        if (ans == 1)
149
            env->sr |= SR_T;
150
        else
151
            env->sr &= ~SR_T;
152
    } else
153
        env->sr &= ~SR_T;
154
    return arg1;
155
}
156

    
157
#define T (env->sr & SR_T)
158
#define Q (env->sr & SR_Q ? 1 : 0)
159
#define M (env->sr & SR_M ? 1 : 0)
160
#define SETT env->sr |= SR_T
161
#define CLRT env->sr &= ~SR_T
162
#define SETQ env->sr |= SR_Q
163
#define CLRQ env->sr &= ~SR_Q
164
#define SETM env->sr |= SR_M
165
#define CLRM env->sr &= ~SR_M
166

    
167
uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
168
{
169
    uint32_t tmp0, tmp2;
170
    uint8_t old_q, tmp1 = 0xff;
171

    
172
    //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
173
    old_q = Q;
174
    if ((0x80000000 & arg1) != 0)
175
        SETQ;
176
    else
177
        CLRQ;
178
    tmp2 = arg0;
179
    arg1 <<= 1;
180
    arg1 |= T;
181
    switch (old_q) {
182
    case 0:
183
        switch (M) {
184
        case 0:
185
            tmp0 = arg1;
186
            arg1 -= tmp2;
187
            tmp1 = arg1 > tmp0;
188
            switch (Q) {
189
            case 0:
190
                if (tmp1)
191
                    SETQ;
192
                else
193
                    CLRQ;
194
                break;
195
            case 1:
196
                if (tmp1 == 0)
197
                    SETQ;
198
                else
199
                    CLRQ;
200
                break;
201
            }
202
            break;
203
        case 1:
204
            tmp0 = arg1;
205
            arg1 += tmp2;
206
            tmp1 = arg1 < tmp0;
207
            switch (Q) {
208
            case 0:
209
                if (tmp1 == 0)
210
                    SETQ;
211
                else
212
                    CLRQ;
213
                break;
214
            case 1:
215
                if (tmp1)
216
                    SETQ;
217
                else
218
                    CLRQ;
219
                break;
220
            }
221
            break;
222
        }
223
        break;
224
    case 1:
225
        switch (M) {
226
        case 0:
227
            tmp0 = arg1;
228
            arg1 += tmp2;
229
            tmp1 = arg1 < tmp0;
230
            switch (Q) {
231
            case 0:
232
                if (tmp1)
233
                    SETQ;
234
                else
235
                    CLRQ;
236
                break;
237
            case 1:
238
                if (tmp1 == 0)
239
                    SETQ;
240
                else
241
                    CLRQ;
242
                break;
243
            }
244
            break;
245
        case 1:
246
            tmp0 = arg1;
247
            arg1 -= tmp2;
248
            tmp1 = arg1 > tmp0;
249
            switch (Q) {
250
            case 0:
251
                if (tmp1 == 0)
252
                    SETQ;
253
                else
254
                    CLRQ;
255
                break;
256
            case 1:
257
                if (tmp1)
258
                    SETQ;
259
                else
260
                    CLRQ;
261
                break;
262
            }
263
            break;
264
        }
265
        break;
266
    }
267
    if (Q == M)
268
        SETT;
269
    else
270
        CLRT;
271
    //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
272
    return arg1;
273
}
274

    
275
void helper_macl(uint32_t arg0, uint32_t arg1)
276
{
277
    int64_t res;
278

    
279
    res = ((uint64_t) env->mach << 32) | env->macl;
280
    res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
281
    env->mach = (res >> 32) & 0xffffffff;
282
    env->macl = res & 0xffffffff;
283
    if (env->sr & SR_S) {
284
        if (res < 0)
285
            env->mach |= 0xffff0000;
286
        else
287
            env->mach &= 0x00007fff;
288
    }
289
}
290

    
291
void helper_macw(uint32_t arg0, uint32_t arg1)
292
{
293
    int64_t res;
294

    
295
    res = ((uint64_t) env->mach << 32) | env->macl;
296
    res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
297
    env->mach = (res >> 32) & 0xffffffff;
298
    env->macl = res & 0xffffffff;
299
    if (env->sr & SR_S) {
300
        if (res < -0x80000000) {
301
            env->mach = 1;
302
            env->macl = 0x80000000;
303
        } else if (res > 0x000000007fffffff) {
304
            env->mach = 1;
305
            env->macl = 0x7fffffff;
306
        }
307
    }
308
}
309

    
310
uint32_t helper_negc(uint32_t arg)
311
{
312
    uint32_t temp;
313

    
314
    temp = -arg;
315
    arg = temp - (env->sr & SR_T);
316
    if (0 < temp)
317
        env->sr |= SR_T;
318
    else
319
        env->sr &= ~SR_T;
320
    if (temp < arg)
321
        env->sr |= SR_T;
322
    return arg;
323
}
324

    
325
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
326
{
327
    uint32_t tmp0, tmp1;
328

    
329
    tmp1 = arg1 - arg0;
330
    tmp0 = arg1;
331
    arg1 = tmp1 - (env->sr & SR_T);
332
    if (tmp0 < tmp1)
333
        env->sr |= SR_T;
334
    else
335
        env->sr &= ~SR_T;
336
    if (tmp1 < arg1)
337
        env->sr |= SR_T;
338
    return arg1;
339
}
340

    
341
uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
342
{
343
    int32_t dest, src, ans;
344

    
345
    if ((int32_t) arg1 >= 0)
346
        dest = 0;
347
    else
348
        dest = 1;
349
    if ((int32_t) arg0 >= 0)
350
        src = 0;
351
    else
352
        src = 1;
353
    src += dest;
354
    arg1 -= arg0;
355
    if ((int32_t) arg1 >= 0)
356
        ans = 0;
357
    else
358
        ans = 1;
359
    ans += dest;
360
    if (src == 1) {
361
        if (ans == 1)
362
            env->sr |= SR_T;
363
        else
364
            env->sr &= ~SR_T;
365
    } else
366
        env->sr &= ~SR_T;
367
    return arg1;
368
}
369

    
370
static inline void set_t(void)
371
{
372
    env->sr |= SR_T;
373
}
374

    
375
static inline void clr_t(void)
376
{
377
    env->sr &= ~SR_T;
378
}
379

    
380
void helper_ld_fpscr(uint32_t val)
381
{
382
    env->fpscr = val & 0x003fffff;
383
    if (val & 0x01)
384
        set_float_rounding_mode(float_round_to_zero, &env->fp_status);
385
    else
386
        set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
387
}
388

    
389
uint32_t helper_fabs_FT(uint32_t t0)
390
{
391
    float32 ret = float32_abs(*(float32*)&t0);
392
    return *(uint32_t*)(&ret);
393
}
394

    
395
uint64_t helper_fabs_DT(uint64_t t0)
396
{
397
    float64 ret = float64_abs(*(float64*)&t0);
398
    return *(uint64_t*)(&ret);
399
}
400

    
401
uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
402
{
403
    float32 ret = float32_add(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
404
    return *(uint32_t*)(&ret);
405
}
406

    
407
uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
408
{
409
    float64 ret = float64_add(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
410
    return *(uint64_t*)(&ret);
411
}
412

    
413
void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
414
{
415
    if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 0)
416
        set_t();
417
    else
418
        clr_t();
419
}
420

    
421
void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
422
{
423
    if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 0)
424
        set_t();
425
    else
426
        clr_t();
427
}
428

    
429
void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
430
{
431
    if (float32_compare(*(float32*)&t0, *(float32*)&t1, &env->fp_status) == 1)
432
        set_t();
433
    else
434
        clr_t();
435
}
436

    
437
void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
438
{
439
    if (float64_compare(*(float64*)&t0, *(float64*)&t1, &env->fp_status) == 1)
440
        set_t();
441
    else
442
        clr_t();
443
}
444

    
445
uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
446
{
447
    float64 ret = float32_to_float64(*(float32*)&t0, &env->fp_status);
448
    return *(uint64_t*)(&ret);
449
}
450

    
451
uint32_t helper_fcnvds_DT_FT(uint64_t t0)
452
{
453
    float32 ret = float64_to_float32(*(float64*)&t0, &env->fp_status);
454
    return *(uint32_t*)(&ret);
455
}
456

    
457
uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
458
{
459
    float32 ret = float32_div(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
460
    return *(uint32_t*)(&ret);
461
}
462

    
463
uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
464
{
465
    float64 ret = float64_div(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
466
    return *(uint64_t*)(&ret);
467
}
468

    
469
uint32_t helper_float_FT(uint32_t t0)
470
{
471
    float32 ret = int32_to_float32(t0, &env->fp_status);
472
    return *(uint32_t*)(&ret);
473
}
474

    
475
uint64_t helper_float_DT(uint32_t t0)
476
{
477
    float64 ret = int32_to_float64(t0, &env->fp_status);
478
    return *(uint64_t*)(&ret);
479
}
480

    
481
uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
482
{
483
    float32 ret = float32_mul(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
484
    return *(uint32_t*)(&ret);
485
}
486

    
487
uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
488
{
489
    float64 ret = float64_mul(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
490
    return *(uint64_t*)(&ret);
491
}
492

    
493
uint32_t helper_fneg_T(uint32_t t0)
494
{
495
    float32 ret = float32_chs(*(float32*)&t0);
496
    return *(uint32_t*)(&ret);
497
}
498

    
499
uint32_t helper_fsqrt_FT(uint32_t t0)
500
{
501
    float32 ret = float32_sqrt(*(float32*)&t0, &env->fp_status);
502
    return *(uint32_t*)(&ret);
503
}
504

    
505
uint64_t helper_fsqrt_DT(uint64_t t0)
506
{
507
    float64 ret = float64_sqrt(*(float64*)&t0, &env->fp_status);
508
    return *(uint64_t*)(&ret);
509
}
510

    
511
uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
512
{
513
    float32 ret = float32_sub(*(float32*)&t0, *(float32*)&t1, &env->fp_status);
514
    return *(uint32_t*)(&ret);
515
}
516

    
517
uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
518
{
519
    float64 ret = float64_sub(*(float64*)&t0, *(float64*)&t1, &env->fp_status);
520
    return *(uint64_t*)(&ret);
521
}
522

    
523
uint32_t helper_ftrc_FT(uint32_t t0)
524
{
525
    return float32_to_int32_round_to_zero(*(float32*)&t0, &env->fp_status);
526
}
527

    
528
uint32_t helper_ftrc_DT(uint64_t t0)
529
{
530
    return float64_to_int32_round_to_zero(*(float64*)&t0, &env->fp_status);
531
}