Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ 9b7b85d2

History | View | Annotate | Download (6.5 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
void do_raise_exception(void)
24
{
25
    cpu_loop_exit();
26
}
27

    
28
#ifndef CONFIG_USER_ONLY
29

    
30
#define MMUSUFFIX _mmu
31

    
32
#define SHIFT 0
33
#include "softmmu_template.h"
34

    
35
#define SHIFT 1
36
#include "softmmu_template.h"
37

    
38
#define SHIFT 2
39
#include "softmmu_template.h"
40

    
41
#define SHIFT 3
42
#include "softmmu_template.h"
43

    
44
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
45
{
46
    TranslationBlock *tb;
47
    CPUState *saved_env;
48
    unsigned long pc;
49
    int ret;
50

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

    
72
#endif
73

    
74
void helper_ldtlb(void)
75
{
76
#ifdef CONFIG_USER_ONLY
77
    /* XXXXX */
78
    assert(0);
79
#else
80
    cpu_load_tlb(env);
81
#endif
82
}
83

    
84
void helper_addc_T0_T1(void)
85
{
86
    uint32_t tmp0, tmp1;
87

    
88
    tmp1 = T0 + T1;
89
    tmp0 = T1;
90
    T1 = tmp1 + (env->sr & 1);
91
    if (tmp0 > tmp1)
92
        env->sr |= SR_T;
93
    else
94
        env->sr &= ~SR_T;
95
    if (tmp1 > T1)
96
        env->sr |= SR_T;
97
}
98

    
99
void helper_addv_T0_T1(void)
100
{
101
    uint32_t dest, src, ans;
102

    
103
    if ((int32_t) T1 >= 0)
104
        dest = 0;
105
    else
106
        dest = 1;
107
    if ((int32_t) T0 >= 0)
108
        src = 0;
109
    else
110
        src = 1;
111
    src += dest;
112
    T1 += T0;
113
    if ((int32_t) T1 >= 0)
114
        ans = 0;
115
    else
116
        ans = 1;
117
    ans += dest;
118
    if (src == 0 || src == 2) {
119
        if (ans == 1)
120
            env->sr |= SR_T;
121
        else
122
            env->sr &= ~SR_T;
123
    } else
124
        env->sr &= ~SR_T;
125
}
126

    
127
#define T (env->sr & SR_T)
128
#define Q (env->sr & SR_Q ? 1 : 0)
129
#define M (env->sr & SR_M ? 1 : 0)
130
#define SETT env->sr |= SR_T
131
#define CLRT env->sr &= ~SR_T
132
#define SETQ env->sr |= SR_Q
133
#define CLRQ env->sr &= ~SR_Q
134
#define SETM env->sr |= SR_M
135
#define CLRM env->sr &= ~SR_M
136

    
137
void helper_div1_T0_T1(void)
138
{
139
    uint32_t tmp0, tmp2;
140
    uint8_t old_q, tmp1 = 0xff;
141

    
142
    //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
143
    old_q = Q;
144
    if ((0x80000000 & T1) != 0)
145
        SETQ;
146
    else
147
        CLRQ;
148
    tmp2 = T0;
149
    T1 <<= 1;
150
    T1 |= T;
151
    switch (old_q) {
152
    case 0:
153
        switch (M) {
154
        case 0:
155
            tmp0 = T1;
156
            T1 -= tmp2;
157
            tmp1 = T1 > tmp0;
158
            switch (Q) {
159
            case 0:
160
                if (tmp1)
161
                    SETQ;
162
                else
163
                    CLRQ;
164
                break;
165
            case 1:
166
                if (tmp1 == 0)
167
                    SETQ;
168
                else
169
                    CLRQ;
170
                break;
171
            }
172
            break;
173
        case 1:
174
            tmp0 = T1;
175
            T1 += tmp2;
176
            tmp1 = T1 < tmp0;
177
            switch (Q) {
178
            case 0:
179
                if (tmp1 == 0)
180
                    SETQ;
181
                else
182
                    CLRQ;
183
                break;
184
            case 1:
185
                if (tmp1)
186
                    SETQ;
187
                else
188
                    CLRQ;
189
                break;
190
            }
191
            break;
192
        }
193
        break;
194
    case 1:
195
        switch (M) {
196
        case 0:
197
            tmp0 = T1;
198
            T1 += tmp2;
199
            tmp1 = T1 < tmp0;
200
            switch (Q) {
201
            case 0:
202
                if (tmp1)
203
                    SETQ;
204
                else
205
                    CLRQ;
206
                break;
207
            case 1:
208
                if (tmp1 == 0)
209
                    SETQ;
210
                else
211
                    CLRQ;
212
                break;
213
            }
214
            break;
215
        case 1:
216
            tmp0 = T1;
217
            T1 -= tmp2;
218
            tmp1 = T1 > tmp0;
219
            switch (Q) {
220
            case 0:
221
                if (tmp1 == 0)
222
                    SETQ;
223
                else
224
                    CLRQ;
225
                break;
226
            case 1:
227
                if (tmp1)
228
                    SETQ;
229
                else
230
                    CLRQ;
231
                break;
232
            }
233
            break;
234
        }
235
        break;
236
    }
237
    if (Q == M)
238
        SETT;
239
    else
240
        CLRT;
241
    //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
242
}
243

    
244
void helper_dmulsl_T0_T1()
245
{
246
    int64_t res;
247

    
248
    res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
249
    env->mach = (res >> 32) & 0xffffffff;
250
    env->macl = res & 0xffffffff;
251
}
252

    
253
void helper_dmulul_T0_T1()
254
{
255
    uint64_t res;
256

    
257
    res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
258
    env->mach = (res >> 32) & 0xffffffff;
259
    env->macl = res & 0xffffffff;
260
}
261

    
262
void helper_macl_T0_T1()
263
{
264
    int64_t res;
265

    
266
    res = ((uint64_t) env->mach << 32) | env->macl;
267
    res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
268
    env->mach = (res >> 32) & 0xffffffff;
269
    env->macl = res & 0xffffffff;
270
    if (env->sr & SR_S) {
271
        if (res < 0)
272
            env->mach |= 0xffff0000;
273
        else
274
            env->mach &= 0x00007fff;
275
    }
276
}
277

    
278
void helper_macw_T0_T1()
279
{
280
    int64_t res;
281

    
282
    res = ((uint64_t) env->mach << 32) | env->macl;
283
    res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1;
284
    env->mach = (res >> 32) & 0xffffffff;
285
    env->macl = res & 0xffffffff;
286
    if (env->sr & SR_S) {
287
        if (res < -0x80000000) {
288
            env->mach = 1;
289
            env->macl = 0x80000000;
290
        } else if (res > 0x000000007fffffff) {
291
            env->mach = 1;
292
            env->macl = 0x7fffffff;
293
        }
294
    }
295
}
296

    
297
void helper_negc_T0()
298
{
299
    uint32_t temp;
300

    
301
    temp = -T0;
302
    T0 = temp - (env->sr & SR_T);
303
    if (0 < temp)
304
        env->sr |= SR_T;
305
    else
306
        env->sr &= ~SR_T;
307
    if (temp < T0)
308
        env->sr |= SR_T;
309
}
310

    
311
void helper_subc_T0_T1()
312
{
313
    uint32_t tmp0, tmp1;
314

    
315
    tmp1 = T1 - T0;
316
    tmp0 = T1;
317
    T1 = tmp1 - (env->sr & SR_T);
318
    if (tmp0 < tmp1)
319
        env->sr |= SR_T;
320
    else
321
        env->sr &= ~SR_T;
322
    if (tmp1 < T1)
323
        env->sr |= SR_T;
324
}
325

    
326
void helper_subv_T0_T1()
327
{
328
    int32_t dest, src, ans;
329

    
330
    if ((int32_t) T1 >= 0)
331
        dest = 0;
332
    else
333
        dest = 1;
334
    if ((int32_t) T0 >= 0)
335
        src = 0;
336
    else
337
        src = 1;
338
    src += dest;
339
    T1 -= T0;
340
    if ((int32_t) T1 >= 0)
341
        ans = 0;
342
    else
343
        ans = 1;
344
    ans += dest;
345
    if (src == 1) {
346
        if (ans == 1)
347
            env->sr |= SR_T;
348
        else
349
            env->sr &= ~SR_T;
350
    } else
351
        env->sr &= ~SR_T;
352
}
353

    
354
void helper_rotcl(uint32_t * addr)
355
{
356
    uint32_t new;
357

    
358
    new = (*addr << 1) | (env->sr & SR_T);
359
    if (*addr & 0x80000000)
360
        env->sr |= SR_T;
361
    else
362
        env->sr &= ~SR_T;
363
    *addr = new;
364
}
365

    
366
void helper_rotcr(uint32_t * addr)
367
{
368
    uint32_t new;
369

    
370
    new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
371
    if (*addr & 1)
372
        env->sr |= SR_T;
373
    else
374
        env->sr &= ~SR_T;
375
    *addr = new;
376
}