Statistics
| Branch: | Revision:

root / target-unicore32 / op_helper.c @ a15bb0d6

History | View | Annotate | Download (5.2 kB)

1
/*
2
 *  UniCore32 helper routines
3
 *
4
 * Copyright (C) 2010-2011 GUAN Xue-tao
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.
9
 */
10
#include "exec.h"
11
#include "helper.h"
12

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

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

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

    
30
target_ulong cpu_asr_read(CPUState *env1)
31
{
32
    CPUState *saved_env;
33
    target_ulong ret;
34

    
35
    saved_env = env;
36
    env = env1;
37
    ret = asr_read();
38
    env = saved_env;
39
    return ret;
40
}
41

    
42
target_ulong HELPER(asr_read)(void)
43
{
44
    return asr_read();
45
}
46

    
47
static void asr_write(target_ulong val, target_ulong mask)
48
{
49
    if (mask & ASR_NZCV) {
50
        env->ZF = (~val) & ASR_Z;
51
        env->NF = val;
52
        env->CF = (val >> 29) & 1;
53
        env->VF = (val << 3) & 0x80000000;
54
    }
55

    
56
    if ((env->uncached_asr ^ val) & mask & ASR_M) {
57
        switch_mode(env, val & ASR_M);
58
    }
59
    mask &= ~ASR_NZCV;
60
    env->uncached_asr = (env->uncached_asr & ~mask) | (val & mask);
61
}
62

    
63
void cpu_asr_write(CPUState *env1, target_ulong val, target_ulong mask)
64
{
65
    CPUState *saved_env;
66

    
67
    saved_env = env;
68
    env = env1;
69
    asr_write(val, mask);
70
    env = saved_env;
71
}
72

    
73
void HELPER(asr_write)(target_ulong val, target_ulong mask)
74
{
75
    asr_write(val, mask);
76
}
77

    
78
/* Access to user mode registers from privileged modes.  */
79
uint32_t HELPER(get_user_reg)(uint32_t regno)
80
{
81
    uint32_t val;
82

    
83
    if (regno == 29) {
84
        val = env->banked_r29[0];
85
    } else if (regno == 30) {
86
        val = env->banked_r30[0];
87
    } else {
88
        val = env->regs[regno];
89
    }
90
    return val;
91
}
92

    
93
void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
94
{
95
    if (regno == 29) {
96
        env->banked_r29[0] = val;
97
    } else if (regno == 30) {
98
        env->banked_r30[0] = val;
99
    } else {
100
        env->regs[regno] = val;
101
    }
102
}
103

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

    
108
uint32_t HELPER(add_cc)(uint32_t a, uint32_t b)
109
{
110
    uint32_t result;
111
    result = a + b;
112
    env->NF = env->ZF = result;
113
    env->CF = result < a;
114
    env->VF = (a ^ b ^ -1) & (a ^ result);
115
    return result;
116
}
117

    
118
uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
119
{
120
    uint32_t result;
121
    if (!env->CF) {
122
        result = a + b;
123
        env->CF = result < a;
124
    } else {
125
        result = a + b + 1;
126
        env->CF = result <= a;
127
    }
128
    env->VF = (a ^ b ^ -1) & (a ^ result);
129
    env->NF = env->ZF = result;
130
    return result;
131
}
132

    
133
uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
134
{
135
    uint32_t result;
136
    result = a - b;
137
    env->NF = env->ZF = result;
138
    env->CF = a >= b;
139
    env->VF = (a ^ b) & (a ^ result);
140
    return result;
141
}
142

    
143
uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
144
{
145
    uint32_t result;
146
    if (!env->CF) {
147
        result = a - b - 1;
148
        env->CF = a > b;
149
    } else {
150
        result = a - b;
151
        env->CF = a >= b;
152
    }
153
    env->VF = (a ^ b) & (a ^ result);
154
    env->NF = env->ZF = result;
155
    return result;
156
}
157

    
158
/* Similarly for variable shift instructions.  */
159

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

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

    
178
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
179
{
180
    int shift = i & 0xff;
181
    if (shift >= 32) {
182
        shift = 31;
183
    }
184
    return (int32_t)x >> shift;
185
}
186

    
187
uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
188
{
189
    int shift = i & 0xff;
190
    if (shift >= 32) {
191
        if (shift == 32) {
192
            env->CF = x & 1;
193
        } else {
194
            env->CF = 0;
195
        }
196
        return 0;
197
    } else if (shift != 0) {
198
        env->CF = (x >> (32 - shift)) & 1;
199
        return x << shift;
200
    }
201
    return x;
202
}
203

    
204
uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
205
{
206
    int shift = i & 0xff;
207
    if (shift >= 32) {
208
        if (shift == 32) {
209
            env->CF = (x >> 31) & 1;
210
        } else {
211
            env->CF = 0;
212
        }
213
        return 0;
214
    } else if (shift != 0) {
215
        env->CF = (x >> (shift - 1)) & 1;
216
        return x >> shift;
217
    }
218
    return x;
219
}
220

    
221
uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
222
{
223
    int shift = i & 0xff;
224
    if (shift >= 32) {
225
        env->CF = (x >> 31) & 1;
226
        return (int32_t)x >> 31;
227
    } else if (shift != 0) {
228
        env->CF = (x >> (shift - 1)) & 1;
229
        return (int32_t)x >> shift;
230
    }
231
    return x;
232
}
233

    
234
uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
235
{
236
    int shift1, shift;
237
    shift1 = i & 0xff;
238
    shift = shift1 & 0x1f;
239
    if (shift == 0) {
240
        if (shift1 != 0) {
241
            env->CF = (x >> 31) & 1;
242
        }
243
        return x;
244
    } else {
245
        env->CF = (x >> (shift - 1)) & 1;
246
        return ((uint32_t)x >> shift) | (x << (32 - shift));
247
    }
248
}