Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ 273af660

History | View | Annotate | Download (6.6 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
#ifdef __s390__
32
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
33
#else
34
# define GETPC() (__builtin_return_address(0))
35
#endif
36

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

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

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

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

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

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

    
77
#endif
78

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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