Statistics
| Branch: | Revision:

root / target-arm / op.c @ 6ddbc6e4

History | View | Annotate | Download (16.4 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
#define EIP (env->regs[15])
84

    
85
void OPPROTO op_test_eq(void)
86
{
87
    if (env->NZF == 0)
88
        GOTO_LABEL_PARAM(1);;
89
    FORCE_RET();
90
}
91

    
92
void OPPROTO op_test_ne(void)
93
{
94
    if (env->NZF != 0)
95
        GOTO_LABEL_PARAM(1);;
96
    FORCE_RET();
97
}
98

    
99
void OPPROTO op_test_cs(void)
100
{
101
    if (env->CF != 0)
102
        GOTO_LABEL_PARAM(1);
103
    FORCE_RET();
104
}
105

    
106
void OPPROTO op_test_cc(void)
107
{
108
    if (env->CF == 0)
109
        GOTO_LABEL_PARAM(1);
110
    FORCE_RET();
111
}
112

    
113
void OPPROTO op_test_mi(void)
114
{
115
    if ((env->NZF & 0x80000000) != 0)
116
        GOTO_LABEL_PARAM(1);
117
    FORCE_RET();
118
}
119

    
120
void OPPROTO op_test_pl(void)
121
{
122
    if ((env->NZF & 0x80000000) == 0)
123
        GOTO_LABEL_PARAM(1);
124
    FORCE_RET();
125
}
126

    
127
void OPPROTO op_test_vs(void)
128
{
129
    if ((env->VF & 0x80000000) != 0)
130
        GOTO_LABEL_PARAM(1);
131
    FORCE_RET();
132
}
133

    
134
void OPPROTO op_test_vc(void)
135
{
136
    if ((env->VF & 0x80000000) == 0)
137
        GOTO_LABEL_PARAM(1);
138
    FORCE_RET();
139
}
140

    
141
void OPPROTO op_test_hi(void)
142
{
143
    if (env->CF != 0 && env->NZF != 0)
144
        GOTO_LABEL_PARAM(1);
145
    FORCE_RET();
146
}
147

    
148
void OPPROTO op_test_ls(void)
149
{
150
    if (env->CF == 0 || env->NZF == 0)
151
        GOTO_LABEL_PARAM(1);
152
    FORCE_RET();
153
}
154

    
155
void OPPROTO op_test_ge(void)
156
{
157
    if (((env->VF ^ env->NZF) & 0x80000000) == 0)
158
        GOTO_LABEL_PARAM(1);
159
    FORCE_RET();
160
}
161

    
162
void OPPROTO op_test_lt(void)
163
{
164
    if (((env->VF ^ env->NZF) & 0x80000000) != 0)
165
        GOTO_LABEL_PARAM(1);
166
    FORCE_RET();
167
}
168

    
169
void OPPROTO op_test_gt(void)
170
{
171
    if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
172
        GOTO_LABEL_PARAM(1);
173
    FORCE_RET();
174
}
175

    
176
void OPPROTO op_test_le(void)
177
{
178
    if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
179
        GOTO_LABEL_PARAM(1);
180
    FORCE_RET();
181
}
182

    
183
void OPPROTO op_test_T0(void)
184
{
185
    if (T0)
186
        GOTO_LABEL_PARAM(1);
187
    FORCE_RET();
188
}
189
void OPPROTO op_testn_T0(void)
190
{
191
    if (!T0)
192
        GOTO_LABEL_PARAM(1);
193
    FORCE_RET();
194
}
195

    
196
void OPPROTO op_movl_T0_cpsr(void)
197
{
198
    /* Execution state bits always read as zero.  */
199
    T0 = cpsr_read(env) & ~CPSR_EXEC;
200
    FORCE_RET();
201
}
202

    
203
void OPPROTO op_movl_T0_spsr(void)
204
{
205
    T0 = env->spsr;
206
}
207

    
208
void OPPROTO op_movl_spsr_T0(void)
209
{
210
    uint32_t mask = PARAM1;
211
    env->spsr = (env->spsr & ~mask) | (T0 & mask);
212
}
213

    
214
void OPPROTO op_movl_cpsr_T0(void)
215
{
216
    cpsr_write(env, T0, PARAM1);
217
    FORCE_RET();
218
}
219

    
220
/* 48 bit signed mul, top 32 bits */
221
void OPPROTO op_imulw_T0_T1(void)
222
{
223
  uint64_t res;
224
  res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
225
  T0 = res >> 16;
226
}
227

    
228
void OPPROTO op_addq_T0_T1(void)
229
{
230
    uint64_t res;
231
    res = ((uint64_t)T1 << 32) | T0;
232
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
233
    T1 = res >> 32;
234
    T0 = res;
235
}
236

    
237
void OPPROTO op_addq_lo_T0_T1(void)
238
{
239
    uint64_t res;
240
    res = ((uint64_t)T1 << 32) | T0;
241
    res += (uint64_t)(env->regs[PARAM1]);
242
    T1 = res >> 32;
243
    T0 = res;
244
}
245

    
246
/* Dual 16-bit accumulate.  */
247
void OPPROTO op_addq_T0_T1_dual(void)
248
{
249
  uint64_t res;
250
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
251
  res += (int32_t)T0;
252
  res += (int32_t)T1;
253
  env->regs[PARAM1] = (uint32_t)res;
254
  env->regs[PARAM2] = res >> 32;
255
}
256

    
257
/* Dual 16-bit subtract accumulate.  */
258
void OPPROTO op_subq_T0_T1_dual(void)
259
{
260
  uint64_t res;
261
  res = ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
262
  res += (int32_t)T0;
263
  res -= (int32_t)T1;
264
  env->regs[PARAM1] = (uint32_t)res;
265
  env->regs[PARAM2] = res >> 32;
266
}
267

    
268
void OPPROTO op_logicq_cc(void)
269
{
270
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
271
}
272

    
273
/* memory access */
274

    
275
#define MEMSUFFIX _raw
276
#include "op_mem.h"
277

    
278
#if !defined(CONFIG_USER_ONLY)
279
#define MEMSUFFIX _user
280
#include "op_mem.h"
281
#define MEMSUFFIX _kernel
282
#include "op_mem.h"
283
#endif
284

    
285
void OPPROTO op_clrex(void)
286
{
287
    cpu_lock();
288
    helper_clrex(env);
289
    cpu_unlock();
290
}
291

    
292
/* T1 based, use T0 as shift count */
293

    
294
void OPPROTO op_shll_T1_T0(void)
295
{
296
    int shift;
297
    shift = T0 & 0xff;
298
    if (shift >= 32)
299
        T1 = 0;
300
    else
301
        T1 = T1 << shift;
302
    FORCE_RET();
303
}
304

    
305
void OPPROTO op_shrl_T1_T0(void)
306
{
307
    int shift;
308
    shift = T0 & 0xff;
309
    if (shift >= 32)
310
        T1 = 0;
311
    else
312
        T1 = (uint32_t)T1 >> shift;
313
    FORCE_RET();
314
}
315

    
316
void OPPROTO op_sarl_T1_T0(void)
317
{
318
    int shift;
319
    shift = T0 & 0xff;
320
    if (shift >= 32)
321
        shift = 31;
322
    T1 = (int32_t)T1 >> shift;
323
}
324

    
325
void OPPROTO op_rorl_T1_T0(void)
326
{
327
    int shift;
328
    shift = T0 & 0x1f;
329
    if (shift) {
330
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
331
    }
332
    FORCE_RET();
333
}
334

    
335
/* T1 based, use T0 as shift count and compute CF */
336

    
337
void OPPROTO op_shll_T1_T0_cc(void)
338
{
339
    int shift;
340
    shift = T0 & 0xff;
341
    if (shift >= 32) {
342
        if (shift == 32)
343
            env->CF = T1 & 1;
344
        else
345
            env->CF = 0;
346
        T1 = 0;
347
    } else if (shift != 0) {
348
        env->CF = (T1 >> (32 - shift)) & 1;
349
        T1 = T1 << shift;
350
    }
351
    FORCE_RET();
352
}
353

    
354
void OPPROTO op_shrl_T1_T0_cc(void)
355
{
356
    int shift;
357
    shift = T0 & 0xff;
358
    if (shift >= 32) {
359
        if (shift == 32)
360
            env->CF = (T1 >> 31) & 1;
361
        else
362
            env->CF = 0;
363
        T1 = 0;
364
    } else if (shift != 0) {
365
        env->CF = (T1 >> (shift - 1)) & 1;
366
        T1 = (uint32_t)T1 >> shift;
367
    }
368
    FORCE_RET();
369
}
370

    
371
void OPPROTO op_sarl_T1_T0_cc(void)
372
{
373
    int shift;
374
    shift = T0 & 0xff;
375
    if (shift >= 32) {
376
        env->CF = (T1 >> 31) & 1;
377
        T1 = (int32_t)T1 >> 31;
378
    } else if (shift != 0) {
379
        env->CF = (T1 >> (shift - 1)) & 1;
380
        T1 = (int32_t)T1 >> shift;
381
    }
382
    FORCE_RET();
383
}
384

    
385
void OPPROTO op_rorl_T1_T0_cc(void)
386
{
387
    int shift1, shift;
388
    shift1 = T0 & 0xff;
389
    shift = shift1 & 0x1f;
390
    if (shift == 0) {
391
        if (shift1 != 0)
392
            env->CF = (T1 >> 31) & 1;
393
    } else {
394
        env->CF = (T1 >> (shift - 1)) & 1;
395
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
396
    }
397
    FORCE_RET();
398
}
399

    
400
/* exceptions */
401

    
402
void OPPROTO op_swi(void)
403
{
404
    env->exception_index = EXCP_SWI;
405
    cpu_loop_exit();
406
}
407

    
408
void OPPROTO op_undef_insn(void)
409
{
410
    env->exception_index = EXCP_UDEF;
411
    cpu_loop_exit();
412
}
413

    
414
void OPPROTO op_debug(void)
415
{
416
    env->exception_index = EXCP_DEBUG;
417
    cpu_loop_exit();
418
}
419

    
420
void OPPROTO op_wfi(void)
421
{
422
    env->exception_index = EXCP_HLT;
423
    env->halted = 1;
424
    cpu_loop_exit();
425
}
426

    
427
void OPPROTO op_bkpt(void)
428
{
429
    env->exception_index = EXCP_BKPT;
430
    cpu_loop_exit();
431
}
432

    
433
void OPPROTO op_exception_exit(void)
434
{
435
    env->exception_index = EXCP_EXCEPTION_EXIT;
436
    cpu_loop_exit();
437
}
438

    
439
/* VFP support.  We follow the convention used for VFP instrunctions:
440
   Single precition routines have a "s" suffix, double precision a
441
   "d" suffix.  */
442

    
443
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
444

    
445
#define VFP_BINOP(name) \
446
VFP_OP(name, s)             \
447
{                           \
448
    FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
449
}                           \
450
VFP_OP(name, d)             \
451
{                           \
452
    FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
453
}
454
VFP_BINOP(add)
455
VFP_BINOP(sub)
456
VFP_BINOP(mul)
457
VFP_BINOP(div)
458
#undef VFP_BINOP
459

    
460
#define VFP_HELPER(name)  \
461
VFP_OP(name, s)           \
462
{                         \
463
    do_vfp_##name##s();    \
464
}                         \
465
VFP_OP(name, d)           \
466
{                         \
467
    do_vfp_##name##d();    \
468
}
469
VFP_HELPER(abs)
470
VFP_HELPER(sqrt)
471
VFP_HELPER(cmp)
472
VFP_HELPER(cmpe)
473
#undef VFP_HELPER
474

    
475
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
476
   without looking at the rest of the value.  */
477
VFP_OP(neg, s)
478
{
479
    FT0s = float32_chs(FT0s);
480
}
481

    
482
VFP_OP(neg, d)
483
{
484
    FT0d = float64_chs(FT0d);
485
}
486

    
487
VFP_OP(F1_ld0, s)
488
{
489
    union {
490
        uint32_t i;
491
        float32 s;
492
    } v;
493
    v.i = 0;
494
    FT1s = v.s;
495
}
496

    
497
VFP_OP(F1_ld0, d)
498
{
499
    union {
500
        uint64_t i;
501
        float64 d;
502
    } v;
503
    v.i = 0;
504
    FT1d = v.d;
505
}
506

    
507
/* Helper routines to perform bitwise copies between float and int.  */
508
static inline float32 vfp_itos(uint32_t i)
509
{
510
    union {
511
        uint32_t i;
512
        float32 s;
513
    } v;
514

    
515
    v.i = i;
516
    return v.s;
517
}
518

    
519
static inline uint32_t vfp_stoi(float32 s)
520
{
521
    union {
522
        uint32_t i;
523
        float32 s;
524
    } v;
525

    
526
    v.s = s;
527
    return v.i;
528
}
529

    
530
static inline float64 vfp_itod(uint64_t i)
531
{
532
    union {
533
        uint64_t i;
534
        float64 d;
535
    } v;
536

    
537
    v.i = i;
538
    return v.d;
539
}
540

    
541
static inline uint64_t vfp_dtoi(float64 d)
542
{
543
    union {
544
        uint64_t i;
545
        float64 d;
546
    } v;
547

    
548
    v.d = d;
549
    return v.i;
550
}
551

    
552
/* Integer to float conversion.  */
553
VFP_OP(uito, s)
554
{
555
    FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
556
}
557

    
558
VFP_OP(uito, d)
559
{
560
    FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
561
}
562

    
563
VFP_OP(sito, s)
564
{
565
    FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
566
}
567

    
568
VFP_OP(sito, d)
569
{
570
    FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
571
}
572

    
573
/* Float to integer conversion.  */
574
VFP_OP(toui, s)
575
{
576
    FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
577
}
578

    
579
VFP_OP(toui, d)
580
{
581
    FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
582
}
583

    
584
VFP_OP(tosi, s)
585
{
586
    FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
587
}
588

    
589
VFP_OP(tosi, d)
590
{
591
    FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
592
}
593

    
594
/* TODO: Set rounding mode properly.  */
595
VFP_OP(touiz, s)
596
{
597
    FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
598
}
599

    
600
VFP_OP(touiz, d)
601
{
602
    FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
603
}
604

    
605
VFP_OP(tosiz, s)
606
{
607
    FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
608
}
609

    
610
VFP_OP(tosiz, d)
611
{
612
    FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
613
}
614

    
615
/* floating point conversion */
616
VFP_OP(fcvtd, s)
617
{
618
    FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
619
}
620

    
621
VFP_OP(fcvts, d)
622
{
623
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
624
}
625

    
626
/* VFP3 fixed point conversion.  */
627
#define VFP_CONV_FIX(name, p, ftype, itype, sign) \
628
VFP_OP(name##to, p) \
629
{ \
630
    ftype tmp; \
631
    tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \
632
                                  &env->vfp.fp_status); \
633
    FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \
634
} \
635
VFP_OP(to##name, p) \
636
{ \
637
    ftype tmp; \
638
    tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \
639
    FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
640
            &env->vfp.fp_status)); \
641
}
642

    
643
VFP_CONV_FIX(sh, d, float64, int16, )
644
VFP_CONV_FIX(sl, d, float64, int32, )
645
VFP_CONV_FIX(uh, d, float64, uint16, u)
646
VFP_CONV_FIX(ul, d, float64, uint32, u)
647
VFP_CONV_FIX(sh, s, float32, int16, )
648
VFP_CONV_FIX(sl, s, float32, int32, )
649
VFP_CONV_FIX(uh, s, float32, uint16, u)
650
VFP_CONV_FIX(ul, s, float32, uint32, u)
651

    
652
/* Get and Put values from registers.  */
653
VFP_OP(getreg_F0, d)
654
{
655
  FT0d = *(float64 *)((char *) env + PARAM1);
656
}
657

    
658
VFP_OP(getreg_F0, s)
659
{
660
  FT0s = *(float32 *)((char *) env + PARAM1);
661
}
662

    
663
VFP_OP(getreg_F1, d)
664
{
665
  FT1d = *(float64 *)((char *) env + PARAM1);
666
}
667

    
668
VFP_OP(getreg_F1, s)
669
{
670
  FT1s = *(float32 *)((char *) env + PARAM1);
671
}
672

    
673
VFP_OP(setreg_F0, d)
674
{
675
  *(float64 *)((char *) env + PARAM1) = FT0d;
676
}
677

    
678
VFP_OP(setreg_F0, s)
679
{
680
  *(float32 *)((char *) env + PARAM1) = FT0s;
681
}
682

    
683
void OPPROTO op_vfp_movl_T0_fpscr(void)
684
{
685
    do_vfp_get_fpscr ();
686
}
687

    
688
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
689
{
690
    T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
691
}
692

    
693
void OPPROTO op_vfp_movl_fpscr_T0(void)
694
{
695
    do_vfp_set_fpscr();
696
}
697

    
698
void OPPROTO op_vfp_movl_T0_xreg(void)
699
{
700
    T0 = env->vfp.xregs[PARAM1];
701
}
702

    
703
void OPPROTO op_vfp_movl_xreg_T0(void)
704
{
705
    env->vfp.xregs[PARAM1] = T0;
706
}
707

    
708
/* Move between FT0s to T0  */
709
void OPPROTO op_vfp_mrs(void)
710
{
711
    T0 = vfp_stoi(FT0s);
712
}
713

    
714
void OPPROTO op_vfp_msr(void)
715
{
716
    FT0s = vfp_itos(T0);
717
}
718

    
719
/* Move between FT0d and {T0,T1} */
720
void OPPROTO op_vfp_mrrd(void)
721
{
722
    CPU_DoubleU u;
723

    
724
    u.d = FT0d;
725
    T0 = u.l.lower;
726
    T1 = u.l.upper;
727
}
728

    
729
void OPPROTO op_vfp_mdrr(void)
730
{
731
    CPU_DoubleU u;
732

    
733
    u.l.lower = T0;
734
    u.l.upper = T1;
735
    FT0d = u.d;
736
}
737

    
738
/* Load immediate.  PARAM1 is the 32 most significant bits of the value.  */
739
void OPPROTO op_vfp_fconstd(void)
740
{
741
    CPU_DoubleU u;
742
    u.l.upper = PARAM1;
743
    u.l.lower = 0;
744
    FT0d = u.d;
745
}
746

    
747
void OPPROTO op_vfp_fconsts(void)
748
{
749
    FT0s = vfp_itos(PARAM1);
750
}
751

    
752
void OPPROTO op_movl_cp_T0(void)
753
{
754
    helper_set_cp(env, PARAM1, T0);
755
    FORCE_RET();
756
}
757

    
758
void OPPROTO op_movl_T0_cp(void)
759
{
760
    T0 = helper_get_cp(env, PARAM1);
761
    FORCE_RET();
762
}
763

    
764
void OPPROTO op_movl_cp15_T0(void)
765
{
766
    helper_set_cp15(env, PARAM1, T0);
767
    FORCE_RET();
768
}
769

    
770
void OPPROTO op_movl_T0_cp15(void)
771
{
772
    T0 = helper_get_cp15(env, PARAM1);
773
    FORCE_RET();
774
}
775

    
776
/* Access to user mode registers from privileged modes.  */
777
void OPPROTO op_movl_T0_user(void)
778
{
779
    int regno = PARAM1;
780
    if (regno == 13) {
781
        T0 = env->banked_r13[0];
782
    } else if (regno == 14) {
783
        T0 = env->banked_r14[0];
784
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
785
        T0 = env->usr_regs[regno - 8];
786
    } else {
787
        T0 = env->regs[regno];
788
    }
789
    FORCE_RET();
790
}
791

    
792

    
793
void OPPROTO op_movl_user_T0(void)
794
{
795
    int regno = PARAM1;
796
    if (regno == 13) {
797
        env->banked_r13[0] = T0;
798
    } else if (regno == 14) {
799
        env->banked_r14[0] = T0;
800
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
801
        env->usr_regs[regno - 8] = T0;
802
    } else {
803
        env->regs[regno] = T0;
804
    }
805
    FORCE_RET();
806
}
807

    
808
void OPPROTO op_movl_T1_r13_banked(void)
809
{
810
    T1 = helper_get_r13_banked(env, PARAM1);
811
}
812

    
813
void OPPROTO op_movl_r13_T1_banked(void)
814
{
815
    helper_set_r13_banked(env, PARAM1, T1);
816
}
817

    
818
void OPPROTO op_v7m_mrs_T0(void)
819
{
820
    T0 = helper_v7m_mrs(env, PARAM1);
821
}
822

    
823
void OPPROTO op_v7m_msr_T0(void)
824
{
825
    helper_v7m_msr(env, PARAM1, T0);
826
}
827

    
828
void OPPROTO op_movl_T0_sp(void)
829
{
830
    if (PARAM1 == env->v7m.current_sp)
831
        T0 = env->regs[13];
832
    else
833
        T0 = env->v7m.other_sp;
834
    FORCE_RET();
835
}
836

    
837
#include "op_neon.h"
838

    
839
/* iwMMXt support */
840
#include "op_iwmmxt.c"