]> git.proxmox.com Git - qemu.git/blame - op-arm.c
update
[qemu.git] / op-arm.c
CommitLineData
5898e816
FB
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-arm.h"
21
22#define REGNAME r0
23#define REG (env->regs[0])
24#include "op-arm-template.h"
25
26#define REGNAME r1
27#define REG (env->regs[1])
28#include "op-arm-template.h"
29
30#define REGNAME r2
31#define REG (env->regs[2])
32#include "op-arm-template.h"
33
34#define REGNAME r3
35#define REG (env->regs[3])
36#include "op-arm-template.h"
37
38#define REGNAME r4
39#define REG (env->regs[4])
40#include "op-arm-template.h"
41
42#define REGNAME r5
43#define REG (env->regs[5])
44#include "op-arm-template.h"
45
46#define REGNAME r6
47#define REG (env->regs[6])
48#include "op-arm-template.h"
49
50#define REGNAME r7
51#define REG (env->regs[7])
52#include "op-arm-template.h"
53
54#define REGNAME r8
55#define REG (env->regs[8])
56#include "op-arm-template.h"
57
58#define REGNAME r9
59#define REG (env->regs[9])
60#include "op-arm-template.h"
61
62#define REGNAME r10
63#define REG (env->regs[10])
64#include "op-arm-template.h"
65
66#define REGNAME r11
67#define REG (env->regs[11])
68#include "op-arm-template.h"
69
70#define REGNAME r12
71#define REG (env->regs[12])
72#include "op-arm-template.h"
73
74#define REGNAME r13
75#define REG (env->regs[13])
76#include "op-arm-template.h"
77
78#define REGNAME r14
79#define REG (env->regs[14])
80#include "op-arm-template.h"
81
82#define REGNAME r15
83#define REG (env->regs[15])
84#include "op-arm-template.h"
85
86void OPPROTO op_movl_T0_0(void)
87{
88 T0 = 0;
89}
90
91void OPPROTO op_movl_T0_im(void)
92{
93 T0 = PARAM1;
94}
95
96void OPPROTO op_movl_T1_im(void)
97{
98 T1 = PARAM1;
99}
100
101void OPPROTO op_movl_T2_im(void)
102{
103 T2 = PARAM1;
104}
105
106void OPPROTO op_addl_T1_im(void)
107{
108 T1 += PARAM1;
109}
110
111void OPPROTO op_addl_T1_T2(void)
112{
113 T1 += T2;
114}
115
116void OPPROTO op_subl_T1_T2(void)
117{
118 T1 -= T2;
119}
120
121void OPPROTO op_addl_T0_T1(void)
122{
123 T0 += T1;
124}
125
126void 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
136void OPPROTO op_adcl_T0_T1(void)
137{
138 T0 += T1 + env->CF;
139}
140
141void 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, T0, T1) \
158 \
159void OPPROTO op_ ## sub ## l_T0_T1(void) \
160{ \
161 T0 -= T1; \
162} \
163 \
164void 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} \
173 \
174void OPPROTO op_ ## sbc ## l_T0_T1(void) \
175{ \
176 T0 = T0 - T1 + env->CF - 1; \
177} \
178 \
179void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \
180{ \
181 unsigned int src1; \
182 src1 = T0; \
183 if (!env->CF) { \
184 T0 = T0 - T1 - 1; \
185 T0 += T1; \
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 FORCE_RET(); \
194}
195
196OPSUB(sub, sbc, T0, T1)
197
198OPSUB(rsb, rsc, T1, T0)
199
200void OPPROTO op_andl_T0_T1(void)
201{
202 T0 &= T1;
203}
204
205void OPPROTO op_xorl_T0_T1(void)
206{
207 T0 ^= T1;
208}
209
210void OPPROTO op_orl_T0_T1(void)
211{
212 T0 |= T1;
213}
214
215void OPPROTO op_bicl_T0_T1(void)
216{
217 T0 &= ~T1;
218}
219
220void OPPROTO op_notl_T1(void)
221{
222 T1 = ~T1;
223}
224
225void OPPROTO op_logic_cc(void)
226{
227 env->NZF = T0;
228}
229
230#define EIP (env->regs[15])
231
232void OPPROTO op_test_eq(void)
233{
234 if (env->NZF == 0)
235 JUMP_TB(PARAM1, 0, PARAM2);
236 FORCE_RET();
237}
238
239void OPPROTO op_test_ne(void)
240{
241 if (env->NZF != 0)
242 JUMP_TB(PARAM1, 0, PARAM2);
243 FORCE_RET();
244}
245
246void OPPROTO op_test_cs(void)
247{
248 if (env->CF != 0)
249 JUMP_TB(PARAM1, 0, PARAM2);
250 FORCE_RET();
251}
252
253void OPPROTO op_test_cc(void)
254{
255 if (env->CF == 0)
256 JUMP_TB(PARAM1, 0, PARAM2);
257 FORCE_RET();
258}
259
260void OPPROTO op_test_mi(void)
261{
262 if ((env->NZF & 0x80000000) != 0)
263 JUMP_TB(PARAM1, 0, PARAM2);
264 FORCE_RET();
265}
266
267void OPPROTO op_test_pl(void)
268{
269 if ((env->NZF & 0x80000000) == 0)
270 JUMP_TB(PARAM1, 0, PARAM2);
271 FORCE_RET();
272}
273
274void OPPROTO op_test_vs(void)
275{
276 if ((env->VF & 0x80000000) != 0)
277 JUMP_TB(PARAM1, 0, PARAM2);
278 FORCE_RET();
279}
280
281void OPPROTO op_test_vc(void)
282{
283 if ((env->VF & 0x80000000) == 0)
284 JUMP_TB(PARAM1, 0, PARAM2);
285 FORCE_RET();
286}
287
288void OPPROTO op_test_hi(void)
289{
290 if (env->CF != 0 && env->NZF != 0)
291 JUMP_TB(PARAM1, 0, PARAM2);
292 FORCE_RET();
293}
294
295void OPPROTO op_test_ls(void)
296{
297 if (env->CF == 0 || env->NZF == 0)
298 JUMP_TB(PARAM1, 0, PARAM2);
299 FORCE_RET();
300}
301
302void OPPROTO op_test_ge(void)
303{
304 if (((env->VF ^ env->NZF) & 0x80000000) == 0)
305 JUMP_TB(PARAM1, 0, PARAM2);
306 FORCE_RET();
307}
308
309void OPPROTO op_test_lt(void)
310{
311 if (((env->VF ^ env->NZF) & 0x80000000) != 0)
312 JUMP_TB(PARAM1, 0, PARAM2);
313 FORCE_RET();
314}
315
316void OPPROTO op_test_gt(void)
317{
318 if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
319 JUMP_TB(PARAM1, 0, PARAM2);
320 FORCE_RET();
321}
322
323void OPPROTO op_test_le(void)
324{
325 if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
326 JUMP_TB(PARAM1, 0, PARAM2);
327 FORCE_RET();
328}
329
330void OPPROTO op_jmp(void)
331{
332 JUMP_TB(PARAM1, 1, PARAM2);
333}
334
335void OPPROTO op_movl_T0_psr(void)
336{
337 int ZF;
338 ZF = (env->NZF == 0);
339 T0 = env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
340 (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
341}
342
343/* NOTE: N = 1 and Z = 1 cannot be stored currently */
344void OPPROTO op_movl_psr_T0(void)
345{
346 unsigned int psr;
347 psr = T0;
348 env->CF = (psr >> 29) & 1;
349 env->NZF = (psr & 0xc0000000) ^ 0x40000000;
350 env->VF = (psr << 3) & 0x80000000;
351 /* for user mode we do not update other state info */
352}
353
354void OPPROTO op_mul_T0_T1(void)
355{
356 T0 = T0 * T1;
357}
358
359/* 64 bit unsigned mul */
360void OPPROTO op_mull_T0_T1(void)
361{
362 uint64_t res;
363 res = T0 * T1;
364 T1 = res >> 32;
365 T0 = res;
366}
367
368/* 64 bit signed mul */
369void OPPROTO op_imull_T0_T1(void)
370{
371 uint64_t res;
372 res = (int32_t)T0 * (int32_t)T1;
373 T1 = res >> 32;
374 T0 = res;
375}
376
377void OPPROTO op_addq_T0_T1(void)
378{
379 uint64_t res;
380 res = ((uint64_t)T1 << 32) | T0;
381 res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
382 T1 = res >> 32;
383 T0 = res;
384}
385
386void OPPROTO op_logicq_cc(void)
387{
388 env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
389}
390
391/* memory access */
392
393void OPPROTO op_ldub_T0_T1(void)
394{
395 T0 = ldub((void *)T1);
396}
397
398void OPPROTO op_ldsb_T0_T1(void)
399{
400 T0 = ldsb((void *)T1);
401}
402
403void OPPROTO op_lduw_T0_T1(void)
404{
405 T0 = lduw((void *)T1);
406}
407
408void OPPROTO op_ldsw_T0_T1(void)
409{
410 T0 = ldsw((void *)T1);
411}
412
413void OPPROTO op_ldl_T0_T1(void)
414{
415 T0 = ldl((void *)T1);
416}
417
418void OPPROTO op_stb_T0_T1(void)
419{
420 stb((void *)T1, T0);
421}
422
423void OPPROTO op_stw_T0_T1(void)
424{
425 stw((void *)T1, T0);
426}
427
428void OPPROTO op_stl_T0_T1(void)
429{
430 stl((void *)T1, T0);
431}
432
433void OPPROTO op_swpb_T0_T1(void)
434{
435 int tmp;
436
437 cpu_lock();
438 tmp = ldub((void *)T1);
439 stb((void *)T1, T0);
440 T0 = tmp;
441 cpu_unlock();
442}
443
444void OPPROTO op_swpl_T0_T1(void)
445{
446 int tmp;
447
448 cpu_lock();
449 tmp = ldl((void *)T1);
450 stl((void *)T1, T0);
451 T0 = tmp;
452 cpu_unlock();
453}
454
455/* shifts */
456
457/* T1 based */
458void OPPROTO op_shll_T1_im(void)
459{
460 T1 = T1 << PARAM1;
461}
462
463void OPPROTO op_shrl_T1_im(void)
464{
465 T1 = (uint32_t)T1 >> PARAM1;
466}
467
468void OPPROTO op_sarl_T1_im(void)
469{
470 T1 = (int32_t)T1 >> PARAM1;
471}
472
473void OPPROTO op_rorl_T1_im(void)
474{
475 int shift;
476 shift = PARAM1;
477 T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
478}
479
480/* T1 based, set C flag */
481void OPPROTO op_shll_T1_im_cc(void)
482{
483 env->CF = (T1 >> (32 - PARAM1)) & 1;
484 T1 = T1 << PARAM1;
485}
486
487void OPPROTO op_shrl_T1_im_cc(void)
488{
489 env->CF = (T1 >> (PARAM1 - 1)) & 1;
490 T1 = (uint32_t)T1 >> PARAM1;
491}
492
493void OPPROTO op_sarl_T1_im_cc(void)
494{
495 env->CF = (T1 >> (PARAM1 - 1)) & 1;
496 T1 = (int32_t)T1 >> PARAM1;
497}
498
499void OPPROTO op_rorl_T1_im_cc(void)
500{
501 int shift;
502 shift = PARAM1;
503 env->CF = (T1 >> (shift - 1)) & 1;
504 T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
505}
506
507/* T2 based */
508void OPPROTO op_shll_T2_im(void)
509{
510 T2 = T2 << PARAM1;
511}
512
513void OPPROTO op_shrl_T2_im(void)
514{
515 T2 = (uint32_t)T2 >> PARAM1;
516}
517
518void OPPROTO op_sarl_T2_im(void)
519{
520 T2 = (int32_t)T2 >> PARAM1;
521}
522
523void OPPROTO op_rorl_T2_im(void)
524{
525 int shift;
526 shift = PARAM1;
527 T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
528}
529
530/* T1 based, use T0 as shift count */
531
532void OPPROTO op_shll_T1_T0(void)
533{
534 int shift;
535 shift = T0 & 0xff;
536 if (shift >= 32)
537 T1 = 0;
538 else
539 T1 = T1 << shift;
540 FORCE_RET();
541}
542
543void OPPROTO op_shrl_T1_T0(void)
544{
545 int shift;
546 shift = T0 & 0xff;
547 if (shift >= 32)
548 T1 = 0;
549 else
550 T1 = (uint32_t)T1 >> shift;
551 FORCE_RET();
552}
553
554void OPPROTO op_sarl_T1_T0(void)
555{
556 int shift;
557 shift = T0 & 0xff;
558 if (shift >= 32)
559 shift = 31;
560 T1 = (int32_t)T1 >> shift;
561}
562
563void OPPROTO op_rorl_T1_T0(void)
564{
565 int shift;
566 shift = T0 & 0x1f;
567 if (shift) {
568 T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
569 }
570 FORCE_RET();
571}
572
573/* T1 based, use T0 as shift count and compute CF */
574
575void OPPROTO op_shll_T1_T0_cc(void)
576{
577 int shift;
578 shift = T0 & 0xff;
579 if (shift >= 32) {
580 if (shift == 32)
581 env->CF = T1 & 1;
582 else
583 env->CF = 0;
584 T1 = 0;
585 } else if (shift != 0) {
586 env->CF = (T1 >> (32 - shift)) & 1;
587 T1 = T1 << shift;
588 }
589 FORCE_RET();
590}
591
592void OPPROTO op_shrl_T1_T0_cc(void)
593{
594 int shift;
595 shift = T0 & 0xff;
596 if (shift >= 32) {
597 if (shift == 32)
598 env->CF = (T1 >> 31) & 1;
599 else
600 env->CF = 0;
601 T1 = 0;
602 } else if (shift != 0) {
603 env->CF = (T1 >> (shift - 1)) & 1;
604 T1 = (uint32_t)T1 >> shift;
605 }
606 FORCE_RET();
607}
608
609void OPPROTO op_sarl_T1_T0_cc(void)
610{
611 int shift;
612 shift = T0 & 0xff;
613 if (shift >= 32) {
614 env->CF = (T1 >> 31) & 1;
615 T1 = (int32_t)T1 >> 31;
616 } else {
617 env->CF = (T1 >> (shift - 1)) & 1;
618 T1 = (int32_t)T1 >> shift;
619 }
620 FORCE_RET();
621}
622
623void OPPROTO op_rorl_T1_T0_cc(void)
624{
625 int shift1, shift;
626 shift1 = T0 & 0xff;
627 shift = shift1 & 0x1f;
628 if (shift == 0) {
629 if (shift1 != 0)
630 env->CF = (T1 >> 31) & 1;
631 } else {
632 env->CF = (T1 >> (shift - 1)) & 1;
633 T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
634 }
635 FORCE_RET();
636}
637
638/* exceptions */
639
640void OPPROTO op_swi(void)
641{
642 env->exception_index = EXCP_SWI;
643 cpu_loop_exit();
644}
645
646void OPPROTO op_undef_insn(void)
647{
648 env->exception_index = EXCP_UDEF;
649 cpu_loop_exit();
650}
651
652/* thread support */
653
654spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
655
656void cpu_lock(void)
657{
658 spin_lock(&global_cpu_lock);
659}
660
661void cpu_unlock(void)
662{
663 spin_unlock(&global_cpu_lock);
664}
665