Statistics
| Branch: | Revision:

root / target-arm / op.c @ 4373f3ce

History | View | Annotate | Download (6.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
void OPPROTO op_addq_T0_T1(void)
84
{
85
    uint64_t res;
86
    res = ((uint64_t)T1 << 32) | T0;
87
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
88
    T1 = res >> 32;
89
    T0 = res;
90
}
91

    
92
void OPPROTO op_addq_lo_T0_T1(void)
93
{
94
    uint64_t res;
95
    res = ((uint64_t)T1 << 32) | T0;
96
    res += (uint64_t)(env->regs[PARAM1]);
97
    T1 = res >> 32;
98
    T0 = res;
99
}
100

    
101
/* Dual 16-bit accumulate.  */
102
void OPPROTO op_addq_T0_T1_dual(void)
103
{
104
  uint64_t res;
105
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
106
  res += (int32_t)T0;
107
  res += (int32_t)T1;
108
  env->regs[PARAM1] = (uint32_t)res;
109
  env->regs[PARAM2] = res >> 32;
110
}
111

    
112
/* Dual 16-bit subtract accumulate.  */
113
void OPPROTO op_subq_T0_T1_dual(void)
114
{
115
  uint64_t res;
116
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
117
  res += (int32_t)T0;
118
  res -= (int32_t)T1;
119
  env->regs[PARAM1] = (uint32_t)res;
120
  env->regs[PARAM2] = res >> 32;
121
}
122

    
123
void OPPROTO op_logicq_cc(void)
124
{
125
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
126
}
127

    
128
/* memory access */
129

    
130
#define MEMSUFFIX _raw
131
#include "op_mem.h"
132

    
133
#if !defined(CONFIG_USER_ONLY)
134
#define MEMSUFFIX _user
135
#include "op_mem.h"
136
#define MEMSUFFIX _kernel
137
#include "op_mem.h"
138
#endif
139

    
140
void OPPROTO op_clrex(void)
141
{
142
    cpu_lock();
143
    helper_clrex(env);
144
    cpu_unlock();
145
}
146

    
147
/* T1 based, use T0 as shift count */
148

    
149
void OPPROTO op_shll_T1_T0(void)
150
{
151
    int shift;
152
    shift = T0 & 0xff;
153
    if (shift >= 32)
154
        T1 = 0;
155
    else
156
        T1 = T1 << shift;
157
    FORCE_RET();
158
}
159

    
160
void OPPROTO op_shrl_T1_T0(void)
161
{
162
    int shift;
163
    shift = T0 & 0xff;
164
    if (shift >= 32)
165
        T1 = 0;
166
    else
167
        T1 = (uint32_t)T1 >> shift;
168
    FORCE_RET();
169
}
170

    
171
void OPPROTO op_sarl_T1_T0(void)
172
{
173
    int shift;
174
    shift = T0 & 0xff;
175
    if (shift >= 32)
176
        shift = 31;
177
    T1 = (int32_t)T1 >> shift;
178
}
179

    
180
void OPPROTO op_rorl_T1_T0(void)
181
{
182
    int shift;
183
    shift = T0 & 0x1f;
184
    if (shift) {
185
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
186
    }
187
    FORCE_RET();
188
}
189

    
190
/* T1 based, use T0 as shift count and compute CF */
191

    
192
void OPPROTO op_shll_T1_T0_cc(void)
193
{
194
    int shift;
195
    shift = T0 & 0xff;
196
    if (shift >= 32) {
197
        if (shift == 32)
198
            env->CF = T1 & 1;
199
        else
200
            env->CF = 0;
201
        T1 = 0;
202
    } else if (shift != 0) {
203
        env->CF = (T1 >> (32 - shift)) & 1;
204
        T1 = T1 << shift;
205
    }
206
    FORCE_RET();
207
}
208

    
209
void OPPROTO op_shrl_T1_T0_cc(void)
210
{
211
    int shift;
212
    shift = T0 & 0xff;
213
    if (shift >= 32) {
214
        if (shift == 32)
215
            env->CF = (T1 >> 31) & 1;
216
        else
217
            env->CF = 0;
218
        T1 = 0;
219
    } else if (shift != 0) {
220
        env->CF = (T1 >> (shift - 1)) & 1;
221
        T1 = (uint32_t)T1 >> shift;
222
    }
223
    FORCE_RET();
224
}
225

    
226
void OPPROTO op_sarl_T1_T0_cc(void)
227
{
228
    int shift;
229
    shift = T0 & 0xff;
230
    if (shift >= 32) {
231
        env->CF = (T1 >> 31) & 1;
232
        T1 = (int32_t)T1 >> 31;
233
    } else if (shift != 0) {
234
        env->CF = (T1 >> (shift - 1)) & 1;
235
        T1 = (int32_t)T1 >> shift;
236
    }
237
    FORCE_RET();
238
}
239

    
240
void OPPROTO op_rorl_T1_T0_cc(void)
241
{
242
    int shift1, shift;
243
    shift1 = T0 & 0xff;
244
    shift = shift1 & 0x1f;
245
    if (shift == 0) {
246
        if (shift1 != 0)
247
            env->CF = (T1 >> 31) & 1;
248
    } else {
249
        env->CF = (T1 >> (shift - 1)) & 1;
250
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
251
    }
252
    FORCE_RET();
253
}
254

    
255
void OPPROTO op_movl_cp_T0(void)
256
{
257
    helper_set_cp(env, PARAM1, T0);
258
    FORCE_RET();
259
}
260

    
261
void OPPROTO op_movl_T0_cp(void)
262
{
263
    T0 = helper_get_cp(env, PARAM1);
264
    FORCE_RET();
265
}
266

    
267
void OPPROTO op_movl_cp15_T0(void)
268
{
269
    helper_set_cp15(env, PARAM1, T0);
270
    FORCE_RET();
271
}
272

    
273
void OPPROTO op_movl_T0_cp15(void)
274
{
275
    T0 = helper_get_cp15(env, PARAM1);
276
    FORCE_RET();
277
}
278

    
279
void OPPROTO op_v7m_mrs_T0(void)
280
{
281
    T0 = helper_v7m_mrs(env, PARAM1);
282
}
283

    
284
void OPPROTO op_v7m_msr_T0(void)
285
{
286
    helper_v7m_msr(env, PARAM1, T0);
287
}
288

    
289
void OPPROTO op_movl_T0_sp(void)
290
{
291
    if (PARAM1 == env->v7m.current_sp)
292
        T0 = env->regs[13];
293
    else
294
        T0 = env->v7m.other_sp;
295
    FORCE_RET();
296
}
297

    
298
#include "op_neon.h"
299

    
300
/* iwMMXt support */
301
#include "op_iwmmxt.c"