Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ 69d6275b

History | View | Annotate | Download (6.8 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(void)
98
{
99
    env->halted = 1;
100
    env->exception_index = EXCP_HLT;
101
    cpu_loop_exit();
102
}
103

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
369
void helper_ld_fpscr(uint32_t val)
370
{
371
    env->fpscr = val & 0x003fffff;
372
    if (val & 0x01)
373
        set_float_rounding_mode(float_round_to_zero, &env->fp_status);
374
    else
375
        set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
376
}