Statistics
| Branch: | Revision:

root / target-arm / op.c @ 977d5710

History | View | Annotate | Download (13.4 kB)

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

    
22
#define REGNAME r0
23
#define REG (env->regs[0])
24
#include "op_template.h"
25

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
82
#define REGNAME r15
83
#define REG (env->regs[15])
84
#include "op_template.h"
85

    
86
void OPPROTO op_movl_T0_0(void)
87
{
88
    T0 = 0;
89
}
90

    
91
void OPPROTO op_movl_T0_im(void)
92
{
93
    T0 = PARAM1;
94
}
95

    
96
void OPPROTO op_movl_T1_im(void)
97
{
98
    T1 = PARAM1;
99
}
100

    
101
void OPPROTO op_movl_T2_im(void)
102
{
103
    T2 = PARAM1;
104
}
105

    
106
void OPPROTO op_addl_T1_im(void)
107
{
108
    T1 += PARAM1;
109
}
110

    
111
void OPPROTO op_addl_T1_T2(void)
112
{
113
    T1 += T2;
114
}
115

    
116
void OPPROTO op_subl_T1_T2(void)
117
{
118
    T1 -= T2;
119
}
120

    
121
void OPPROTO op_addl_T0_T1(void)
122
{
123
    T0 += T1;
124
}
125

    
126
void OPPROTO op_addl_T0_T1_cc(void)
127
{
128
    unsigned int src1;
129
    src1 = T0;
130
    T0 += T1;
131
    env->NZF = T0;
132
    env->CF = T0 < src1;
133
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
134
}
135

    
136
void OPPROTO op_adcl_T0_T1(void)
137
{
138
    T0 += T1 + env->CF;
139
}
140

    
141
void OPPROTO op_adcl_T0_T1_cc(void)
142
{
143
    unsigned int src1;
144
    src1 = T0;
145
    if (!env->CF) {
146
        T0 += T1;
147
        env->CF = T0 < src1;
148
    } else {
149
        T0 += T1 + 1;
150
        env->CF = T0 <= src1;
151
    }
152
    env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
153
    env->NZF = T0;
154
    FORCE_RET();
155
}
156

    
157
#define OPSUB(sub, sbc, res, T0, T1)            \
158
                                                \
159
void OPPROTO op_ ## sub ## l_T0_T1(void)        \
160
{                                               \
161
    res = T0 - T1;                              \
162
}                                               \
163
                                                \
164
void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
165
{                                               \
166
    unsigned int src1;                          \
167
    src1 = T0;                                  \
168
    T0 -= T1;                                   \
169
    env->NZF = T0;                              \
170
    env->CF = src1 >= T1;                       \
171
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
172
    res = T0;                                   \
173
}                                               \
174
                                                \
175
void OPPROTO op_ ## sbc ## l_T0_T1(void)        \
176
{                                               \
177
    res = T0 - T1 + env->CF - 1;                \
178
}                                               \
179
                                                \
