Statistics
| Branch: | Revision:

root / target-arm / op.c @ 157777ef

History | View | Annotate | Download (19.5 kB)

1
/*
2
 *  ARM micro operations
3
 * 
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005 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
#define REGNAME r0
24
#define REG (env->regs[0])
25
#include "op_template.h"
26

    
27
#define REGNAME r1
28
#define REG (env->regs[1])
29
#include "op_template.h"
30

    
31
#define REGNAME r2
32
#define REG (env->regs[2])
33
#include "op_template.h"
34

    
35
#define REGNAME r3
36
#define REG (env->regs[3])
37
#include "op_template.h"
38

    
39
#define REGNAME r4
40
#define REG (env->regs[4])
41
#include "op_template.h"
42

    
43
#define REGNAME r5
44
#define REG (env->regs[5])
45
#include "op_template.h"
46

    
47
#define REGNAME r6
48
#define REG (env->regs[6])
49
#include "op_template.h"
50

    
51
#define REGNAME r7
52
#define REG (env->regs[7])
53
#include "op_template.h"
54

    
55
#define REGNAME r8
56
#define REG (env->regs[8])
57
#include "op_template.h"
58

    
59
#define REGNAME r9
60
#define REG (env->regs[9])
61
#include "op_template.h"
62

    
63
#define REGNAME r10
64
#define REG (env->regs[10])
65
#include "op_template.h"
66

    
67
#define REGNAME r11
68
#define REG (env->regs[11])
69
#include "op_template.h"
70

    
71
#define REGNAME r12
72
#define REG (env->regs[12])
73
#include "op_template.h"
74

    
75
#define REGNAME r13
76
#define REG (env->regs[13])
77
#include "op_template.h"
78

    
79
#define REGNAME r14
80
#define REG (env->regs[14])
81
#include "op_template.h"
82

    
83
#define REGNAME r15
84
#define REG (env->regs[15])
85
#define SET_REG(x) REG = x & ~(uint32_t)1
86
#include "op_template.h"
87

    
88
void OPPROTO op_bx_T0(void)
89
{
90
  env->regs[15] = T0 & ~(uint32_t)1;
91
  env->thumb = (T0 & 1) != 0;
92
}
93

    
94
void OPPROTO op_movl_T0_0(void)
95
{
96
    T0 = 0;
97
}
98

    
99
void OPPROTO op_movl_T0_im(void)
100
{
101
    T0 = PARAM1;
102
}
103

    
104
void OPPROTO op_movl_T1_im(void)
105
{
106
    T1 = PARAM1;
107
}
108

    
109
void OPPROTO op_mov_CF_T1(void)
110
{
111
    env->CF = ((uint32_t)T1) >> 31;
112
}
113

    
114
void OPPROTO op_movl_T2_im(void)
115
{
116
    T2 = PARAM1;
117
}
118

    
119
void OPPROTO op_addl_T1_im(void)
120
{
121
    T1 += PARAM1;
122
}
123

    
124
void OPPROTO op_addl_T1_T2(void)
125
{
126
    T1 += T2;
127
}
128

    
129
void OPPROTO op_subl_T1_T2(void)
130
{
131
    T1 -= T2;
132
}
133

    
134
void OPPROTO op_addl_T0_T1(void)
135
{
136
    T0 += T1;
137
}
138

    
139
void OPPROTO op_addl_T0_T1_cc(void)
140
{
141
    unsigned int src1;
142
    src1 = T0;
143
    T0 += T1;
144
    env->NZF = T0;
145
    env->CF = T0 < src1;
146
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
147
}
148

    
149
void OPPROTO op_adcl_T0_T1(void)
150
{
151
    T0 += T1 + env->CF;
152
}
153

    
154
void OPPROTO op_adcl_T0_T1_cc(void)
155
{
156
    unsigned int src1;
157
    src1 = T0;
158
    if (!env->CF) {
159
        T0 += T1;
160
        env->CF = T0 < src1;
161
    } else {
162
        T0 += T1 + 1;
163
        env->CF = T0 <= src1;
164
    }
165
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
166
    env->NZF = T0;
167
    FORCE_RET();
168
}
169

    
170
#define OPSUB(sub, sbc, res, T0, T1)            \
171
                                                \
172
void OPPROTO op_ ## sub ## l_T0_T1(void)        \
173
{                                               \
174
    res = T0 - T1;                              \
175
}                                               \
176
                                                \
177
void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
178
{                                               \
179
    unsigned int src1;                          \
180
    src1 = T0;                                  \
181
    T0 -= T1;                                   \
182
    env->NZF = T0;                              \
183
    env->CF = src1 >= T1;                       \
184
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
185
    res = T0;                                   \
186
}                                               \
187
                                                \
188
void OPPROTO op_ ## sbc ## l_T0_T1(void)        \
189
{                                               \
190
    res = T0 - T1 + env->CF - 1;                \
191
}                                               \
192
                                                \
193
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
194
{                                               \
195
    unsigned int src1;                          \
196
    src1 = T0;                                  \
197
    if (!env->CF) {                             \
198
        T0 = T0 - T1 - 1;                       \
199
        env->CF = src1 > T1;                    \
200
    } else {                                    \
201
        T0 = T0 - T1;                           \
202
        env->CF = src1 >= T1;                   \
203
    }                                           \
204
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
205
    env->NZF = T0;                              \
206
    res = T0;                                   \
207
    FORCE_RET();                                \
208
}
209

    
210
OPSUB(sub, sbc, T0, T0, T1)
211

    
212
OPSUB(rsb, rsc, T0, T1, T0)
213

    
214
void OPPROTO op_andl_T0_T1(void)
215
{
216
    T0 &= T1;
217
}
218

    
219
void OPPROTO op_xorl_T0_T1(void)
220
{
221
    T0 ^= T1;
222
}
223

    
224
void OPPROTO op_orl_T0_T1(void)
225
{
226
    T0 |= T1;
227
}
228

    
229
void OPPROTO op_bicl_T0_T1(void)
230
{
231
    T0 &= ~T1;
232
}
233

    
234
void OPPROTO op_notl_T1(void)
235
{
236
    T1 = ~T1;
237
}
238

    
239
void OPPROTO op_logic_T0_cc(void)
240
{
241
    env->NZF = T0;
242
}
243

    
244
void OPPROTO op_logic_T1_cc(void)
245
{
246
    env->NZF = T1;
247
}
248

    
249
#define EIP (env->regs[15])
250

    
251
void OPPROTO op_test_eq(void)
252
{
253
    if (env->NZF == 0)
254
        JUMP_TB(op_test_eq, PARAM1, 0, PARAM2);
255
    FORCE_RET();
256
}
257

    
258
void OPPROTO op_test_ne(void)
259
{
260
    if (env->NZF != 0)
261
        JUMP_TB(op_test_ne, PARAM1, 0, PARAM2);
262
    FORCE_RET();
263
}
264

    
265
void OPPROTO op_test_cs(void)
266
{
267
    if (env->CF != 0)
268
        JUMP_TB(op_test_cs, PARAM1, 0, PARAM2);
269
    FORCE_RET();
270
}
271

    
272
void OPPROTO op_test_cc(void)
273
{
274
    if (env->CF == 0)
275
        JUMP_TB(op_test_cc, PARAM1, 0, PARAM2);
276
    FORCE_RET();
277
}
278

    
279
void OPPROTO op_test_mi(void)
280
{
281
    if ((env->NZF & 0x80000000) != 0)
282
        JUMP_TB(op_test_mi, PARAM1, 0, PARAM2);
283
    FORCE_RET();
284
}
285

    
286
void OPPROTO op_test_pl(void)
287
{
288
    if ((env->NZF & 0x80000000) == 0)
289
        JUMP_TB(op_test_pl, PARAM1, 0, PARAM2);
290
    FORCE_RET();
291
}
292

    
293
void OPPROTO op_test_vs(void)
294
{
295
    if ((env->VF & 0x80000000) != 0)
296
        JUMP_TB(op_test_vs, PARAM1, 0, PARAM2);
297
    FORCE_RET();
298
}
299

    
300
void OPPROTO op_test_vc(void)
301
{
302
    if ((env->VF & 0x80000000) == 0)
303
        JUMP_TB(op_test_vc, PARAM1, 0, PARAM2);
304
    FORCE_RET();
305
}
306

    
307
void OPPROTO op_test_hi(void)
308
{
309
    if (env->CF != 0 && env->NZF != 0)
310
        JUMP_TB(op_test_hi, PARAM1, 0, PARAM2);
311
    FORCE_RET();
312
}
313

    
314
void OPPROTO op_test_ls(void)
315
{
316
    if (env->CF == 0 || env->NZF == 0)
317
        JUMP_TB(op_test_ls, PARAM1, 0, PARAM2);
318
    FORCE_RET();
319
}
320

    
321
void OPPROTO op_test_ge(void)
322
{
323
    if (((env->VF ^ env->NZF) & 0x80000000) == 0)
324
        JUMP_TB(op_test_ge, PARAM1, 0, PARAM2);
325
    FORCE_RET();
326
}
327

    
328
void OPPROTO op_test_lt(void)
329
{
330
    if (((env->VF ^ env->NZF) & 0x80000000) != 0)
331
        JUMP_TB(op_test_lt, PARAM1, 0, PARAM2);
332
    FORCE_RET();
333
}
334

    
335
void OPPROTO op_test_gt(void)
336
{
337
    if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
338
        JUMP_TB(op_test_gt, PARAM1, 0, PARAM2);
339
    FORCE_RET();
340
}
341

    
342
void OPPROTO op_test_le(void)
343
{
344
    if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
345
        JUMP_TB(op_test_le, PARAM1, 0, PARAM2);
346
    FORCE_RET();
347
}
348

    
349
void OPPROTO op_jmp(void)
350
{
351
    JUMP_TB(op_jmp, PARAM1, 1, PARAM2);
352
}
353

    
354
void OPPROTO op_exit_tb(void)
355
{
356
    EXIT_TB();
357
}
358

    
359
void OPPROTO op_movl_T0_psr(void)
360
{
361
    T0 = compute_cpsr();
362
}
363

    
364
/* NOTE: N = 1 and Z = 1 cannot be stored currently */
365
void OPPROTO op_movl_psr_T0(void)
366
{
367
    unsigned int psr;
368
    psr = T0;
369
    env->CF = (psr >> 29) & 1;
370
    env->NZF = (psr & 0xc0000000) ^ 0x40000000;
371
    env->VF = (psr << 3) & 0x80000000;
372
    /* for user mode we do not update other state info */
373
}
374

    
375
void OPPROTO op_mul_T0_T1(void)
376
{
377
    T0 = T0 * T1;
378
}
379

    
380
/* 64 bit unsigned mul */
381
void OPPROTO op_mull_T0_T1(void)
382
{
383
    uint64_t res;
384
    res = (uint64_t)T0 * (uint64_t)T1;
385
    T1 = res >> 32;
386
    T0 = res;
387
}
388

    
389
/* 64 bit signed mul */
390
void OPPROTO op_imull_T0_T1(void)
391
{
392
    uint64_t res;
393
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
394
    T1 = res >> 32;
395
    T0 = res;
396
}
397

    
398
/* 48 bit signed mul, top 32 bits */
399
void OPPROTO op_imulw_T0_T1(void)
400
{
401
  uint64_t res;
402
  res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
403
  T0 = res >> 16;
404
}
405

    
406
void OPPROTO op_addq_T0_T1(void)
407
{
408
    uint64_t res;
409
    res = ((uint64_t)T1 << 32) | T0;
410
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
411
    T1 = res >> 32;
412
    T0 = res;
413
}
414

    
415
void OPPROTO op_addq_lo_T0_T1(void)
416
{
417
    uint64_t res;
418
    res = ((uint64_t)T1 << 32) | T0;
419
    res += (uint64_t)(env->regs[PARAM1]);
420
    T1 = res >> 32;
421
    T0 = res;
422
}
423

    
424
void OPPROTO op_logicq_cc(void)
425
{
426
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
427
}
428

    
429
/* memory access */
430

    
431
void OPPROTO op_ldub_T0_T1(void)
432
{
433
    T0 = ldub((void *)T1);
434
}
435

    
436
void OPPROTO op_ldsb_T0_T1(void)
437
{
438
    T0 = ldsb((void *)T1);
439
}
440

    
441
void OPPROTO op_lduw_T0_T1(void)
442
{
443
    T0 = lduw((void *)T1);
444
}
445

    
446
void OPPROTO op_ldsw_T0_T1(void)
447
{
448
    T0 = ldsw((void *)T1);
449
}
450

    
451
void OPPROTO op_ldl_T0_T1(void)
452
{
453
    T0 = ldl((void *)T1);
454
}
455

    
456
void OPPROTO op_stb_T0_T1(void)
457
{
458
    stb((void *)T1, T0);
459
}
460

    
461
void OPPROTO op_stw_T0_T1(void)
462
{
463
    stw((void *)T1, T0);
464
}
465

    
466
void OPPROTO op_stl_T0_T1(void)
467
{
468
    stl((void *)T1, T0);
469
}
470

    
471
void OPPROTO op_swpb_T0_T1(void)
472
{
473
    int tmp;
474

    
475
    cpu_lock();
476
    tmp = ldub((void *)T1);
477
    stb((void *)T1, T0);
478
    T0 = tmp;
479
    cpu_unlock();
480
}
481

    
482
void OPPROTO op_swpl_T0_T1(void)
483
{
484
    int tmp;
485

    
486
    cpu_lock();
487
    tmp = ldl((void *)T1);
488
    stl((void *)T1, T0);
489
    T0 = tmp;
490
    cpu_unlock();
491
}
492

    
493
/* shifts */
494

    
495
/* T1 based */
496

    
497
void OPPROTO op_shll_T1_im(void)
498
{
499
    T1 = T1 << PARAM1;
500
}
501

    
502
void OPPROTO op_shrl_T1_im(void)
503
{
504
    T1 = (uint32_t)T1 >> PARAM1;
505
}
506

    
507
void OPPROTO op_shrl_T1_0(void)
508
{
509
    T1 = 0;
510
}
511

    
512
void OPPROTO op_sarl_T1_im(void)
513
{
514
    T1 = (int32_t)T1 >> PARAM1;
515
}
516

    
517
void OPPROTO op_sarl_T1_0(void)
518
{
519
    T1 = (int32_t)T1 >> 31;
520
}
521

    
522
void OPPROTO op_rorl_T1_im(void)
523
{
524
    int shift;
525
    shift = PARAM1;
526
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
527
}
528

    
529
void OPPROTO op_rrxl_T1(void)
530
{
531
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
532
}
533

    
534
/* T1 based, set C flag */
535
void OPPROTO op_shll_T1_im_cc(void)
536
{
537
    env->CF = (T1 >> (32 - PARAM1)) & 1;
538
    T1 = T1 << PARAM1;
539
}
540

    
541
void OPPROTO op_shrl_T1_im_cc(void)
542
{
543
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
544
    T1 = (uint32_t)T1 >> PARAM1;
545
}
546

    
547
void OPPROTO op_shrl_T1_0_cc(void)
548
{
549
    env->CF = (T1 >> 31) & 1;
550
    T1 = 0;
551
}
552

    
553
void OPPROTO op_sarl_T1_im_cc(void)
554
{
555
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
556
    T1 = (int32_t)T1 >> PARAM1;
557
}
558

    
559
void OPPROTO op_sarl_T1_0_cc(void)
560
{
561
    env->CF = (T1 >> 31) & 1;
562
    T1 = (int32_t)T1 >> 31;
563
}
564

    
565
void OPPROTO op_rorl_T1_im_cc(void)
566
{
567
    int shift;
568
    shift = PARAM1;
569
    env->CF = (T1 >> (shift - 1)) & 1;
570
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
571
}
572

    
573
void OPPROTO op_rrxl_T1_cc(void)
574
{
575
    uint32_t c;
576
    c = T1 & 1;
577
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
578
    env->CF = c;
579
}
580

    
581
/* T2 based */
582
void OPPROTO op_shll_T2_im(void)
583
{
584
    T2 = T2 << PARAM1;
585
}
586

    
587
void OPPROTO op_shrl_T2_im(void)
588
{
589
    T2 = (uint32_t)T2 >> PARAM1;
590
}
591

    
592
void OPPROTO op_shrl_T2_0(void)
593
{
594
    T2 = 0;
595
}
596

    
597
void OPPROTO op_sarl_T2_im(void)
598
{
599
    T2 = (int32_t)T2 >> PARAM1;
600
}
601

    
602
void OPPROTO op_sarl_T2_0(void)
603
{
604
    T2 = (int32_t)T2 >> 31;
605
}
606

    
607
void OPPROTO op_rorl_T2_im(void)
608
{
609
    int shift;
610
    shift = PARAM1;
611
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
612
}
613

    
614
void OPPROTO op_rrxl_T2(void)
615
{
616
    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
617
}
618

    
619
/* T1 based, use T0 as shift count */
620

    
621
void OPPROTO op_shll_T1_T0(void)
622
{
623
    int shift;
624
    shift = T0 & 0xff;
625
    if (shift >= 32)
626
        T1 = 0;
627
    else
628
        T1 = T1 << shift;
629
    FORCE_RET();
630
}
631

    
632
void OPPROTO op_shrl_T1_T0(void)
633
{
634
    int shift;
635
    shift = T0 & 0xff;
636
    if (shift >= 32)
637
        T1 = 0;
638
    else
639
        T1 = (uint32_t)T1 >> shift;
640
    FORCE_RET();
641
}
642

    
643
void OPPROTO op_sarl_T1_T0(void)
644
{
645
    int shift;
646
    shift = T0 & 0xff;
647
    if (shift >= 32)
648
        shift = 31;
649
    T1 = (int32_t)T1 >> shift;
650
}
651

    
652
void OPPROTO op_rorl_T1_T0(void)
653
{
654
    int shift;
655
    shift = T0 & 0x1f;
656
    if (shift) {
657
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
658
    }
659
    FORCE_RET();
660
}
661

    
662
/* T1 based, use T0 as shift count and compute CF */
663

    
664
void OPPROTO op_shll_T1_T0_cc(void)
665
{
666
    int shift;
667
    shift = T0 & 0xff;
668
    if (shift >= 32) {
669
        if (shift == 32)
670
            env->CF = T1 & 1;
671
        else
672
            env->CF = 0;
673
        T1 = 0;
674
    } else if (shift != 0) {
675
        env->CF = (T1 >> (32 - shift)) & 1;
676
        T1 = T1 << shift;
677
    }
678
    FORCE_RET();
679
}
680

    
681
void OPPROTO op_shrl_T1_T0_cc(void)
682
{
683
    int shift;
684
    shift = T0 & 0xff;
685
    if (shift >= 32) {
686
        if (shift == 32)
687
            env->CF = (T1 >> 31) & 1;
688
        else
689
            env->CF = 0;
690
        T1 = 0;
691
    } else if (shift != 0) {
692
        env->CF = (T1 >> (shift - 1)) & 1;
693
        T1 = (uint32_t)T1 >> shift;
694
    }
695
    FORCE_RET();
696
}
697

    
698
void OPPROTO op_sarl_T1_T0_cc(void)
699
{
700
    int shift;
701
    shift = T0 & 0xff;
702
    if (shift >= 32) {
703
        env->CF = (T1 >> 31) & 1;
704
        T1 = (int32_t)T1 >> 31;
705
    } else {
706
        env->CF = (T1 >> (shift - 1)) & 1;
707
        T1 = (int32_t)T1 >> shift;
708
    }
709
    FORCE_RET();
710
}
711

    
712
void OPPROTO op_rorl_T1_T0_cc(void)
713
{
714
    int shift1, shift;
715
    shift1 = T0 & 0xff;
716
    shift = shift1 & 0x1f;
717
    if (shift == 0) {
718
        if (shift1 != 0)
719
            env->CF = (T1 >> 31) & 1;
720
    } else {
721
        env->CF = (T1 >> (shift - 1)) & 1;
722
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
723
    }
724
    FORCE_RET();
725
}
726

    
727
/* misc */
728
void OPPROTO op_clz_T0(void)
729
{
730
    int count;
731
    for (count = 32; T0 > 0; count--)
732
        T0 = T0 >> 1;
733
    T0 = count;
734
    FORCE_RET();
735
}
736

    
737
void OPPROTO op_sarl_T0_im(void)
738
{
739
    T0 = (int32_t)T0 >> PARAM1;
740
}
741

    
742
/* 16->32 Sign extend */
743
void OPPROTO op_sxl_T0(void)
744
{
745
  T0 = (int16_t)T0;
746
}
747

    
748
void OPPROTO op_sxl_T1(void)
749
{
750
  T1 = (int16_t)T1;
751
}
752

    
753
#define SIGNBIT (uint32_t)0x80000000
754
/* saturating arithmetic  */
755
void OPPROTO op_addl_T0_T1_setq(void)
756
{
757
  uint32_t res;
758

    
759
  res = T0 + T1;
760
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
761
      env->QF = 1;
762

    
763
  T0 = res;
764
  FORCE_RET();
765
}
766

    
767
void OPPROTO op_addl_T0_T1_saturate(void)
768
{
769
  uint32_t res;
770

    
771
  res = T0 + T1;
772
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
773
      env->QF = 1;
774
      if (T0 & SIGNBIT)
775
          T0 = 0x80000000;
776
      else
777
          T0 = 0x7fffffff;
778
  }
