Statistics
| Branch: | Revision:

root / target-arm / op.c @ 5e3f878a

History | View | Annotate | Download (5.8 kB)

1
/*
2
 *  ARM micro operations
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005-2007 CodeSourcery, LLC
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
#include "exec.h"
22

    
23
void OPPROTO op_addl_T0_T1_cc(void)
24
{
25
    unsigned int src1;
26
    src1 = T0;
27
    T0 += T1;
28
    env->NZF = T0;
29
    env->CF = T0 < src1;
30
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
31
}
32

    
33
void OPPROTO op_adcl_T0_T1_cc(void)
34
{
35
    unsigned int src1;
36
    src1 = T0;
37
    if (!env->CF) {
38
        T0 += T1;
39
        env->CF = T0 < src1;
40
    } else {
41
        T0 += T1 + 1;
42
        env->CF = T0 <= src1;
43
    }
44
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
45
    env->NZF = T0;
46
    FORCE_RET();
47
}
48

    
49
#define OPSUB(sub, sbc, res, T0, T1)            \
50
                                                \
51
void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
52
{                                               \
53
    unsigned int src1;                          \
54
    src1 = T0;                                  \
55
    T0 -= T1;                                   \
56
    env->NZF = T0;                              \
57
    env->CF = src1 >= T1;                       \
58
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
59
    res = T0;                                   \
60
}                                               \
61
                                                \
62
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
63
{                                               \
64
    unsigned int src1;                          \
65
    src1 = T0;                                  \
66
    if (!env->CF) {                             \
67
        T0 = T0 - T1 - 1;                       \
68
        env->CF = src1 > T1;                    \
69
    } else {                                    \
70
        T0 = T0 - T1;                           \
71
        env->CF = src1 >= T1;                   \
72
    }                                           \
73
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
74
    env->NZF = T0;                              \
75
    res = T0;                                   \
76
    FORCE_RET();                                \
77
}
78

    
79
OPSUB(sub, sbc, T0, T0, T1)
80

    
81
OPSUB(rsb, rsc, T0, T1, T0)
82

    
83
/* memory access */
84

    
85
#define MEMSUFFIX _raw
86
#include "op_mem.h"
87

    
88
#if !defined(CONFIG_USER_ONLY)
89
#define MEMSUFFIX _user
90
#include "op_mem.h"
91
#define MEMSUFFIX _kernel
92
#include "op_mem.h"
93
#endif
94

    
95
void OPPROTO op_clrex(void)
96
{
97
    cpu_lock();
98
    helper_clrex(env);
99
    cpu_unlock();
100
}
101

    
102
/* T1 based, use T0 as shift count */
103

    
104
void OPPROTO op_shll_T1_T0(void)
105
{
106
    int shift;
107
    shift = T0 & 0xff;
108
    if (shift >= 32)
109
        T1 = 0;
110
    else
111
        T1 = T1 << shift;
112
    FORCE_RET();
113
}
114

    
115
void OPPROTO op_shrl_T1_T0(void)
116
{
117
    int shift;
118
    shift = T0 & 0xff;
119
    if (shift >= 32)
120
        T1 = 0;
121
    else
122
        T1 = (uint32_t)T1 >> shift;
123
    FORCE_RET();
124
}
125

    
126
void OPPROTO op_sarl_T1_T0(void)
127
{
128
    int shift;
129
    shift = T0 & 0xff;
130
    if (shift >= 32)
131
        shift = 31;
132
    T1 = (int32_t)T1 >> shift;
133
}
134

    
135
void OPPROTO op_rorl_T1_T0(void)
136
{
137
    int shift;
138
    shift = T0 & 0x1f;
139
    if (shift) {
140
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
141
    }
142
    FORCE_RET();
143
}
144

    
145
/* T1 based, use T0 as shift count and compute CF */
146

    
147
void OPPROTO op_shll_T1_T0_cc(void)
148
{
149
    int shift;
150
    shift = T0 & 0xff;
151
    if (shift >= 32) {
152
        if (shift == 32)
153
            env->CF = T1 & 1;
154
        else
155
            env->CF = 0;
156
        T1 = 0;
157
    } else if (shift != 0) {
158
        env->CF = (T1 >> (32 - shift)) & 1;
159
        T1 = T1 << shift;
160
    }
161
    FORCE_RET();
162
}
163

    
164
void OPPROTO op_shrl_T1_T0_cc(void)
165
{
166
    int shift;
167
    shift = T0 & 0xff;
168
    if (shift >= 32) {
169
        if (shift == 32)
170
            env->CF = (T1 >> 31) & 1;
171
        else
172
            env->CF = 0;
173
        T1 = 0;
174
    } else if (shift != 0) {
175
        env->CF = (T1 >> (shift - 1)) & 1;
176
        T1 = (uint32_t)T1 >> shift;
177
    }
178
    FORCE_RET();
179
}
180

    
181
void OPPROTO op_sarl_T1_T0_cc(void)
182
{
183
    int shift;
184
    shift = T0 & 0xff;
185
    if (shift >= 32) {
186
        env->CF = (T1 >> 31) & 1;
187
        T1 = (int32_t)T1 >> 31;
188
    } else if (shift != 0) {
189
        env->CF = (T1 >> (shift - 1)) & 1;
190
        T1 = (int32_t)T1 >> shift;
191
    }
192
    FORCE_RET();
193
}
194

    
195
void OPPROTO op_rorl_T1_T0_cc(void)
196
{
197
    int shift1, shift;
198
    shift1 = T0 & 0xff;
199
    shift = shift1 & 0x1f;
200
    if (shift == 0) {
201
        if (shift1 != 0)
202
            env->CF = (T1 >> 31) & 1;
203
    } else {
204
        env->CF = (T1 >> (shift - 1)) & 1;
205
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
206
    }
207
    FORCE_RET();
208
}
209

    
210
void OPPROTO op_movl_cp_T0(void)
211
{
212
    helper_set_cp(env, PARAM1, T0);
213
    FORCE_RET();
214
}
215

    
216
void OPPROTO op_movl_T0_cp(void)
217
{
218
    T0 = helper_get_cp(env, PARAM1);
219
    FORCE_RET();
220
}
221

    
222
void OPPROTO op_movl_cp15_T0(void)
223
{
224
    helper_set_cp15(env, PARAM1, T0);
225
    FORCE_RET();
226
}
227

    
228
void OPPROTO op_movl_T0_cp15(void)
229
{
230
    T0 = helper_get_cp15(env, PARAM1);
231
    FORCE_RET();
232
}
233

    
234
void OPPROTO op_v7m_mrs_T0(void)
235
{
236
    T0 = helper_v7m_mrs(env, PARAM1);
237
}
238

    
239
void OPPROTO op_v7m_msr_T0(void)
240
{
241
    helper_v7m_msr(env, PARAM1, T0);
242
}
243

    
244
void OPPROTO op_movl_T0_sp(void)
245
{
246
    if (PARAM1 == env->v7m.current_sp)
247
        T0 = env->regs[13];
248
    else
249
        T0 = env->v7m.other_sp;
250
    FORCE_RET();
251
}
252

    
253
#include "op_neon.h"
254

    
255
/* iwMMXt support */
256
#include "op_iwmmxt.c"