Statistics
| Branch: | Revision:

root / target-arm / op.c @ 2c0262af

History | View | Annotate | Download (12.6 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 = T0 * 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 = (int32_t)T0 * (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
void OPPROTO op_shll_T1_im(void)
467
{
468
    T1 = T1 << PARAM1;
469
}
470

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

    
476
void OPPROTO op_sarl_T1_im(void)
477
{
478
    T1 = (int32_t)T1 >> PARAM1;
479
}
480

    
481
void OPPROTO op_rorl_T1_im(void)
482
{
483
    int shift;
484
    shift = PARAM1;
485
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
486
}
487

    
488
/* T1 based, set C flag */
489
void OPPROTO op_shll_T1_im_cc(void)
490
{
491
    env->CF = (T1 >> (32 - PARAM1)) & 1;
492
    T1 = T1 << PARAM1;
493
}
494

    
495
void OPPROTO op_shrl_T1_im_cc(void)
496
{
497
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
498
    T1 = (uint32_t)T1 >> PARAM1;
499
}
500

    
501
void OPPROTO op_sarl_T1_im_cc(void)
502
{
503
    env->CF = (T1 >> (PARAM1 - 1)) & 1;
504
    T1 = (int32_t)T1 >> PARAM1;
505
}
506

    
507
void OPPROTO op_rorl_T1_im_cc(void)
508
{
509
    int shift;
510
    shift = PARAM1;
511
    env->CF = (T1 >> (shift - 1)) & 1;
512
    T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
513
}
514

    
515
/* T2 based */
516
void OPPROTO op_shll_T2_im(void)
517
{
518
    T2 = T2 << PARAM1;
519
}
520

    
521
void OPPROTO op_shrl_T2_im(void)
522
{
523
    T2 = (uint32_t)T2 >> PARAM1;
524
}
525

    
526
void OPPROTO op_sarl_T2_im(void)
527
{
528
    T2 = (int32_t)T2 >> PARAM1;
529
}
530

    
531
void OPPROTO op_rorl_T2_im(void)
532
{
533
    int shift;
534
    shift = PARAM1;
535
    T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
536
}
537

    
538
/* T1 based, use T0 as shift count */
539

    
540
void OPPROTO op_shll_T1_T0(void)
541
{
542
    int shift;
543
    shift = T0 & 0xff;
544
    if (shift >= 32)
545
        T1 = 0;
546
    else
547
        T1 = T1 << shift;
548
    FORCE_RET();
549
}
550

    
551
void OPPROTO op_shrl_T1_T0(void)
552
{
553
    int shift;
554
    shift = T0 & 0xff;
555
    if (shift >= 32)
556
        T1 = 0;
557
    else
558
        T1 = (uint32_t)T1 >> shift;
559
    FORCE_RET();
560
}
561

    
562
void OPPROTO op_sarl_T1_T0(void)
563
{
564
    int shift;
565
    shift = T0 & 0xff;
566
    if (shift >= 32)
567
        shift = 31;
568
    T1 = (int32_t)T1 >> shift;
569
}
570

    
571
void OPPROTO op_rorl_T1_T0(void)
572
{
573
    int shift;
574
    shift = T0 & 0x1f;
575
    if (shift) {
576
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
577
    }
578
    FORCE_RET();
579
}
580

    
581
/* T1 based, use T0 as shift count and compute CF */
582

    
583
void OPPROTO op_shll_T1_T0_cc(void)
584
{
585
    int shift;
586
    shift = T0 & 0xff;
587
    if (shift >= 32) {
588
        if (shift == 32)
589
            env->CF = T1 & 1;
590
        else
591
            env->CF = 0;
592
        T1 = 0;
593
    } else if (shift != 0) {
594
        env->CF = (T1 >> (32 - shift)) & 1;
595
        T1 = T1 << shift;
596
    }
597
    FORCE_RET();
598
}
599

    
600
void OPPROTO op_shrl_T1_T0_cc(void)
601
{
602
    int shift;
603
    shift = T0 & 0xff;
604
    if (shift >= 32) {
605
        if (shift == 32)
606
            env->CF = (T1 >> 31) & 1;
607
        else
608
            env->CF = 0;
609
        T1 = 0;
610
    } else if (shift != 0) {
611
        env->CF = (T1 >> (shift - 1)) & 1;
612
        T1 = (uint32_t)T1 >> shift;
613
    }
614
    FORCE_RET();
615
}
616

    
617
void OPPROTO op_sarl_T1_T0_cc(void)
618
{
619
    int shift;
620
    shift = T0 & 0xff;
621
    if (shift >= 32) {
622
        env->CF = (T1 >> 31) & 1;
623
        T1 = (int32_t)T1 >> 31;
624
    } else {
625
        env->CF = (T1 >> (shift - 1)) & 1;
626
        T1 = (int32_t)T1 >> shift;
627
    }
628
    FORCE_RET();
629
}
630

    
631
void OPPROTO op_rorl_T1_T0_cc(void)
632
{
633
    int shift1, shift;
634
    shift1 = T0 & 0xff;
635
    shift = shift1 & 0x1f;
636
    if (shift == 0) {
637
        if (shift1 != 0)
638
            env->CF = (T1 >> 31) & 1;
639
    } else {
640
        env->CF = (T1 >> (shift - 1)) & 1;
641
        T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
642
    }
643
    FORCE_RET();
644
}
645

    
646
/* exceptions */
647

    
648
void OPPROTO op_swi(void)
649
{
650
    env->exception_index = EXCP_SWI;
651
    cpu_loop_exit();
652
}
653

    
654
void OPPROTO op_undef_insn(void)
655
{
656
    env->exception_index = EXCP_UDEF;
657
    cpu_loop_exit();
658
}
659

    
660
/* thread support */
661

    
662
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
663

    
664
void cpu_lock(void)
665
{
666
    spin_lock(&global_cpu_lock);
667
}
668

    
669
void cpu_unlock(void)
670
{
671
    spin_unlock(&global_cpu_lock);
672
}
673