Statistics
| Branch: | Revision:

root / target-sh4 / op_helper.c @ e6afc2f4

History | View | Annotate | Download (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
#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
void helper_addc_T0_T1(void)
112
{
113
    uint32_t tmp0, tmp1;
114

    
115
    tmp1 = T0 + T1;
116
    tmp0 = T1;
117
    T1 = tmp1 + (env->sr & 1);
118
    if (tmp0 > tmp1)
119
        env->sr |= SR_T;
120
    else
121
        env->sr &= ~SR_T;
122
    if (tmp1 > T1)
123
        env->sr |= SR_T;
124
}
125

    
126
void helper_addv_T0_T1(void)
127
{
128
    uint32_t dest, src, ans;
129

    
130
    if ((int32_t) T1 >= 0)
131
        dest = 0;
132
    else
133
        dest = 1;
134
    if ((int32_t) T0 >= 0)
135
        src = 0;
136
    else
137
        src = 1;
138
    src += dest;
139
    T1 += T0;
140
    if ((int32_t) T1 >= 0)
141
        ans = 0;
142
    else
143
        ans = 1;
144
    ans += dest;
145
    if (src == 0 || src == 2) {
146
        if (ans == 1)
147
            env->sr |= SR_T;
148
        else
149
            env->sr &= ~SR_T;
150
    } else
151
        env->sr &= ~SR_T;
152
}
153

    
154
#define T (env->sr & SR_T)
155
#define Q (env->sr & SR_Q ? 1 : 0)
156
#define M (env->sr & SR_M ? 1 : 0)
157
#define SETT env->sr |= SR_T
158
#define CLRT env->sr &= ~SR_T
159
#define SETQ env->sr |= SR_Q
160
#define CLRQ env->sr &= ~SR_Q
161
#define SETM env->sr |= SR_M
162
#define CLRM env->sr &= ~SR_M
163

    
164
void helper_div1_T0_T1(void)
165
{
166
    uint32_t tmp0, tmp2;
167
    uint8_t old_q, tmp1 = 0xff;
168

    
169
    //printf("div1 T0=0x%08x T1=0x%08x M=%d Q=%d T=%d\n", T0, T1, M, Q, T);
170
    old_q = Q;
171
    if ((0x80000000 & T1) != 0)
172
        SETQ;
173
    else
174
        CLRQ;
175
    tmp2 = T0;
176
    T1 <<= 1;
177
    T1 |= T;
178
    switch (old_q) {
179
    case 0:
180
        switch (M) {
181
        case 0:
182
            tmp0 = T1;
183
            T1 -= tmp2;
184
            tmp1 = T1 > tmp0;
185
            switch (Q) {
186
            case 0:
187
                if (tmp1)
188
                    SETQ;
189
                else
190
                    CLRQ;
191
                break;
192
            case 1:
193
                if (tmp1 == 0)
194
                    SETQ;
195
                else
196
                    CLRQ;
197
                break;
198
            }
199
            break;
200
        case 1:
201
            tmp0 = T1;
202
            T1 += tmp2;
203
            tmp1 = T1 < tmp0;
204
            switch (Q) {
205
            case 0:
206
                if (tmp1 == 0)
207
                    SETQ;
208
                else
209
                    CLRQ;
210
                break;
211
            case 1:
212
                if (tmp1)
213
                    SETQ;
214
                else
215
                    CLRQ;
216
                break;
217
            }
218
            break;
219
        }
220
        break;
221
    case 1:
222
        switch (M) {
223
        case 0:
224
            tmp0 = T1;
225
            T1 += tmp2;
226
            tmp1 = T1 < tmp0;
227
            switch (Q) {
228
            case 0:
229
                if (tmp1)
230
                    SETQ;
231
                else
232
                    CLRQ;
233
                break;
234
            case 1:
235
                if (tmp1 == 0)
236
                    SETQ;
237
                else
238
                    CLRQ;
239
                break;
240
            }
241
            break;
242
        case 1:
243
            tmp0 = T1;
244
            T1 -= tmp2;
245
            tmp1 = T1 > tmp0;
246
            switch (Q) {
247
            case 0:
248
                if (tmp1 == 0)
249
                    SETQ;
250
                else
251
                    CLRQ;
252
                break;
253
            case 1:
254
                if (tmp1)
255
                    SETQ;
256
                else
257
                    CLRQ;
258
                break;
259
            }
260
            break;
261
        }
262
        break;
263
    }
264
    if (Q == M)
265
        SETT;
266
    else
267
        CLRT;
268
    //printf("Output: T1=0x%08x M=%d Q=%d T=%d\n", T1, M, Q, T);
269
}
270

    
271
void helper_dmulsl_T0_T1()
272
{
273
    int64_t res;
274

    
275
    res = (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
276
    env->mach = (res >> 32) & 0xffffffff;
277
    env->macl = res & 0xffffffff;
278
}
279

    
280
void helper_dmulul_T0_T1()
281
{
282
    uint64_t res;
283

    
284
    res = (uint64_t) (uint32_t) T0 *(uint64_t) (uint32_t) T1;
285
    env->mach = (res >> 32) & 0xffffffff;
286
    env->macl = res & 0xffffffff;
287
}
288

    
289
void helper_macl_T0_T1()
290
{
291
    int64_t res;
292

    
293
    res = ((uint64_t) env->mach << 32) | env->macl;
294
    res += (int64_t) (int32_t) T0 *(int64_t) (int32_t) T1;
295
    env->mach = (res >> 32) & 0xffffffff;
296
    env->macl = res & 0xffffffff;
297
    if (env->sr & SR_S) {
298
        if (res < 0)
299
            env->mach |= 0xffff0000;
300
        else
301
            env->mach &= 0x00007fff;
302
    }
303
}
304

    
305
void helper_macw_T0_T1()
306
{
307
    int64_t res;
308

    
309
    res = ((uint64_t) env->mach << 32) | env->macl;
310
    res += (int64_t) (int16_t) T0 *(int64_t) (int16_t) T1;
311
    env->mach = (res >> 32) & 0xffffffff;
312
    env->macl = res & 0xffffffff;
313
    if (env->sr & SR_S) {
314
        if (res < -0x80000000) {
315
            env->mach = 1;
316
            env->macl = 0x80000000;
317
        } else if (res > 0x000000007fffffff) {
318
            env->mach = 1;
319
            env->macl = 0x7fffffff;
320
        }
321
    }
322
}
323

    
324
void helper_negc_T0()
325
{
326
    uint32_t temp;
327

    
328
    temp = -T0;
329
    T0 = temp - (env->sr & SR_T);
330
    if (0 < temp)
331
        env->sr |= SR_T;
332
    else
333
        env->sr &= ~SR_T;
334
    if (temp < T0)
335
        env->sr |= SR_T;
336
}
337

    
338
void helper_subc_T0_T1()
339
{
340
    uint32_t tmp0, tmp1;
341

    
342
    tmp1 = T1 - T0;
343
    tmp0 = T1;
344
    T1 = tmp1 - (env->sr & SR_T);
345
    if (tmp0 < tmp1)
346
        env->sr |= SR_T;
347
    else
348
        env->sr &= ~SR_T;
349
    if (tmp1 < T1)
350
        env->sr |= SR_T;
351
}
352

    
353
void helper_subv_T0_T1()
354
{
355
    int32_t dest, src, ans;
356

    
357
    if ((int32_t) T1 >= 0)
358
        dest = 0;
359
    else
360
        dest = 1;
361
    if ((int32_t) T0 >= 0)
362
        src = 0;
363
    else
364
        src = 1;
365
    src += dest;
366
    T1 -= T0;
367
    if ((int32_t) T1 >= 0)
368
        ans = 0;
369
    else
370
        ans = 1;
371
    ans += dest;
372
    if (src == 1) {
373
        if (ans == 1)
374
            env->sr |= SR_T;
375
        else
376
            env->sr &= ~SR_T;
377
    } else
378
        env->sr &= ~SR_T;
379
}
380

    
381
void helper_rotcl(uint32_t * addr)
382
{
383
    uint32_t new;
384

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

    
393
void helper_rotcr(uint32_t * addr)
394
{
395
    uint32_t new;
396

    
397
    new = (*addr >> 1) | ((env->sr & SR_T) ? 0x80000000 : 0);
398
    if (*addr & 1)
399
        env->sr |= SR_T;
400
    else
401
        env->sr &= ~SR_T;
402
    *addr = new;
403
}