Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ fdf9b3e8

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 cpu_loop_exit(void)
24
{
25
    longjmp(env->jmp_env, 1);
26
}
27

    
28
void do_raise_exception(void)
29
{
30
    cpu_loop_exit();
31
}
32

    
33
#ifndef CONFIG_USER_ONLY
34

    
35
#define MMUSUFFIX _mmu
36
#define GETPC() (__builtin_return_address(0))
37

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

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

    
44
#define SHIFT 2
45
#include "softmmu_template.h"
46

    
47
#define SHIFT 3
48
#include "softmmu_template.h"
49

    
50
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
51
{
52
    TranslationBlock *tb;
53
    CPUState *saved_env;
54
    unsigned long pc;
55
    int ret;
56

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

    
78
#endif
79

    
80
void helper_addc_T0_T1(void)
81
{
82
    uint32_t tmp0, tmp1;
83

    
84
    tmp1 = T0 + T1;
85
    tmp0 = T1;
86
    T1 = tmp1 + (env->sr & 1);
87
    if (tmp0 > tmp1)
88
        env->sr |= SR_T;
89
    else
90
        env->sr &= ~SR_T;
91
    if (tmp1 > T1)
92
        env->sr |= SR_T;
93
}
94

    
95
void helper_addv_T0_T1(void)
96
{
97
    uint32_t dest, src, ans;
98

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

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

    
133
void helper_div1_T0_T1(void)
134
{
135
    uint32_t tmp0, tmp2;
136
    uint8_t old_q, tmp1 = 0xff;
137

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

    
240
void helper_dmulsl_T0_T1()
241
{
242
    int64_t res;
243

    
244
    res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
245
    env->mach = (res >> 32) & 0xffffffff;
246
    env->macl = res & 0xffffffff;
247
}
248

    
249
void helper_dmulul_T0_T1()
250
{
251
    uint64_t res;
252

    
253
    res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
254
    env->mach = (res >> 32) & 0xffffffff;
255
    env->macl = res & 0xffffffff;
256
}
257

    
258
void helper_macl_T0_T1()
259
{
260
    int64_t res;
261

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

    
274
void helper_macw_T0_T1()
275
{
276
    int64_t res;
277

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

    
293
void helper_negc_T0()
294
{
295
    uint32_t temp;
296

    
297
    temp = -T0;
298
    T0 = temp - (env->sr & SR_T);
299
    if (0 < temp)
300
        env->sr |= SR_T;
301
    else
302
        env->sr &= ~SR_T;
303
    if (temp < T0)
304
        env->sr |= SR_T;
305
}
306

    
307
void helper_subc_T0_T1()
308
{
309
    uint32_t tmp0, tmp1;
310

    
311
    tmp1 = T1 - T0;
312
    tmp0 = T1;
313
    T1 = tmp1 - (env->sr & SR_T);
314
    if (tmp0 < tmp1)
315
        env->sr |= SR_T;
316
    else
317
        env->sr &= ~SR_T;
318
    if (tmp1 < T1)
319
        env->sr |= SR_T;
320
}
321

    
322
void helper_subv_T0_T1()
323
{
324
    int32_t dest, src, ans;
325

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

    
350
void helper_rotcl(uint32_t * addr)
351
{
352
    uint32_t new;
353

    
354
    new = (*addr << 1) | (env->sr & SR_T);
355
    if (*addr & 0x80000000)
356
        env->sr |= SR_T;
357
    else
358
        env->sr &= ~SR_T;
359
    *addr = new;
360
}
361

    
362
void helper_rotcr(uint32_t * addr)
363
{
364
    uint32_t new;
365

    
366
    new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
367
    if (*addr & 1)
368
        env->sr |= SR_T;
369
    else
370
        env->sr &= ~SR_T;
371
    *addr = new;
372
}