779
  else
780
    T0 = res;
781
  
782
  FORCE_RET();
783
}
784

    
785
void OPPROTO op_subl_T0_T1_saturate(void)
786
{
787
  uint32_t res;
788

    
789
  res = T0 - T1;
790
  if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
791
      env->QF = 1;
792
      if (T0 & SIGNBIT)
793
          T0 = 0x8000000;
794
      else
795
          T0 = 0x7fffffff;
796
  }
797
  else
798
    T0 = res;
799
  
800
  FORCE_RET();
801
}
802

    
803
/* thumb shift by immediate */
804
void OPPROTO op_shll_T0_im_thumb(void)
805
{
806
    int shift;
807
    shift = PARAM1;
808
    if (shift != 0) {
809
        env->CF = (T1 >> (32 - shift)) & 1;
810
        T0 = T0 << shift;
811
    }
812
    env->NZF = T0;
813
    FORCE_RET();
814
}
815

    
816
void OPPROTO op_shrl_T0_im_thumb(void)
817
{
818
    int shift;
819

    
820
    shift = PARAM1;
821
    if (shift == 0) {
822
        env->CF = 0;
823
        T0 = 0;
824
    } else {
825
        env->CF = (T0 >> (shift - 1)) & 1;
826
        T0 = T0 >> shift;
827
    }
828
    FORCE_RET();
829
}
830

    
831
void OPPROTO op_sarl_T0_im_thumb(void)
832
{
833
    int shift;
834

    
835
    shift = PARAM1;
836
    if (shift == 0) {
837
        T0 = ((int32_t)T0) >> 31;
838
        env->CF = T0 & 1;
839
    } else {
840
        env->CF = (T0 >> (shift - 1)) & 1;
841
        T0 = ((int32_t)T0) >> shift;
842
    }
843
    env->NZF = T0;
844
    FORCE_RET();
845
}
846

    
847
/* exceptions */
848

    
849
void OPPROTO op_swi(void)
850
{
851
    env->exception_index = EXCP_SWI;
852
    cpu_loop_exit();
853
}
854

    
855
void OPPROTO op_undef_insn(void)
856
{
857
    env->exception_index = EXCP_UDEF;
858
    cpu_loop_exit();
859
}
860

    
861
/* VFP support.  We follow the convention used for VFP instrunctions:
862
   Single precition routines have a "s" suffix, double precision a
863
   "d" suffix.  */
