Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ 390af821

History | View | Annotate | Download (7.1 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
void helper_div1_T0_T1(void)
167
{
168
    uint32_t tmp0, tmp2;
169
    uint8_t old_q, tmp1 = 0xff;
170

    
171
    //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
172
    old_q = Q;
173
    if ((0x80000000 & T1) != 0)
174
        SETQ;
175
    else
176
        CLRQ;
177
    tmp2 = T0;
178
    T1 <<= 1;
179
    T1 |= T;
180
    switch (old_q) {
181
    case 0:
182
        switch (M) {
183
        case 0:
184
            tmp0 = T1;
185
            T1 -= tmp2;
186
            tmp1 = T1 > 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 = T1;
204
            T1 += tmp2;
205
            tmp1 = T1 < 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 = T1;
227
            T1 += tmp2;
228
            tmp1 = T1 < 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 = T1;
246
            T1 -= tmp2;
247
            tmp1 = T1 > 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: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
271
}
272

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

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

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

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

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

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

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

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

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

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

    
368
void helper_rotcl(uint32_t * addr)
369
{
370
    uint32_t new;
371

    
372
    new = (*addr << 1) | (env->sr & SR_T);
373
    if (*addr & 0x80000000)
374
        env->sr |= SR_T;
375
    else
376
        env->sr &= ~SR_T;
377
    *addr = new;
378
}
379

    
380
void helper_rotcr(uint32_t * addr)
381
{
382
    uint32_t new;
383

    
384
    new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
385
    if (*addr & 1)
386
        env->sr |= SR_T;
387
    else
388
        env->sr &= ~SR_T;
389
    *addr = new;
390
}
391

    
392
void helper_ld_fpscr(uint32_t val)
393
{
394
    env->fpscr = val & 0x003fffff;
395
    if (val & 0x01)
396
        set_float_rounding_mode(float_round_to_zero, &env->fp_status);
397
    else
398
        set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
399
}