Statistics
| Branch: | Revision:

root / target-unicore32 / op_helper.c @ 5cd8f621

History | View | Annotate | Download (6.2 kB)

1
/*
2
 *  UniCore32 helper routines
3
 *
4
 * Copyright (C) 2010-2012 Guan Xuetao
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License version 2 as
8
 * published by the Free Software Foundation, or (at your option) any
9
 * later version. See the COPYING file in the top-level directory.
10
 */
11
#include "cpu.h"
12
#include "helper.h"
13

    
14
#define SIGNBIT (uint32_t)0x80000000
15
#define SIGNBIT64 ((uint64_t)1 << 63)
16

    
17
void HELPER(exception)(CPUUniCore32State *env, uint32_t excp)
18
{
19
    env->exception_index = excp;
20
    cpu_loop_exit(env);
21
}
22

    
23
static target_ulong asr_read(CPUUniCore32State *env)
24
{
25
    int ZF;
26
    ZF = (env->ZF == 0);
27
    return env->uncached_asr | (env->NF & 0x80000000) | (ZF << 30) |
28
        (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
29
}
30

    
31
target_ulong cpu_asr_read(CPUUniCore32State *env)
32
{
33
    return asr_read(env);
34
}
35

    
36
target_ulong HELPER(asr_read)(CPUUniCore32State *env)
37
{
38
    return asr_read(env);
39
}
40

    
41
static void asr_write(CPUUniCore32State *env, target_ulong val,
42
                      target_ulong mask)
43
{
44
    if (mask & ASR_NZCV) {
45
        env->ZF = (~val) & ASR_Z;
46
        env->NF = val;
47
        env->CF = (val >> 29) & 1;
48
        env->VF = (val << 3) & 0x80000000;
49
    }
50

    
51
    if ((env->uncached_asr ^ val) & mask & ASR_M) {
52
        switch_mode(env, val & ASR_M);
53
    }
54
    mask &= ~ASR_NZCV;
55
    env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
56
}
57

    
58
void cpu_asr_write(CPUUniCore32State *env, target_ulong val, target_ulong mask)
59
{
60
    asr_write(env, val, mask);
61
}
62

    
63
void HELPER(asr_write)(CPUUniCore32State *env, target_ulong val,
64
                       target_ulong mask)
65
{
66
    asr_write(env, val, mask);
67
}
68

    
69
/* Access to user mode registers from privileged modes.  */
70
uint32_t HELPER(get_user_reg)(CPUUniCore32State *env, uint32_t regno)
71
{
72
    uint32_t val;
73

    
74
    if (regno == 29) {
75
        val = env->banked_r29[0];
76
    } else if (regno == 30) {
77
        val = env->banked_r30[0];
78
    } else {
79
        val = env->regs[regno];
80
    }
81
    return val;
82
}
83

    
84
void HELPER(set_user_reg)(CPUUniCore32State *env, uint32_t regno, uint32_t val)
85
{
86
    if (regno == 29) {
87
        env->banked_r29[0] = val;
88
    } else if (regno == 30) {
89
        env->banked_r30[0] = val;
90
    } else {
91
        env->regs[regno] = val;
92
    }
93
}
94

    
95
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
96
   The only way to do that in TCG is a conditional branch, which clobbers
97
   all our temporaries.  For now implement these as helper functions.  */
98

    
99
uint32_t HELPER(add_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
100
{
101
    uint32_t result;
102
    result = a + b;
103
    env->NF = env->ZF = result;
104
    env->CF = result < a;
105
    env->VF = (a ^ b ^ -1) & (a ^ result);
106
    return result;
107
}
108

    
109
uint32_t HELPER(adc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
110
{
111
    uint32_t result;
112
    if (!env->CF) {
113
        result = a + b;
114
        env->CF = result < a;
115
    } else {
116
        result = a + b + 1;
117
        env->CF = result <= a;
118
    }
119
    env->VF = (a ^ b ^ -1) & (a ^ result);
120
    env->NF = env->ZF = result;
121
    return result;
122
}
123

    
124
uint32_t HELPER(sub_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
125
{
126
    uint32_t result;
127
    result = a - b;
128
    env->NF = env->ZF = result;
129
    env->CF = a >= b;
130
    env->VF = (a ^ b) & (a ^ result);
131
    return result;
132
}
133

    
134
uint32_t HELPER(sbc_cc)(CPUUniCore32State *env, uint32_t a, uint32_t b)
135
{
136
    uint32_t result;
137
    if (!env->CF) {
138
        result = a - b - 1;
139
        env->CF = a > b;
140
    } else {
141
        result = a - b;
142
        env->CF = a >= b;
143
    }
144
    env->VF = (a ^ b) & (a ^ result);
145
    env->NF = env->ZF = result;
146
    return result;
147
}
148

    
149
/* Similarly for variable shift instructions.  */
150

    
151
uint32_t HELPER(shl)(uint32_t x, uint32_t i)
152
{
153
    int shift = i & 0xff;
154
    if (shift >= 32) {
155
        return 0;
156
    }
157
    return x << shift;
158
}
159

    
160
uint32_t HELPER(shr)(uint32_t x, uint32_t i)
161
{
162
    int shift = i & 0xff;
163
    if (shift >= 32) {
164
        return 0;
165
    }
166
    return (uint32_t)x >> shift;
167
}
168

    
169
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
170
{
171
    int shift = i & 0xff;
172
    if (shift >= 32) {
173
        shift = 31;
174
    }
175
    return (int32_t)x >> shift;
176
}
177

    
178
uint32_t HELPER(shl_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
179
{
180
    int shift = i & 0xff;
181
    if (shift >= 32) {
182
        if (shift == 32) {
183
            env->CF = x & 1;
184
        } else {
185
            env->CF = 0;
186
        }
187
        return 0;
188
    } else if (shift != 0) {
189
        env->CF = (x >> (32 - shift)) & 1;
190
        return x << shift;
191
    }
192
    return x;
193
}
194

    
195
uint32_t HELPER(shr_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
196
{
197
    int shift = i & 0xff;
198
    if (shift >= 32) {
199
        if (shift == 32) {
200
            env->CF = (x >> 31) & 1;
201
        } else {
202
            env->CF = 0;
203
        }
204
        return 0;
205
    } else if (shift != 0) {
206
        env->CF = (x >> (shift - 1)) & 1;
207
        return x >> shift;
208
    }
209
    return x;
210
}
211

    
212
uint32_t HELPER(sar_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
213
{
214
    int shift = i & 0xff;
215
    if (shift >= 32) {
216
        env->CF = (x >> 31) & 1;
217
        return (int32_t)x >> 31;
218
    } else if (shift != 0) {
219
        env->CF = (x >> (shift - 1)) & 1;
220
        return (int32_t)x >> shift;
221
    }
222
    return x;
223
}
224

    
225
uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i)
226
{
227
    int shift1, shift;
228
    shift1 = i & 0xff;
229
    shift = shift1 & 0x1f;
230
    if (shift == 0) {
231
        if (shift1 != 0) {
232
            env->CF = (x >> 31) & 1;
233
        }
234
        return x;
235
    } else {
236
        env->CF = (x >> (shift - 1)) & 1;
237
        return ((uint32_t)x >> shift) | (x << (32 - shift));
238
    }
239
}
240

    
241
#ifndef CONFIG_USER_ONLY
242
#include "exec/softmmu_exec.h"
243

    
244
#define MMUSUFFIX _mmu
245

    
246
#define SHIFT 0
247
#include "exec/softmmu_template.h"
248

    
249
#define SHIFT 1
250
#include "exec/softmmu_template.h"
251

    
252
#define SHIFT 2
253
#include "exec/softmmu_template.h"
254

    
255
#define SHIFT 3
256
#include "exec/softmmu_template.h"
257

    
258
void tlb_fill(CPUUniCore32State *env, target_ulong addr, int is_write,
259
              int mmu_idx, uintptr_t retaddr)
260
{
261
    int ret;
262

    
263
    ret = uc32_cpu_handle_mmu_fault(env, addr, is_write, mmu_idx);
264
    if (unlikely(ret)) {
265
        if (retaddr) {
266
            /* now we have a real cpu fault */
267
            cpu_restore_state(env, retaddr);
268
        }
269
        cpu_loop_exit(env);
270
    }
271
}
272
#endif