864

    
865
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
866

    
867
#define VFP_BINOP(name, op) \
868
VFP_OP(name, s)             \
869
{                           \
870
    FT0s = FT0s op FT1s;    \
871
}                           \
872
VFP_OP(name, d)             \
873
{                           \
874
    FT0d = FT0d op FT1d;    \
875
}
876
VFP_BINOP(add, +)
877
VFP_BINOP(sub, -)
878
VFP_BINOP(mul, *)
879
VFP_BINOP(div, /)
880
#undef VFP_BINOP
881

    
882
#define VFP_HELPER(name)  \
883
VFP_OP(name, s)           \
884
{                         \
885
    do_vfp_##name##s();    \
886
}                         \
887
VFP_OP(name, d)           \
888
{                         \
889
    do_vfp_##name##d();    \
890
}
891
VFP_HELPER(abs)
892
VFP_HELPER(sqrt)
893
VFP_HELPER(cmp)
894
VFP_HELPER(cmpe)
895
#undef VFP_HELPER
896

    
897
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
898
   without looking at the rest of the value.  */
899
VFP_OP(neg, s)
900
{
901
    FT0s = -FT0s;
902
}
903

    
904
VFP_OP(neg, d)
905
{
906
    FT0d = -FT0d;
907
}
908

    
909
VFP_OP(F1_ld0, s)
910
{
911
    FT1s = 0.0f;
912
}
913

    
914
VFP_OP(F1_ld0, d)
915
{
916
    FT1d = 0.0;
917
}
918

    
919
/* Helper routines to perform bitwise copies between float and int.  */
920
static inline float vfp_itos(uint32_t i)
921
{
922
    union {
923
        uint32_t i;
924
        float s;
925
    } v;
926

    
927
    v.i = i;
928
    return v.s;
929
}
930

    
931
static inline uint32_t vfp_stoi(float s)
932
{
933
    union {
934
        uint32_t i;
935
        float s;
936
    } v;
937

    
938
    v.s = s;
939
    return v.i;
940
}
941

    
942
/* Integer to float conversion.  */
943
VFP_OP(uito, s)
944
{
945
    FT0s = (float)(uint32_t)vfp_stoi(FT0s);
946
}
947

    
948
VFP_OP(uito, d)
949
{
950
    FT0d = (double)(uint32_t)vfp_stoi(FT0s);
951
}
952

    
953
VFP_OP(sito, s)
954
{
955
    FT0s = (float)(int32_t)vfp_stoi(FT0s);
956
}
957

    
958
VFP_OP(sito, d)
959
{
960
    FT0d = (double)(int32_t)vfp_stoi(FT0s);
961
}
962

    
963
/* Float to integer conversion.  */
964
VFP_OP(toui, s)
965
{
966
    FT0s = vfp_itos((uint32_t)FT0s);
967
}
968

    
969
VFP_OP(toui, d)
970
{
971
    FT0s = vfp_itos((uint32_t)FT0d);
972
}
973

    
974
VFP_OP(tosi, s)
975
{
976
    FT0s = vfp_itos((int32_t)FT0s);
977
}
978

    
979
VFP_OP(tosi, d)
980
{
981
    FT0s = vfp_itos((int32_t)FT0d);
982
}
983

    
984
/* TODO: Set rounding mode properly.  */
985
VFP_OP(touiz, s)
986
{
987
    FT0s = vfp_itos((uint32_t)FT0s);
988
}
989

    
990
VFP_OP(touiz, d)
991
{
992
    FT0s = vfp_itos((uint32_t)FT0d);
993
}
994

    
995
VFP_OP(tosiz, s)
996
{
997
    FT0s = vfp_itos((int32_t)FT0s);
998
}
999

    
1000
VFP_OP(tosiz, d)
1001
{
1002
    FT0s = vfp_itos((int32_t)FT0d);
1003
}
1004

    
1005
/* floating point conversion */
1006
VFP_OP(fcvtd, s)
1007
{
1008
    FT0d = (double)FT0s;
1009
}
1010

    
1011
VFP_OP(fcvts, d)
1012
{
1013
    FT0s = (float)FT0d;
1014
}
1015

    
1016
/* Get and Put values from registers.  */
1017
VFP_OP(getreg_F0, d)
1018
{
1019
  FT0d = *(double *)((char *) env + PARAM1);
1020
}
1021

    
1022
VFP_OP(getreg_F0, s)
1023
{
1024
  FT0s = *(float *)((char *) env + PARAM1);
1025
}
1026

    
1027
VFP_OP(getreg_F1, d)
1028
{
1029
  FT1d = *(double *)((char *) env + PARAM1);
1030
}
1031

    
1032
VFP_OP(getreg_F1, s)
1033
{
1034
  FT1s = *(float *)((char *) env + PARAM1);
1035
}
1036

    
1037
VFP_OP(setreg_F0, d)
1038
{
1039
  *(double *)((char *) env + PARAM1) = FT0d;
1040
}
1041

    
1042
VFP_OP(setreg_F0, s)
1043
{
1044
  *(float *)((char *) env + PARAM1) = FT0s;
1045
}
1046

    
1047
VFP_OP(foobar, d)
1048
{
1049
  FT0d = env->vfp.regs.s[3];
1050
}
1051

    
1052
void OPPROTO op_vfp_movl_T0_fpscr(void)
1053
{
1054
    do_vfp_get_fpscr ();
1055
}
1056

    
1057
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1058
{
1059
    T0 = env->vfp.fpscr & (0xf << 28);
1060
}
1061

    
1062
void OPPROTO op_vfp_movl_fpscr_T0(void)
1063
{
1064
    do_vfp_set_fpscr();
1065
}
1066

    
1067
/* Move between FT0s to T0  */
1068
void OPPROTO op_vfp_mrs(void)
1069
{
1070
    T0 = vfp_stoi(FT0s);
1071
}
1072

    
1073
void OPPROTO op_vfp_msr(void)
1074
{
1075
    FT0s = vfp_itos(T0);
1076
}
1077

    
1078
/* Move between FT0d and {T0,T1} */
1079
void OPPROTO op_vfp_mrrd(void)
1080
{
1081
    CPU_DoubleU u;
1082
    
1083
    u.d = FT0d;
1084
    T0 = u.l.lower;
1085
    T1 = u.l.upper;
1086
}
1087

    
1088
void OPPROTO op_vfp_mdrr(void)
1089
{
1090
    CPU_DoubleU u;
1091
    
1092
    u.l.lower = T0;
1093
    u.l.upper = T1;
1094
    FT0d = u.d;
1095
}
1096

    
1097
/* Floating point load/store.  Address is in T1 */
1098
void OPPROTO op_vfp_lds(void)
1099
{
1100
    FT0s = ldfl((void *)T1);
1101
}
1102

    
1103
void OPPROTO op_vfp_ldd(void)
1104
{
1105
    FT0d = ldfq((void *)T1);
1106
}
1107

    
1108
void OPPROTO op_vfp_sts(void)
1109
{
1110
    stfl((void *)T1, FT0s);
1111
}
1112

    
1113
void OPPROTO op_vfp_std(void)
1114
{
1115
    stfq((void *)T1, FT0d);
1116
}