Statistics
| Branch: | Revision:

root / target-arm / op.c @ c53be334

History | View | Annotate | Download (20.3 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
        GOTO_LABEL_PARAM(1);;
255
    FORCE_RET();
256
}
257

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

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

    
272
void OPPROTO op_test_cc(void)
273
{
274
    if (env->CF == 0)
275
        GOTO_LABEL_PARAM(1);
276
    FORCE_RET();
277
}
278

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

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

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

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

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

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

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

    
328
void OPPROTO op_test_lt(void)
329
{
330
    if (((env->VF ^ env->NZF) & 0x80000000) != 0)
331
        GOTO_LABEL_PARAM(1);
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
        GOTO_LABEL_PARAM(1);
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
        GOTO_LABEL_PARAM(1);
346
    FORCE_RET();
347
}
348

    
349
void OPPROTO op_goto_tb0(void)
350
{
351
    GOTO_TB(op_goto_tb0, PARAM1, 0);
352
}
353

    
354
void OPPROTO op_goto_tb1(void)
355
{
356
    GOTO_TB(op_goto_tb1, PARAM1, 1);
357
}
358

    
359
void OPPROTO op_exit_tb(void)
360
{
361
    EXIT_TB();
362
}
363

    
364
void OPPROTO op_movl_T0_psr(void)
365
{
366
    T0 = compute_cpsr();
367
}
368

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

    
380
void OPPROTO op_mul_T0_T1(void)
381
{
382
    T0 = T0 * T1;
383
}
384

    
385
/* 64 bit unsigned mul */
386
void OPPROTO op_mull_T0_T1(void)
387
{
388
    uint64_t res;
389
    res = (uint64_t)T0 * (uint64_t)T1;
390
    T1 = res >> 32;
391
    T0 = res;
392
}
393

    
394
/* 64 bit signed mul */
395
void OPPROTO op_imull_T0_T1(void)
396
{
397
    uint64_t res;
398
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
399
    T1 = res >> 32;
400
    T0 = res;
401
}
402

    
403
/* 48 bit signed mul, top 32 bits */
404
void OPPROTO op_imulw_T0_T1(void)
405
{
406
  uint64_t res;
407
  res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
408
  T0 = res >> 16;
409
}
410

    
411
void OPPROTO op_addq_T0_T1(void)
412
{
413
    uint64_t res;
414
    res = ((uint64_t)T1 << 32) | T0;
415
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
416
    T1 = res >> 32;
417
    T0 = res;
418
}
419

    
420
void OPPROTO op_addq_lo_T0_T1(void)
421
{
422
    uint64_t res;
423
    res = ((uint64_t)T1 << 32) | T0;
424
    res += (uint64_t)(env->regs[PARAM1]);
425
    T1 = res >> 32;
426
    T0 = res;
427
}
428

    
429
void OPPROTO op_logicq_cc(void)
430
{
431
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
432
}
433

    
434
/* memory access */
435

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

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

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

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

    
456
void OPPROTO op_ldl_T0_T1(void)
457
{
458
    T0 = ldl((void *)T1);
459
}
460

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

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

    
471
void OPPROTO op_stl_T0_T1(void)
472
{
473
    stl((void *)T1, T0);
474
}
475

    
476
void OPPROTO op_swpb_T0_T1(void)
477
{
478
    int tmp;
479

    
480
    cpu_lock();
481
    tmp = ldub((void *)T1);
482
    stb((void *)T1, T0);
483
    T0 = tmp;
484
    cpu_unlock();
485
}
486

    
487
void OPPROTO op_swpl_T0_T1(void)
488
{
489
    int tmp;
490

    
491
    cpu_lock();
492
    tmp = ldl((void *)T1);
493
    stl((void *)T1, T0);
494
    T0 = tmp;
495
    cpu_unlock();
496
}
497

    
498
/* shifts */
499

    
500
/* T1 based */
501

    
502
void OPPROTO op_shll_T1_im(void)
503
{
504
    T1 = T1 << PARAM1;
505
}
506

    
507
void OPPROTO op_shrl_T1_im(void)
508
{
509
    T1 = (uint32_t)T1 >> PARAM1;
510
}
511

    
512
void OPPROTO op_shrl_T1_0(void)
513
{
514
    T1 = 0;
515
}
516

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

    
522
void OPPROTO op_sarl_T1_0(void)
523
{
524
    T1 = (int32_t)T1 >> 31;
525
}
526

    
527
void OPPROTO op_rorl_T1_im(void)
528
{
529
    int shift;
530
    shift = PARAM1;
531
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
532
}
533

    
534
void OPPROTO op_rrxl_T1(void)
535
{
536
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
537
}
538

    
539
/* T1 based, set C flag */
540
void OPPROTO op_shll_T1_im_cc(void)
541
{
542
    env->CF = (T1 >> (32 - PARAM1)) & 1;
543
    T1 = T1 << PARAM1;
544
}
545

    
546
void OPPROTO op_shrl_T1_im_cc(void)
547
{
548
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
549
    T1 = (uint32_t)T1 >> PARAM1;
550
}
551

    
552
void OPPROTO op_shrl_T1_0_cc(void)
553
{
554
    env->CF = (T1 >> 31) & 1;
555
    T1 = 0;
556
}
557

    
558
void OPPROTO op_sarl_T1_im_cc(void)
559
{
560
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
561
    T1 = (int32_t)T1 >> PARAM1;
562
}
563

    
564
void OPPROTO op_sarl_T1_0_cc(void)
565
{
566
    env->CF = (T1 >> 31) & 1;
567
    T1 = (int32_t)T1 >> 31;
568
}
569

    
570
void OPPROTO op_rorl_T1_im_cc(void)
571
{
572
    int shift;
573
    shift = PARAM1;
574
    env->CF = (T1 >> (shift - 1)) & 1;
575
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
576
}
577

    
578
void OPPROTO op_rrxl_T1_cc(void)
579
{
580
    uint32_t c;
581
    c = T1 & 1;
582
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
583
    env->CF = c;
584
}
585

    
586
/* T2 based */
587
void OPPROTO op_shll_T2_im(void)
588
{
589
    T2 = T2 << PARAM1;
590
}
591

    
592
void OPPROTO op_shrl_T2_im(void)
593
{
594
    T2 = (uint32_t)T2 >> PARAM1;
595
}
596

    
597
void OPPROTO op_shrl_T2_0(void)
598
{
599
    T2 = 0;
600
}
601

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

    
607
void OPPROTO op_sarl_T2_0(void)
608
{
609
    T2 = (int32_t)T2 >> 31;
610
}
611

    
612
void OPPROTO op_rorl_T2_im(void)
613
{
614
    int shift;
615
    shift = PARAM1;
616
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
617
}
618

    
619
void OPPROTO op_rrxl_T2(void)
620
{
621
    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
622
}
623

    
624
/* T1 based, use T0 as shift count */
625

    
626
void OPPROTO op_shll_T1_T0(void)
627
{
628
    int shift;
629
    shift = T0 & 0xff;
630
    if (shift >= 32)
631
        T1 = 0;
632
    else
633
        T1 = T1 << shift;
634
    FORCE_RET();
635
}
636

    
637
void OPPROTO op_shrl_T1_T0(void)
638
{
639
    int shift;
640
    shift = T0 & 0xff;
641
    if (shift >= 32)
642
        T1 = 0;
643
    else
644
        T1 = (uint32_t)T1 >> shift;
645
    FORCE_RET();
646
}
647

    
648
void OPPROTO op_sarl_T1_T0(void)
649
{
650
    int shift;
651
    shift = T0 & 0xff;
652
    if (shift >= 32)
653
        shift = 31;
654
    T1 = (int32_t)T1 >> shift;
655
}
656

    
657
void OPPROTO op_rorl_T1_T0(void)
658
{
659
    int shift;
660
    shift = T0 & 0x1f;
661
    if (shift) {
662
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
663
    }
664
    FORCE_RET();
665
}
666

    
667
/* T1 based, use T0 as shift count and compute CF */
668

    
669
void OPPROTO op_shll_T1_T0_cc(void)
670
{
671
    int shift;
672
    shift = T0 & 0xff;
673
    if (shift >= 32) {
674
        if (shift == 32)
675
            env->CF = T1 & 1;
676
        else
677
            env->CF = 0;
678
        T1 = 0;
679
    } else if (shift != 0) {
680
        env->CF = (T1 >> (32 - shift)) & 1;
681
        T1 = T1 << shift;
682
    }
683
    FORCE_RET();
684
}
685

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

    
703
void OPPROTO op_sarl_T1_T0_cc(void)
704
{
705
    int shift;
706
    shift = T0 & 0xff;
707
    if (shift >= 32) {
708
        env->CF = (T1 >> 31) & 1;
709
        T1 = (int32_t)T1 >> 31;
710
    } else {
711
        env->CF = (T1 >> (shift - 1)) & 1;
712
        T1 = (int32_t)T1 >> shift;
713
    }
714
    FORCE_RET();
715
}
716

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

    
732
/* misc */
733
void OPPROTO op_clz_T0(void)
734
{
735
    int count;
736
    for (count = 32; T0 > 0; count--)
737
        T0 = T0 >> 1;
738
    T0 = count;
739
    FORCE_RET();
740
}
741

    
742
void OPPROTO op_sarl_T0_im(void)
743
{
744
    T0 = (int32_t)T0 >> PARAM1;
745
}
746

    
747
/* 16->32 Sign extend */
748
void OPPROTO op_sxl_T0(void)
749
{
750
  T0 = (int16_t)T0;
751
}
752

    
753
void OPPROTO op_sxl_T1(void)
754
{
755
  T1 = (int16_t)T1;
756
}
757

    
758
#define SIGNBIT (uint32_t)0x80000000
759
/* saturating arithmetic  */
760
void OPPROTO op_addl_T0_T1_setq(void)
761
{
762
  uint32_t res;
763

    
764
  res = T0 + T1;
765
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
766
      env->QF = 1;
767

    
768
  T0 = res;
769
  FORCE_RET();
770
}
771

    
772
void OPPROTO op_addl_T0_T1_saturate(void)
773
{
774
  uint32_t res;
775

    
776
  res = T0 + T1;
777
  if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
778
      env->QF = 1;
779
      if (T0 & SIGNBIT)
780
          T0 = 0x80000000;
781
      else
782
          T0 = 0x7fffffff;
783
  }