180
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
181
{                                               \
182
    unsigned int src1;                          \
183
    src1 = T0;                                  \
184
    if (!env->CF) {                             \
185
        T0 = T0 - T1 - 1;                       \
186
        env->CF = src1 >= T1;                   \
187
    } else {                                    \
188
        T0 = T0 - T1;                           \
189
        env->CF = src1 > T1;                    \
190
    }                                           \
191
    env->VF = (src1 ^ T1) & (src1 ^ T0);        \
192
    env->NZF = T0;                              \
193
    res = T0;                                   \
194
    FORCE_RET();                                \
195
}
196

    
197
OPSUB(sub, sbc, T0, T0, T1)
198

    
199
OPSUB(rsb, rsc, T0, T1, T0)
200

    
201
void OPPROTO op_andl_T0_T1(void)
202
{
203
    T0 &= T1;
204
}
205

    
206
void OPPROTO op_xorl_T0_T1(void)
207
{
208
    T0 ^= T1;
209
}
210

    
211
void OPPROTO op_orl_T0_T1(void)
212
{
213
    T0 |= T1;
214
}
215

    
216
void OPPROTO op_bicl_T0_T1(void)
217
{
218
    T0 &= ~T1;
219
}
220

    
221
void OPPROTO op_notl_T1(void)
222
{
223
    T1 = ~T1;
224
}
225

    
226
void OPPROTO op_logic_T0_cc(void)
227
{
228
    env->NZF = T0;
229
}
230

    
231
void OPPROTO op_logic_T1_cc(void)
232
{
233
    env->NZF = T1;
234
}
235

    
236
#define EIP (env->regs[15])
237

    
238
void OPPROTO op_test_eq(void)
239
{
240
    if (env->NZF == 0)
241
        JUMP_TB(op_test_eq, PARAM1, 0, PARAM2);
242
    FORCE_RET();
243
}
244

    
245
void OPPROTO op_test_ne(void)
246
{
247
    if (env->NZF != 0)
248
        JUMP_TB(op_test_ne, PARAM1, 0, PARAM2);
249
    FORCE_RET();
250
}
251

    
252
void OPPROTO op_test_cs(void)
253
{
254
    if (env->CF != 0)
255
        JUMP_TB(op_test_cs, PARAM1, 0, PARAM2);
256
    FORCE_RET();
257
}
258

    
259
void OPPROTO op_test_cc(void)
260
{
261
    if (env->CF == 0)
262
        JUMP_TB(op_test_cc, PARAM1, 0, PARAM2);
263
    FORCE_RET();
264
}
265

    
266
void OPPROTO op_test_mi(void)
267
{
268
    if ((env->NZF & 0x80000000) != 0)
269
        JUMP_TB(op_test_mi, PARAM1, 0, PARAM2);
270
    FORCE_RET();
271
}
272

    
273
void OPPROTO op_test_pl(void)
274
{
275
    if ((env->NZF & 0x80000000) == 0)
276
        JUMP_TB(op_test_pl, PARAM1, 0, PARAM2);
277
    FORCE_RET();
278
}
279

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

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

    
294
void OPPROTO op_test_hi(void)
295
{
296
    if (env->CF != 0 && env->NZF != 0)
297
        JUMP_TB(op_test_hi, PARAM1, 0, PARAM2);
298
    FORCE_RET();
299
}
300

    
301
void OPPROTO op_test_ls(void)
302
{
303
    if (env->CF == 0 || env->NZF == 0)
304
        JUMP_TB(op_test_ls, PARAM1, 0, PARAM2);
305
    FORCE_RET();
306
}
307

    
308
void OPPROTO op_test_ge(void)
309
{
310
    if (((env->VF ^ env->NZF) & 0x80000000) == 0)
311
        JUMP_TB(op_test_ge, PARAM1, 0, PARAM2);
312
    FORCE_RET();
313
}
314

    
315
void OPPROTO op_test_lt(void)
316
{
317
    if (((env->VF ^ env->NZF) & 0x80000000) != 0)
318
        JUMP_TB(op_test_lt, PARAM1, 0, PARAM2);
319
    FORCE_RET();
320
}
321

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

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

    
336
void OPPROTO op_jmp(void)
337
{
338
    JUMP_TB(op_jmp, PARAM1, 1, PARAM2);
339
}
340

    
341
void OPPROTO op_exit_tb(void)
342
{
343
    EXIT_TB();
344
}
345

    
346
void OPPROTO op_movl_T0_psr(void)
347
{
348
    T0 = compute_cpsr();
349
}
350

    
351
/* NOTE: N = 1 and Z = 1 cannot be stored currently */
352
void OPPROTO op_movl_psr_T0(void)
353
{
354
    unsigned int psr;
355
    psr = T0;
356
    env->CF = (psr >> 29) & 1;
357
    env->NZF = (psr & 0xc0000000) ^ 0x40000000;
358
    env->VF = (psr << 3) & 0x80000000;
359
    /* for user mode we do not update other state info */
360
}
361

    
362
void OPPROTO op_mul_T0_T1(void)
363
{
364
    T0 = T0 * T1;
365
}
366

    
367
/* 64 bit unsigned mul */
368
void OPPROTO op_mull_T0_T1(void)
369
{
370
    uint64_t res;
371
    res = (uint64_t)T0 * (uint64_t)T1;
372
    T1 = res >> 32;
373
    T0 = res;
374
}
375

    
376
/* 64 bit signed mul */
377
void OPPROTO op_imull_T0_T1(void)
378
{
379
    uint64_t res;
380
    res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
381
    T1 = res >> 32;
382
    T0 = res;
383
}
384

    
385
void OPPROTO op_addq_T0_T1(void)
386
{
387
    uint64_t res;
388
    res = ((uint64_t)T1 << 32) | T0;
389
    res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
390
    T1 = res >> 32;
391
    T0 = res;
392
}
393

    
394
void OPPROTO op_logicq_cc(void)
395
{
396
    env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
397
}
398

    
399
/* memory access */
400

    
401
void OPPROTO op_ldub_T0_T1(void)
402
{
403
    T0 = ldub((void *)T1);
404
}
405

    
406
void OPPROTO op_ldsb_T0_T1(void)
407
{
408
    T0 = ldsb((void *)T1);
409
}
410

    
411
void OPPROTO op_lduw_T0_T1(void)
412
{
413
    T0 = lduw((void *)T1);
414
}
415

    
416
void OPPROTO op_ldsw_T0_T1(void)
417
{
418
    T0 = ldsw((void *)T1);
419
}
420

    
421
void OPPROTO op_ldl_T0_T1(void)
422
{
423
    T0 = ldl((void *)T1);
424
}
425

    
426
void OPPROTO op_stb_T0_T1(void)
427
{
428
    stb((void *)T1, T0);
429
}
430

    
431
void OPPROTO op_stw_T0_T1(void)
432
{
433
    stw((void *)T1, T0);
434
}
435

    
436
void OPPROTO op_stl_T0_T1(void)
437
{
438
    stl((void *)T1, T0);
439
}
440

    
441
void OPPROTO op_swpb_T0_T1(void)
442
{
443
    int tmp;
444

    
445
    cpu_lock();
446
    tmp = ldub((void *)T1);
447
    stb((void *)T1, T0);
448
    T0 = tmp;
449
    cpu_unlock();
450
}
451

    
452
void OPPROTO op_swpl_T0_T1(void)
453
{
454
    int tmp;
455

    
456
    cpu_lock();
457
    tmp = ldl((void *)T1);
458
    stl((void *)T1, T0);
459
    T0 = tmp;
460
    cpu_unlock();
461
}
462

    
463
/* shifts */
464

    
465
/* T1 based */
466

    
467
void OPPROTO op_shll_T1_im(void)
468
{
469
    T1 = T1 << PARAM1;
470
}
471

    
472
void OPPROTO op_shrl_T1_im(void)
473
{
474
    T1 = (uint32_t)T1 >> PARAM1;
475
}
476

    
477
void OPPROTO op_shrl_T1_0(void)
478
{
479
    T1 = 0;
480
}
481

    
482
void OPPROTO op_sarl_T1_im(void)
483
{
484
    T1 = (int32_t)T1 >> PARAM1;
485
}
486

    
487
void OPPROTO op_sarl_T1_0(void)
488
{
489
    T1 = (int32_t)T1 >> 31;
490
}
491

    
492
void OPPROTO op_rorl_T1_im(void)
493
{
494
    int shift;
495
    shift = PARAM1;
496
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
497
}
498

    
499
void OPPROTO op_rrxl_T1(void)
500
{
501
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
502
}
503

    
504
/* T1 based, set C flag */
505
void OPPROTO op_shll_T1_im_cc(void)
506
{
507
    env->CF = (T1 >> (32 - PARAM1)) & 1;
508
    T1 = T1 << PARAM1;
509
}
510

    
511
void OPPROTO op_shrl_T1_im_cc(void)
512
{
513
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
514
    T1 = (uint32_t)T1 >> PARAM1;
515
}
516

    
517
void OPPROTO op_shrl_T1_0_cc(void)
518
{
519
    env->CF = (T1 >> 31) & 1;
520
    T1 = 0;
521
}
522

    
523
void OPPROTO op_sarl_T1_im_cc(void)
524
{
525
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
526
    T1 = (int32_t)T1 >> PARAM1;
527
}
528

    
529
void OPPROTO op_sarl_T1_0_cc(void)
530
{
531
    env->CF = (T1 >> 31) & 1;
532
    T1 = (int32_t)T1 >> 31;
533
}
534

    
535
void OPPROTO op_rorl_T1_im_cc(void)
536
{
537
    int shift;
538
    shift = PARAM1;
539
    env->CF = (T1 >> (shift - 1)) & 1;
540
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
541
}
542

    
543
void OPPROTO op_rrxl_T1_cc(void)
544
{
545
    uint32_t c;
546
    c = T1 & 1;
547
    T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
548
    env->CF = c;
549
}
550

    
551
/* T2 based */
552
void OPPROTO op_shll_T2_im(void)
553
{
554
    T2 = T2 << PARAM1;
555
}
556

    
557
void OPPROTO op_shrl_T2_im(void)
558
{
559
    T2 = (uint32_t)T2 >> PARAM1;
560
}
561

    
562
void OPPROTO op_shrl_T2_0(void)
563
{
564
    T2 = 0;
565
}
566

    
567
void OPPROTO op_sarl_T2_im(void)
568
{
569
    T2 = (int32_t)T2 >> PARAM1;
570
}
571

    
572
void OPPROTO op_sarl_T2_0(void)
573
{
574
    T2 = (int32_t)T2 >> 31;
575
}
576

    
577
void OPPROTO op_rorl_T2_im(void)
578
{
579
    int shift;
580
    shift = PARAM1;
581
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
582
}
583

    
584
void OPPROTO op_rrxl_T2(void)
585
{
586
    T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
587
}
588

    
589
/* T1 based, use T0 as shift count */
590

    
591
void OPPROTO op_shll_T1_T0(void)
592
{
593
    int shift;
594
    shift = T0 & 0xff;
595
    if (shift >= 32)
596
        T1 = 0;
597
    else
598
        T1 = T1 << shift;
599
    FORCE_RET();
600
}
601

    
602
void OPPROTO op_shrl_T1_T0(void)
603
{
604
    int shift;
605
    shift = T0 & 0xff;
606
    if (shift >= 32)
607
        T1 = 0;
608
    else
609
        T1 = (uint32_t)T1 >> shift;
610
    FORCE_RET();
611
}
612

    
613
void OPPROTO op_sarl_T1_T0(void)
614
{
615
    int shift;
616
    shift = T0 & 0xff;
617
    if (shift >= 32)
618
        shift = 31;
619
    T1 = (int32_t)T1 >> shift;
620
}
621

    
622
void OPPROTO op_rorl_T1_T0(void)
623
{
624
    int shift;
625
    shift = T0 & 0x1f;
626
    if (shift) {
627
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
628
    }
629
    FORCE_RET();
630
}
631

    
632
/* T1 based, use T0 as shift count and compute CF */
633

    
634
void OPPROTO op_shll_T1_T0_cc(void)
635
{
636
    int shift;
637
    shift = T0 & 0xff;
638
    if (shift >= 32) {
639
        if (shift == 32)
640
            env->CF = T1 & 1;
641
        else
642
            env->CF = 0;
643
        T1 = 0;
644
    } else if (shift != 0) {
645
        env->CF = (T1 >> (32 - shift)) & 1;
646
        T1 = T1 << shift;
647
    }
648
    FORCE_RET();
649
}
650

    
651
void OPPROTO op_shrl_T1_T0_cc(void)
652
{
653
    int shift;
654
    shift = T0 & 0xff;
655
    if (shift >= 32) {
656
        if (shift == 32)
657
            env->CF = (T1 >> 31) & 1;
658
        else
659
            env->CF = 0;
660
        T1 = 0;
661
    } else if (shift != 0) {
662
        env->CF = (T1 >> (shift - 1)) & 1;
663
        T1 = (uint32_t)T1 >> shift;
664
    }
665
    FORCE_RET();
666
}
667

    
668
void OPPROTO op_sarl_T1_T0_cc(void)
669
{
670
    int shift;
671
    shift = T0 & 0xff;
672
    if (shift >= 32) {
673
        env->CF = (T1 >> 31) & 1;
674
        T1 = (int32_t)T1 >> 31;
675
    } else {
676
        env->CF = (T1 >> (shift - 1)) & 1;
677
        T1 = (int32_t)T1 >> shift;
678
    }
679
    FORCE_RET();
680
}
681

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

    
697
/* exceptions */
698

    
699
void OPPROTO op_swi(void)
700
{
701
    env->exception_index = EXCP_SWI;
702
    cpu_loop_exit();
703
}
704

    
705
void OPPROTO op_undef_insn(void)
706
{
707
    env->exception_index = EXCP_UDEF;
708
    cpu_loop_exit();
709
}
710

    
711
/* thread support */
712

    
713
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
714

    
715
void cpu_lock(void)
716
{
717
    spin_lock(&global_cpu_lock);
718
}
719

    
720
void cpu_unlock(void)
721
{
722
    spin_unlock(&global_cpu_lock);
723
}
724