Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ ea2b542a

History | View | Annotate | Download (6.7 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_ldtlb(void)
80
{
81
#ifdef CONFIG_USER_ONLY
82
    /* XXXXX */
83
    assert(0);
84
#else
85
    cpu_load_tlb(env);
86
#endif
87
}
88

    
89
void helper_addc_T0_T1(void)
90
{
91
    uint32_t tmp0, tmp1;
92

    
93
    tmp1 = T0 + T1;
94
    tmp0 = T1;
95
    T1 = tmp1 + (env->sr & 1);
96
    if (tmp0 > tmp1)
97
        env->sr |= SR_T;
98
    else
99
        env->sr &= ~SR_T;
100
    if (tmp1 > T1)
101
        env->sr |= SR_T;
102
}
103

    
104
void helper_addv_T0_T1(void)
105
{
106
    uint32_t dest, src, ans;
107

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

    
132
#define T (env->sr & SR_T)
133
#define Q (env->sr & SR_Q ? 1 : 0)
134
#define M (env->sr & SR_M ? 1 : 0)
135
#define SETT env->sr |= SR_T
136
#define CLRT env->sr &= ~SR_T
137
#define SETQ env->sr |= SR_Q
138
#define CLRQ env->sr &= ~SR_Q
139
#define SETM env->sr |= SR_M
140
#define CLRM env->sr &= ~SR_M
141

    
142
void helper_div1_T0_T1(void)
143
{
144
    uint32_t tmp0, tmp2;
145
    uint8_t old_q, tmp1 = 0xff;
146

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

    
249
void helper_dmulsl_T0_T1()
250
{
251
    int64_t res;
252

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

    
258
void helper_dmulul_T0_T1()
259
{
260
    uint64_t res;
261

    
262
    res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
263
    env->mach = (res >> 32) & 0xffffffff;
264
    env->macl = res & 0xffffffff;
265
}
266

    
267
void helper_macl_T0_T1()
268
{
269
    int64_t res;
270

    
271
    res = ((uint64_t) env->mach << 32) | env->macl;
272
    res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
273
    env->mach = (res >> 32) & 0xffffffff;
274
    env->macl = res & 0xffffffff;
275
    if (env->sr & SR_S) {
276
        if (res < 0)
277
            env->mach |= 0xffff0000;
278
        else
279
            env->mach &= 0x00007fff;
280
    }
281
}
282

    
283
void helper_macw_T0_T1()
284
{
285
    int64_t res;
286

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

    
302
void helper_negc_T0()
303
{
304
    uint32_t temp;
305

    
306
    temp = -T0;
307
    T0 = temp - (env->sr & SR_T);
308
    if (0 < temp)
309
        env->sr |= SR_T;
310
    else
311
        env->sr &= ~SR_T;
312
    if (temp < T0)
313
        env->sr |= SR_T;
314
}
315

    
316
void helper_subc_T0_T1()
317
{
318
    uint32_t tmp0, tmp1;
319

    
320
    tmp1 = T1 - T0;
321
    tmp0 = T1;
322
    T1 = tmp1 - (env->sr & SR_T);
323
    if (tmp0 < tmp1)
324
        env->sr |= SR_T;
325
    else
326
        env->sr &= ~SR_T;
327
    if (tmp1 < T1)
328
        env->sr |= SR_T;
329
}
330

    
331
void helper_subv_T0_T1()
332
{
333
    int32_t dest, src, ans;
334

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

    
359
void helper_rotcl(uint32_t * addr)
360
{
361
    uint32_t new;
362

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

    
371
void helper_rotcr(uint32_t * addr)
372
{
373
    uint32_t new;
374

    
375
    new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
376
    if (*addr & 1)
377
        env->sr |= SR_T;
378
    else
379
        env->sr &= ~SR_T;
380
    *addr = new;
381
}