784
  else
785
    T0 = res;
786
  
787
  FORCE_RET();
788
}
789

    
790
void OPPROTO op_subl_T0_T1_saturate(void)
791
{
792
  uint32_t res;
793

    
794
  res = T0 - T1;
795
  if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
796
      env->QF = 1;
797
      if (T0 & SIGNBIT)
798
          T0 = 0x8000000;
799
      else
800
          T0 = 0x7fffffff;
801
  }
802
  else
803
    T0 = res;
804
  
805
  FORCE_RET();
806
}
807

    
808
void OPPROTO op_double_T1_saturate(void)
809
{
810
  int32_t val;
811

    
812
  val = T1;
813
  if (val >= 0x40000000) {
814
      T1 = 0x7fffffff;
815
      env->QF = 1;
816
  } else if (val <= (int32_t)0xc0000000) {
817
      T1 = 0x80000000;
818
      env->QF = 1;
819
  } else {
820
      T1 = val << 1;
821
  }
822
  FORCE_RET();
823
}
824

    
825
/* thumb shift by immediate */
826
void OPPROTO op_shll_T0_im_thumb(void)
827
{
828
    int shift;
829
    shift = PARAM1;
830
    if (shift != 0) {
831
        env->CF = (T1 >> (32 - shift)) & 1;
832
        T0 = T0 << shift;
833
    }
834
    env->NZF = T0;
835
    FORCE_RET();
836
}
837

    
838
void OPPROTO op_shrl_T0_im_thumb(void)
839
{
840
    int shift;
841

    
842
    shift = PARAM1;
843
    if (shift == 0) {
844
        env->CF = ((uint32_t)shift) >> 31;
845
        T0 = 0;
846
    } else {
847
        env->CF = (T0 >> (shift - 1)) & 1;
848
        T0 = T0 >> shift;
849
    }
850
    env->NZF = T0;
851
    FORCE_RET();
852
}
853

    
854
void OPPROTO op_sarl_T0_im_thumb(void)
855
{
856
    int shift;
857

    
858
    shift = PARAM1;
859
    if (shift == 0) {
860
        T0 = ((int32_t)T0) >> 31;
861
        env->CF = T0 & 1;
862
    } else {
863
        env->CF = (T0 >> (shift - 1)) & 1;
864
        T0 = ((int32_t)T0) >> shift;
865
    }
866
    env->NZF = T0;
867
    FORCE_RET();
868
}
869

    
870
/* exceptions */
871

    
872
void OPPROTO op_swi(void)
873
{
874
    env->exception_index = EXCP_SWI;
875
    cpu_loop_exit();
876
}
877

    
878
void OPPROTO op_undef_insn(void)
879
{
880
    env->exception_index = EXCP_UDEF;
881
    cpu_loop_exit();
882
}
883

    
884
void OPPROTO op_debug(void)
885
{
886
    env->exception_index = EXCP_DEBUG;
887
    cpu_loop_exit();
888
}
889

    
890
/* VFP support.  We follow the convention used for VFP instrunctions:
891
   Single precition routines have a "s" suffix, double precision a
892
   "d" suffix.  */
893

    
894
#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
895

    
896
#define VFP_BINOP(name) \
897
VFP_OP(name, s)             \
898
{                           \
899
    FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
900
}                           \
901
VFP_OP(name, d)             \
902
{                           \
903
    FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
904
}
905
VFP_BINOP(add)
906
VFP_BINOP(sub)
907
VFP_BINOP(mul)
908
VFP_BINOP(div)
909
#undef VFP_BINOP
910

    
911
#define VFP_HELPER(name)  \
912
VFP_OP(name, s)           \
913
{                         \
914
    do_vfp_##name##s();    \
915
}                         \
916
VFP_OP(name, d)           \
917
{                         \
918
    do_vfp_##name##d();    \
919
}
920
VFP_HELPER(abs)
921
VFP_HELPER(sqrt)
922
VFP_HELPER(cmp)
923
VFP_HELPER(cmpe)
924
#undef VFP_HELPER
925

    
926
/* XXX: Will this do the right thing for NANs.  Should invert the signbit
927
   without looking at the rest of the value.  */
928
VFP_OP(neg, s)
929
{
930
    FT0s = float32_chs(FT0s);
931
}
932

    
933
VFP_OP(neg, d)
934
{
935
    FT0d = float64_chs(FT0d);
936
}
937

    
938
VFP_OP(F1_ld0, s)
939
{
940
    union {
941
        uint32_t i;
942
        float32 s;
943
    } v;
944
    v.i = 0;
945
    FT1s = v.s;
946
}
947

    
948
VFP_OP(F1_ld0, d)
949
{
950
    union {
951
        uint64_t i;
952
        float64 d;
953
    } v;
954
    v.i = 0;
955
    FT1d = v.d;
956
}
957

    
958
/* Helper routines to perform bitwise copies between float and int.  */
959
static inline float32 vfp_itos(uint32_t i)
960
{
961
    union {
962
        uint32_t i;
963
        float32 s;
964
    } v;
965

    
966
    v.i = i;
967
    return v.s;
968
}
969

    
970
static inline uint32_t vfp_stoi(float32 s)
971
{
972
    union {
973
        uint32_t i;
974
        float32 s;
975
    } v;
976

    
977
    v.s = s;
978
    return v.i;
979
}
980

    
981
/* Integer to float conversion.  */
982
VFP_OP(uito, s)
983
{
984
    FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
985
}
986

    
987
VFP_OP(uito, d)
988
{
989
    FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
990
}
991

    
992
VFP_OP(sito, s)
993
{
994
    FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
995
}
996

    
997
VFP_OP(sito, d)
998
{
999
    FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
1000
}
1001

    
1002
/* Float to integer conversion.  */
1003
VFP_OP(toui, s)
1004
{
1005
    FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
1006
}
1007

    
1008
VFP_OP(toui, d)
1009
{
1010
    FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
1011
}
1012

    
1013
VFP_OP(tosi, s)
1014
{
1015
    FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
1016
}
1017

    
1018
VFP_OP(tosi, d)
1019
{
1020
    FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
1021
}
1022

    
1023
/* TODO: Set rounding mode properly.  */
1024
VFP_OP(touiz, s)
1025
{
1026
    FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
1027
}
1028

    
1029
VFP_OP(touiz, d)
1030
{
1031
    FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
1032
}
1033

    
1034
VFP_OP(tosiz, s)
1035
{
1036
    FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
1037
}
1038

    
1039
VFP_OP(tosiz, d)
1040
{
1041
    FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
1042
}
1043

    
1044
/* floating point conversion */
1045
VFP_OP(fcvtd, s)
1046
{
1047
    FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
1048
}
1049

    
1050
VFP_OP(fcvts, d)
1051
{
1052
    FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
1053
}
1054

    
1055
/* Get and Put values from registers.  */
1056
VFP_OP(getreg_F0, d)
1057
{
1058
  FT0d = *(float64 *)((char *) env + PARAM1);
1059
}
1060

    
1061
VFP_OP(getreg_F0, s)
1062
{
1063
  FT0s = *(float32 *)((char *) env + PARAM1);
1064
}
1065

    
1066
VFP_OP(getreg_F1, d)
1067
{
1068
  FT1d = *(float64 *)((char *) env + PARAM1);
1069
}
1070

    
1071
VFP_OP(getreg_F1, s)
1072
{
1073
  FT1s = *(float32 *)((char *) env + PARAM1);
1074
}
1075

    
1076
VFP_OP(setreg_F0, d)
1077
{
1078
  *(float64 *)((char *) env + PARAM1) = FT0d;
1079
}
1080

    
1081
VFP_OP(setreg_F0, s)
1082
{
1083
  *(float32 *)((char *) env + PARAM1) = FT0s;
1084
}
1085

    
1086
void OPPROTO op_vfp_movl_T0_fpscr(void)
1087
{
1088
    do_vfp_get_fpscr ();
1089
}
1090

    
1091
void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1092
{
1093
    T0 = env->vfp.fpscr & (0xf << 28);
1094
}
1095

    
1096
void OPPROTO op_vfp_movl_fpscr_T0(void)
1097
{
1098
    do_vfp_set_fpscr();
1099
}
1100

    
1101
/* Move between FT0s to T0  */
1102
void OPPROTO op_vfp_mrs(void)
1103
{
1104
    T0 = vfp_stoi(FT0s);
1105
}
1106

    
1107
void OPPROTO op_vfp_msr(void)
1108
{
1109
    FT0s = vfp_itos(T0);
1110
}
1111

    
1112
/* Move between FT0d and {T0,T1} */
1113
void OPPROTO op_vfp_mrrd(void)
1114
{
1115
    CPU_DoubleU u;
1116
    
1117
    u.d = FT0d;
1118
    T0 = u.l.lower;
1119
    T1 = u.l.upper;
1120
}
1121

    
1122
void OPPROTO op_vfp_mdrr(void)
1123
{
1124
    CPU_DoubleU u;
1125
    
1126
    u.l.lower = T0;
1127
    u.l.upper = T1;
1128
    FT0d = u.d;
1129
}
1130

    
1131
/* Floating point load/store.  Address is in T1 */
1132
void OPPROTO op_vfp_lds(void)
1133
{
1134
    FT0s = ldfl((void *)T1);
1135
}
1136

    
1137
void OPPROTO op_vfp_ldd(void)
1138
{
1139
    FT0d = ldfq((void *)T1);
1140
}
1141

    
1142
void OPPROTO op_vfp_sts(void)
1143
{
1144
    stfl((void *)T1, FT0s);
1145
}
1146

    
1147
void OPPROTO op_vfp_std(void)
1148
{
1149
    stfq((void *)T1, FT0d);
1150
}