1 /* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 static ARMword
GetDPRegRHS (ARMul_State
* state
, ARMword instr
);
24 static ARMword
GetDPSRegRHS (ARMul_State
* state
, ARMword instr
);
25 static void WriteR15 (ARMul_State
* state
, ARMword src
);
26 static void WriteSR15 (ARMul_State
* state
, ARMword src
);
27 static void WriteR15Branch (ARMul_State
* state
, ARMword src
);
28 static ARMword
GetLSRegRHS (ARMul_State
* state
, ARMword instr
);
29 static ARMword
GetLS7RHS (ARMul_State
* state
, ARMword instr
);
30 static unsigned LoadWord (ARMul_State
* state
, ARMword instr
,
32 static unsigned LoadHalfWord (ARMul_State
* state
, ARMword instr
,
33 ARMword address
, int signextend
);
34 static unsigned LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
,
36 static unsigned StoreWord (ARMul_State
* state
, ARMword instr
,
38 static unsigned StoreHalfWord (ARMul_State
* state
, ARMword instr
,
40 static unsigned StoreByte (ARMul_State
* state
, ARMword instr
,
42 static void LoadMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
44 static void StoreMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
46 static void LoadSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
48 static void StoreSMult (ARMul_State
* state
, ARMword address
, ARMword instr
,
50 static unsigned Multiply64 (ARMul_State
* state
, ARMword instr
,
51 int signextend
, int scc
);
52 static unsigned MultiplyAdd64 (ARMul_State
* state
, ARMword instr
,
53 int signextend
, int scc
);
55 #define LUNSIGNED (0) /* unsigned operation */
56 #define LSIGNED (1) /* signed operation */
57 #define LDEFAULT (0) /* default : do nothing */
58 #define LSCC (1) /* set condition codes on result */
60 #ifdef NEED_UI_LOOP_HOOK
61 /* How often to run the ui_loop update, when in use */
62 #define UI_LOOP_POLL_INTERVAL 0x32000
64 /* Counter for the ui_loop_hook update */
65 static long ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
67 /* Actual hook to call to run through gdb's gui event loop */
68 extern int (*ui_loop_hook
) (int);
69 #endif /* NEED_UI_LOOP_HOOK */
71 extern int stop_simulator
;
73 /***************************************************************************\
74 * short-hand macros for LDR/STR *
75 \***************************************************************************/
77 /* store post decrement writeback */
80 if (StoreHalfWord(state, instr, lhs)) \
81 LSBase = lhs - GetLS7RHS(state, instr) ;
83 /* store post increment writeback */
86 if (StoreHalfWord(state, instr, lhs)) \
87 LSBase = lhs + GetLS7RHS(state, instr) ;
89 /* store pre decrement */
91 (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ;
93 /* store pre decrement writeback */
94 #define SHPREDOWNWB() \
95 temp = LHS - GetLS7RHS(state, instr) ; \
96 if (StoreHalfWord(state, instr, temp)) \
99 /* store pre increment */
101 (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ;
103 /* store pre increment writeback */
104 #define SHPREUPWB() \
105 temp = LHS + GetLS7RHS(state, instr) ; \
106 if (StoreHalfWord(state, instr, temp)) \
109 /* Load post decrement writeback. */
110 #define LHPOSTDOWN() \
114 temp = lhs - GetLS7RHS (state, instr); \
116 switch (BITS (5, 6)) \
119 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
123 if (LoadByte (state, instr, lhs, LSIGNED)) \
127 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
130 case 0: /* SWP handled elsewhere. */ \
139 /* Load post increment writeback. */
144 temp = lhs + GetLS7RHS (state, instr); \
146 switch (BITS (5, 6)) \
149 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
153 if (LoadByte (state, instr, lhs, LSIGNED)) \
157 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
160 case 0: /* SWP handled elsewhere. */ \
170 /* load pre decrement */
171 #define LHPREDOWN() \
174 temp = LHS - GetLS7RHS(state,instr) ; \
175 switch (BITS(5,6)) { \
177 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
180 (void)LoadByte(state,instr,temp,LSIGNED) ; \
183 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
185 case 0: /* SWP handled elsewhere */ \
194 /* load pre decrement writeback */
195 #define LHPREDOWNWB() \
198 temp = LHS - GetLS7RHS(state, instr) ; \
199 switch (BITS(5,6)) { \
201 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
205 if (LoadByte(state,instr,temp,LSIGNED)) \
209 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
212 case 0: /* SWP handled elsewhere */ \
221 /* load pre increment */
225 temp = LHS + GetLS7RHS(state,instr) ; \
226 switch (BITS(5,6)) { \
228 (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \
231 (void)LoadByte(state,instr,temp,LSIGNED) ; \
234 (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \
236 case 0: /* SWP handled elsewhere */ \
245 /* load pre increment writeback */
246 #define LHPREUPWB() \
249 temp = LHS + GetLS7RHS(state, instr) ; \
250 switch (BITS(5,6)) { \
252 if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \
256 if (LoadByte(state,instr,temp,LSIGNED)) \
260 if (LoadHalfWord(state,instr,temp,LSIGNED)) \
263 case 0: /* SWP handled elsewhere */ \
272 /***************************************************************************\
273 * EMULATION of ARM6 *
274 \***************************************************************************/
276 /* The PC pipeline value depends on whether ARM or Thumb instructions
277 are being executed: */
282 ARMul_Emulate32 (register ARMul_State
* state
)
286 ARMul_Emulate26 (register ARMul_State
* state
)
289 register ARMword instr
, /* the current instruction */
290 dest
= 0, /* almost the DestBus */
291 temp
, /* ubiquitous third hand */
292 pc
= 0; /* the address of the current instruction */
293 ARMword lhs
, rhs
; /* almost the ABus and BBus */
294 ARMword decoded
= 0, loaded
= 0; /* instruction pipeline */
296 /***************************************************************************\
297 * Execute the next instruction *
298 \***************************************************************************/
300 if (state
->NextInstr
< PRIMEPIPE
)
302 decoded
= state
->decoded
;
303 loaded
= state
->loaded
;
308 { /* just keep going */
310 switch (state
->NextInstr
)
313 state
->Reg
[15] += isize
; /* Advance the pipeline, and an S cycle */
317 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
321 state
->Reg
[15] += isize
; /* Advance the pipeline, and an N cycle */
325 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
330 pc
+= isize
; /* Program counter advanced, and an S cycle */
333 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
338 pc
+= isize
; /* Program counter advanced, and an N cycle */
341 loaded
= ARMul_LoadInstrN (state
, pc
+ (isize
* 2), isize
);
345 case RESUME
: /* The program counter has been changed */
350 state
->Reg
[15] = pc
+ (isize
* 2);
352 instr
= ARMul_ReLoadInstr (state
, pc
, isize
);
353 decoded
= ARMul_ReLoadInstr (state
, pc
+ isize
, isize
);
354 loaded
= ARMul_ReLoadInstr (state
, pc
+ isize
* 2, isize
);
358 default: /* The program counter has been changed */
363 state
->Reg
[15] = pc
+ (isize
* 2);
365 instr
= ARMul_LoadInstrN (state
, pc
, isize
);
366 decoded
= ARMul_LoadInstrS (state
, pc
+ (isize
), isize
);
367 loaded
= ARMul_LoadInstrS (state
, pc
+ (isize
* 2), isize
);
372 ARMul_EnvokeEvent (state
);
375 /* Enable this for a helpful bit of debugging when tracing is needed. */
376 fprintf (stderr
, "pc: %x, instr: %x\n", pc
& ~1, instr
);
381 if (state
->Exception
)
382 { /* Any exceptions */
383 if (state
->NresetSig
== LOW
)
385 ARMul_Abort (state
, ARMul_ResetV
);
388 else if (!state
->NfiqSig
&& !FFLAG
)
390 ARMul_Abort (state
, ARMul_FIQV
);
393 else if (!state
->NirqSig
&& !IFLAG
)
395 ARMul_Abort (state
, ARMul_IRQV
);
400 if (state
->CallDebug
> 0)
402 instr
= ARMul_Debug (state
, pc
, instr
);
403 if (state
->Emulate
< ONCE
)
405 state
->NextInstr
= RESUME
;
410 fprintf (stderr
, "At %08lx Instr %08lx Mode %02lx\n", pc
, instr
,
412 (void) fgetc (stdin
);
415 else if (state
->Emulate
< ONCE
)
417 state
->NextInstr
= RESUME
;
424 /* Provide Thumb instruction decoding. If the processor is in Thumb
425 mode, then we can simply decode the Thumb instruction, and map it
426 to the corresponding ARM instruction (by directly loading the
427 instr variable, and letting the normal ARM simulator
428 execute). There are some caveats to ensure that the correct
429 pipelined PC value is used when executing Thumb code, and also for
430 dealing with the BL instruction. */
432 { /* check if in Thumb mode */
434 switch (ARMul_ThumbDecode (state
, pc
, instr
, &new))
437 ARMul_UndefInstr (state
, instr
); /* This is a Thumb instruction */
440 case t_branch
: /* already processed */
443 case t_decoded
: /* ARM instruction available */
444 instr
= new; /* so continue instruction decoding */
450 /***************************************************************************\
451 * Check the condition codes *
452 \***************************************************************************/
453 if ((temp
= TOPBITS (28)) == AL
)
454 goto mainswitch
; /* vile deed in the need for speed */
456 switch ((int) TOPBITS (28))
457 { /* check the condition code */
464 if (BITS (25, 27) == 5) /* BLX(1) */
468 state
->Reg
[14] = pc
+ 4;
470 dest
= pc
+ 8 + 1; /* Force entry into Thumb mode. */
472 dest
+= (NEGBRANCH
+ (BIT (24) << 1));
474 dest
+= POSBRANCH
+ (BIT (24) << 1);
476 WriteR15Branch (state
, dest
);
479 else if ((instr
& 0xFC70F000) == 0xF450F000)
480 /* The PLD instruction. Ignored. */
483 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
484 ARMul_UndefInstr (state
, instr
);
513 temp
= (CFLAG
&& !ZFLAG
);
516 temp
= (!CFLAG
|| ZFLAG
);
519 temp
= ((!NFLAG
&& !VFLAG
) || (NFLAG
&& VFLAG
));
522 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
));
525 temp
= ((!NFLAG
&& !VFLAG
&& !ZFLAG
) || (NFLAG
&& VFLAG
&& !ZFLAG
));
528 temp
= ((NFLAG
&& !VFLAG
) || (!NFLAG
&& VFLAG
)) || ZFLAG
;
532 /***************************************************************************\
533 * Actual execution of instructions begins here *
534 \***************************************************************************/
537 { /* if the condition codes don't match, stop here */
540 if (state
->is_XScale
)
542 if (BIT (20) == 0 && BITS (25, 27) == 0)
544 if (BITS (4, 7) == 0xD)
546 /* XScale Load Consecutive insn. */
547 ARMword temp
= GetLS7RHS (state
, instr
);
548 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
549 ARMword addr
= BIT (24) ? temp2
: temp
;
552 ARMul_UndefInstr (state
, instr
);
554 /* Alignment violation. */
555 ARMul_Abort (state
, ARMul_DataAbortV
);
558 int wb
= BIT (24) && BIT (21);
560 state
->Reg
[BITS (12, 15)] =
561 ARMul_LoadWordN (state
, addr
);
562 state
->Reg
[BITS (12, 15) + 1] =
563 ARMul_LoadWordN (state
, addr
+ 4);
570 else if (BITS (4, 7) == 0xF)
572 /* XScale Store Consecutive insn. */
573 ARMword temp
= GetLS7RHS (state
, instr
);
574 ARMword temp2
= BIT (23) ? LHS
+ temp
: LHS
- temp
;
575 ARMword addr
= BIT (24) ? temp2
: temp
;
578 ARMul_UndefInstr (state
, instr
);
580 /* Alignment violation. */
581 ARMul_Abort (state
, ARMul_DataAbortV
);
584 ARMul_StoreWordN (state
, addr
,
585 state
->Reg
[BITS (12, 15)]);
586 ARMul_StoreWordN (state
, addr
+ 4,
587 state
->Reg
[BITS (12, 15) + 1]);
598 switch ((int) BITS (20, 27))
601 /***************************************************************************\
602 * Data Processing Register RHS Instructions *
603 \***************************************************************************/
605 case 0x00: /* AND reg and MUL */
607 if (BITS (4, 11) == 0xB)
609 /* STRH register offset, no write-back, down, post indexed */
613 /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */
615 if (BITS (4, 7) == 9)
617 rhs
= state
->Reg
[MULRHSReg
];
618 if (MULLHSReg
== MULDESTReg
)
621 state
->Reg
[MULDESTReg
] = 0;
623 else if (MULDESTReg
!= 15)
624 state
->Reg
[MULDESTReg
] = state
->Reg
[MULLHSReg
] * rhs
;
629 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
630 if (rhs
& (1L << dest
))
631 temp
= dest
; /* mult takes this many/2 I cycles */
632 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
642 case 0x01: /* ANDS reg and MULS */
644 if ((BITS (4, 11) & 0xF9) == 0x9)
646 /* LDR register offset, no write-back, down, post indexed */
648 /* fall through to rest of decoding */
651 if (BITS (4, 7) == 9)
653 rhs
= state
->Reg
[MULRHSReg
];
654 if (MULLHSReg
== MULDESTReg
)
657 state
->Reg
[MULDESTReg
] = 0;
661 else if (MULDESTReg
!= 15)
663 dest
= state
->Reg
[MULLHSReg
] * rhs
;
664 ARMul_NegZero (state
, dest
);
665 state
->Reg
[MULDESTReg
] = dest
;
671 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
672 if (rhs
& (1L << dest
))
673 temp
= dest
; /* mult takes this many/2 I cycles */
674 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
684 case 0x02: /* EOR reg and MLA */
686 if (BITS (4, 11) == 0xB)
688 /* STRH register offset, write-back, down, post indexed */
693 if (BITS (4, 7) == 9)
695 rhs
= state
->Reg
[MULRHSReg
];
696 if (MULLHSReg
== MULDESTReg
)
699 state
->Reg
[MULDESTReg
] = state
->Reg
[MULACCReg
];
701 else if (MULDESTReg
!= 15)
702 state
->Reg
[MULDESTReg
] =
703 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
708 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
709 if (rhs
& (1L << dest
))
710 temp
= dest
; /* mult takes this many/2 I cycles */
711 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
721 case 0x03: /* EORS reg and MLAS */
723 if ((BITS (4, 11) & 0xF9) == 0x9)
725 /* LDR register offset, write-back, down, post-indexed */
727 /* fall through to rest of the decoding */
730 if (BITS (4, 7) == 9)
732 rhs
= state
->Reg
[MULRHSReg
];
733 if (MULLHSReg
== MULDESTReg
)
736 dest
= state
->Reg
[MULACCReg
];
737 ARMul_NegZero (state
, dest
);
738 state
->Reg
[MULDESTReg
] = dest
;
740 else if (MULDESTReg
!= 15)
743 state
->Reg
[MULLHSReg
] * rhs
+ state
->Reg
[MULACCReg
];
744 ARMul_NegZero (state
, dest
);
745 state
->Reg
[MULDESTReg
] = dest
;
751 for (dest
= 0, temp
= 0; dest
< 32; dest
++)
752 if (rhs
& (1L << dest
))
753 temp
= dest
; /* mult takes this many/2 I cycles */
754 ARMul_Icycles (state
, ARMul_MultTable
[temp
], 0L);
764 case 0x04: /* SUB reg */
766 if (BITS (4, 7) == 0xB)
768 /* STRH immediate offset, no write-back, down, post indexed */
778 case 0x05: /* SUBS reg */
780 if ((BITS (4, 7) & 0x9) == 0x9)
782 /* LDR immediate offset, no write-back, down, post indexed */
784 /* fall through to the rest of the instruction decoding */
790 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
792 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
793 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
803 case 0x06: /* RSB reg */
805 if (BITS (4, 7) == 0xB)
807 /* STRH immediate offset, write-back, down, post indexed */
817 case 0x07: /* RSBS reg */
819 if ((BITS (4, 7) & 0x9) == 0x9)
821 /* LDR immediate offset, write-back, down, post indexed */
823 /* fall through to remainder of instruction decoding */
829 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
831 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
832 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
842 case 0x08: /* ADD reg */
844 if (BITS (4, 11) == 0xB)
846 /* STRH register offset, no write-back, up, post indexed */
852 if (BITS (4, 7) == 0x9)
855 ARMul_Icycles (state
,
856 Multiply64 (state
, instr
, LUNSIGNED
,
866 case 0x09: /* ADDS reg */
868 if ((BITS (4, 11) & 0xF9) == 0x9)
870 /* LDR register offset, no write-back, up, post indexed */
872 /* fall through to remaining instruction decoding */
876 if (BITS (4, 7) == 0x9)
879 ARMul_Icycles (state
,
880 Multiply64 (state
, instr
, LUNSIGNED
, LSCC
),
889 if ((lhs
| rhs
) >> 30)
890 { /* possible C,V,N to set */
891 ASSIGNN (NEG (dest
));
892 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
893 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
904 case 0x0a: /* ADC reg */
906 if (BITS (4, 11) == 0xB)
908 /* STRH register offset, write-back, up, post-indexed */
914 if (BITS (4, 7) == 0x9)
917 ARMul_Icycles (state
,
918 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
924 dest
= LHS
+ rhs
+ CFLAG
;
928 case 0x0b: /* ADCS reg */
930 if ((BITS (4, 11) & 0xF9) == 0x9)
932 /* LDR register offset, write-back, up, post indexed */
934 /* fall through to remaining instruction decoding */
938 if (BITS (4, 7) == 0x9)
941 ARMul_Icycles (state
,
942 MultiplyAdd64 (state
, instr
, LUNSIGNED
,
949 dest
= lhs
+ rhs
+ CFLAG
;
951 if ((lhs
| rhs
) >> 30)
952 { /* possible C,V,N to set */
953 ASSIGNN (NEG (dest
));
954 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
955 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
966 case 0x0c: /* SBC reg */
968 if (BITS (4, 7) == 0xB)
970 /* STRH immediate offset, no write-back, up post indexed */
976 if (BITS (4, 7) == 0x9)
979 ARMul_Icycles (state
,
980 Multiply64 (state
, instr
, LSIGNED
, LDEFAULT
),
986 dest
= LHS
- rhs
- !CFLAG
;
990 case 0x0d: /* SBCS reg */
992 if ((BITS (4, 7) & 0x9) == 0x9)
994 /* LDR immediate offset, no write-back, up, post indexed */
999 if (BITS (4, 7) == 0x9)
1002 ARMul_Icycles (state
,
1003 Multiply64 (state
, instr
, LSIGNED
, LSCC
),
1010 dest
= lhs
- rhs
- !CFLAG
;
1011 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1013 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1014 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1024 case 0x0e: /* RSC reg */
1026 if (BITS (4, 7) == 0xB)
1028 /* STRH immediate offset, write-back, up, post indexed */
1034 if (BITS (4, 7) == 0x9)
1037 ARMul_Icycles (state
,
1038 MultiplyAdd64 (state
, instr
, LSIGNED
,
1044 dest
= rhs
- LHS
- !CFLAG
;
1048 case 0x0f: /* RSCS reg */
1050 if ((BITS (4, 7) & 0x9) == 0x9)
1052 /* LDR immediate offset, write-back, up, post indexed */
1054 /* fall through to remaining instruction decoding */
1058 if (BITS (4, 7) == 0x9)
1061 ARMul_Icycles (state
,
1062 MultiplyAdd64 (state
, instr
, LSIGNED
, LSCC
),
1069 dest
= rhs
- lhs
- !CFLAG
;
1070 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1072 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1073 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1083 case 0x10: /* TST reg and MRS CPSR and SWP word */
1086 if (BIT (4) == 0 && BIT (7) == 1)
1088 /* ElSegundo SMLAxy insn. */
1089 ARMword op1
= state
->Reg
[BITS (0, 3)];
1090 ARMword op2
= state
->Reg
[BITS (8, 11)];
1091 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1105 if (AddOverflow (op1
, Rn
, op1
+ Rn
))
1107 state
->Reg
[BITS (16, 19)] = op1
+ Rn
;
1111 if (BITS (4, 11) == 5)
1113 /* ElSegundo QADD insn. */
1114 ARMword op1
= state
->Reg
[BITS (0, 3)];
1115 ARMword op2
= state
->Reg
[BITS (16, 19)];
1116 ARMword result
= op1
+ op2
;
1117 if (AddOverflow (op1
, op2
, result
))
1119 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1122 state
->Reg
[BITS (12, 15)] = result
;
1127 if (BITS (4, 11) == 0xB)
1129 /* STRH register offset, no write-back, down, pre indexed */
1134 if (BITS (4, 11) == 9)
1140 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1142 INTERNALABORT (temp
);
1143 (void) ARMul_LoadWordN (state
, temp
);
1144 (void) ARMul_LoadWordN (state
, temp
);
1148 dest
= ARMul_SwapWord (state
, temp
, state
->Reg
[RHSReg
]);
1150 DEST
= ARMul_Align (state
, temp
, dest
);
1153 if (state
->abortSig
|| state
->Aborted
)
1158 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1161 DEST
= ECC
| EINT
| EMODE
;
1169 case 0x11: /* TSTP reg */
1171 if ((BITS (4, 11) & 0xF9) == 0x9)
1173 /* LDR register offset, no write-back, down, pre indexed */
1175 /* continue with remaining instruction decode */
1181 state
->Cpsr
= GETSPSR (state
->Bank
);
1182 ARMul_CPSRAltered (state
);
1193 ARMul_NegZero (state
, dest
);
1197 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */
1200 if (BITS (4, 7) == 3)
1206 temp
= (pc
+ 2) | 1;
1210 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1211 state
->Reg
[14] = temp
;
1218 if (BIT (4) == 0 && BIT (7) == 1
1219 && (BIT (5) == 0 || BITS (12, 15) == 0))
1221 /* ElSegundo SMLAWy/SMULWy insn. */
1222 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1223 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1224 unsigned long long result
;
1228 if (op1
& 0x80000000)
1233 result
= (op1
* op2
) >> 16;
1237 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1239 if (AddOverflow (result
, Rn
, result
+ Rn
))
1243 state
->Reg
[BITS (16, 19)] = result
;
1247 if (BITS (4, 11) == 5)
1249 /* ElSegundo QSUB insn. */
1250 ARMword op1
= state
->Reg
[BITS (0, 3)];
1251 ARMword op2
= state
->Reg
[BITS (16, 19)];
1252 ARMword result
= op1
- op2
;
1254 if (SubOverflow (op1
, op2
, result
))
1256 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1260 state
->Reg
[BITS (12, 15)] = result
;
1265 if (BITS (4, 11) == 0xB)
1267 /* STRH register offset, write-back, down, pre indexed */
1271 if (BITS (4, 27) == 0x12FFF1)
1274 WriteR15Branch (state
, state
->Reg
[RHSReg
]);
1280 if (BITS (4, 7) == 0x7)
1283 extern int SWI_vector_installed
;
1285 /* Hardware is allowed to optionally override this
1286 instruction and treat it as a breakpoint. Since
1287 this is a simulator not hardware, we take the position
1288 that if a SWI vector was not installed, then an Abort
1289 vector was probably not installed either, and so
1290 normally this instruction would be ignored, even if an
1291 Abort is generated. This is a bad thing, since GDB
1292 uses this instruction for its breakpoints (at least in
1293 Thumb mode it does). So intercept the instruction here
1294 and generate a breakpoint SWI instead. */
1295 if (! SWI_vector_installed
)
1296 ARMul_OSHandleSWI (state
, SWI_Breakpoint
);
1299 /* BKPT - normally this will cause an abort, but for the
1300 XScale if bit 31 in register 10 of coprocessor 14 is
1301 clear, then this is treated as a no-op. */
1302 if (state
->is_XScale
)
1304 if (read_cp14_reg (10) & (1UL << 31))
1308 value
= read_cp14_reg (10);
1312 write_cp14_reg (10, value
);
1313 write_cp15_reg (5, 0, 0, 0x200); /* Set FSR. */
1314 write_cp15_reg (6, 0, 0, pc
); /* Set FAR. */
1320 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
1326 /* MSR reg to CPSR */
1330 /* Don't allow TBIT to be set by MSR. */
1333 ARMul_FixCPSR (state
, instr
, temp
);
1341 case 0x13: /* TEQP reg */
1343 if ((BITS (4, 11) & 0xF9) == 0x9)
1345 /* LDR register offset, write-back, down, pre indexed */
1347 /* continue with remaining instruction decode */
1353 state
->Cpsr
= GETSPSR (state
->Bank
);
1354 ARMul_CPSRAltered (state
);
1365 ARMul_NegZero (state
, dest
);
1369 case 0x14: /* CMP reg and MRS SPSR and SWP byte */
1372 if (BIT (4) == 0 && BIT (7) == 1)
1374 /* ElSegundo SMLALxy insn. */
1375 unsigned long long op1
= state
->Reg
[BITS (0, 3)];
1376 unsigned long long op2
= state
->Reg
[BITS (8, 11)];
1377 unsigned long long dest
;
1378 unsigned long long result
;
1391 dest
= (unsigned long long) state
->Reg
[BITS (16, 19)] << 32;
1392 dest
|= state
->Reg
[BITS (12, 15)];
1394 state
->Reg
[BITS (12, 15)] = dest
;
1395 state
->Reg
[BITS (16, 19)] = dest
>> 32;
1399 if (BITS (4, 11) == 5)
1401 /* ElSegundo QDADD insn. */
1402 ARMword op1
= state
->Reg
[BITS (0, 3)];
1403 ARMword op2
= state
->Reg
[BITS (16, 19)];
1404 ARMword op2d
= op2
+ op2
;
1407 if (AddOverflow (op2
, op2
, op2d
))
1410 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1413 result
= op1
+ op2d
;
1414 if (AddOverflow (op1
, op2d
, result
))
1417 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1420 state
->Reg
[BITS (12, 15)] = result
;
1425 if (BITS (4, 7) == 0xB)
1427 /* STRH immediate offset, no write-back, down, pre indexed */
1432 if (BITS (4, 11) == 9)
1438 if (VECTORACCESS (temp
) || ADDREXCEPT (temp
))
1440 INTERNALABORT (temp
);
1441 (void) ARMul_LoadByte (state
, temp
);
1442 (void) ARMul_LoadByte (state
, temp
);
1446 DEST
= ARMul_SwapByte (state
, temp
, state
->Reg
[RHSReg
]);
1447 if (state
->abortSig
|| state
->Aborted
)
1452 else if ((BITS (0, 11) == 0) && (LHSReg
== 15))
1455 DEST
= GETSPSR (state
->Bank
);
1463 case 0x15: /* CMPP reg */
1465 if ((BITS (4, 7) & 0x9) == 0x9)
1467 /* LDR immediate offset, no write-back, down, pre indexed */
1469 /* continue with remaining instruction decode */
1475 state
->Cpsr
= GETSPSR (state
->Bank
);
1476 ARMul_CPSRAltered (state
);
1488 ARMul_NegZero (state
, dest
);
1489 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1491 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1492 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1502 case 0x16: /* CMN reg and MSR reg to SPSR */
1505 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1507 /* ElSegundo SMULxy insn. */
1508 ARMword op1
= state
->Reg
[BITS (0, 3)];
1509 ARMword op2
= state
->Reg
[BITS (8, 11)];
1510 ARMword Rn
= state
->Reg
[BITS (12, 15)];
1523 state
->Reg
[BITS (16, 19)] = op1
* op2
;
1527 if (BITS (4, 11) == 5)
1529 /* ElSegundo QDSUB insn. */
1530 ARMword op1
= state
->Reg
[BITS (0, 3)];
1531 ARMword op2
= state
->Reg
[BITS (16, 19)];
1532 ARMword op2d
= op2
+ op2
;
1535 if (AddOverflow (op2
, op2
, op2d
))
1538 op2d
= POS (op2d
) ? 0x80000000 : 0x7fffffff;
1541 result
= op1
- op2d
;
1542 if (SubOverflow (op1
, op2d
, result
))
1545 result
= POS (result
) ? 0x80000000 : 0x7fffffff;
1548 state
->Reg
[BITS (12, 15)] = result
;
1555 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1557 /* ARM5 CLZ insn. */
1558 ARMword op1
= state
->Reg
[BITS (0, 3)];
1562 for (result
= 0; (op1
& 0x80000000) == 0; op1
<<= 1)
1565 state
->Reg
[BITS (12, 15)] = result
;
1570 if (BITS (4, 7) == 0xB)
1572 /* STRH immediate offset, write-back, down, pre indexed */
1580 ARMul_FixSPSR (state
, instr
, DPRegRHS
);
1588 case 0x17: /* CMNP reg */
1590 if ((BITS (4, 7) & 0x9) == 0x9)
1592 /* LDR immediate offset, write-back, down, pre indexed */
1594 /* continue with remaining instruction decoding */
1600 state
->Cpsr
= GETSPSR (state
->Bank
);
1601 ARMul_CPSRAltered (state
);
1614 ASSIGNZ (dest
== 0);
1615 if ((lhs
| rhs
) >> 30)
1616 { /* possible C,V,N to set */
1617 ASSIGNN (NEG (dest
));
1618 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1619 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1630 case 0x18: /* ORR reg */
1632 if (BITS (4, 11) == 0xB)
1634 /* STRH register offset, no write-back, up, pre indexed */
1644 case 0x19: /* ORRS reg */
1646 if ((BITS (4, 11) & 0xF9) == 0x9)
1648 /* LDR register offset, no write-back, up, pre indexed */
1650 /* continue with remaining instruction decoding */
1658 case 0x1a: /* MOV reg */
1660 if (BITS (4, 11) == 0xB)
1662 /* STRH register offset, write-back, up, pre indexed */
1671 case 0x1b: /* MOVS reg */
1673 if ((BITS (4, 11) & 0xF9) == 0x9)
1675 /* LDR register offset, write-back, up, pre indexed */
1677 /* continue with remaining instruction decoding */
1684 case 0x1c: /* BIC reg */
1686 if (BITS (4, 7) == 0xB)
1688 /* STRH immediate offset, no write-back, up, pre indexed */
1698 case 0x1d: /* BICS reg */
1700 if ((BITS (4, 7) & 0x9) == 0x9)
1702 /* LDR immediate offset, no write-back, up, pre indexed */
1704 /* continue with instruction decoding */
1712 case 0x1e: /* MVN reg */
1714 if (BITS (4, 7) == 0xB)
1716 /* STRH immediate offset, write-back, up, pre indexed */
1725 case 0x1f: /* MVNS reg */
1727 if ((BITS (4, 7) & 0x9) == 0x9)
1729 /* LDR immediate offset, write-back, up, pre indexed */
1731 /* continue instruction decoding */
1738 /***************************************************************************\
1739 * Data Processing Immediate RHS Instructions *
1740 \***************************************************************************/
1742 case 0x20: /* AND immed */
1743 dest
= LHS
& DPImmRHS
;
1747 case 0x21: /* ANDS immed */
1753 case 0x22: /* EOR immed */
1754 dest
= LHS
^ DPImmRHS
;
1758 case 0x23: /* EORS immed */
1764 case 0x24: /* SUB immed */
1765 dest
= LHS
- DPImmRHS
;
1769 case 0x25: /* SUBS immed */
1773 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1775 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1776 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1786 case 0x26: /* RSB immed */
1787 dest
= DPImmRHS
- LHS
;
1791 case 0x27: /* RSBS immed */
1795 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1797 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1798 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1808 case 0x28: /* ADD immed */
1809 dest
= LHS
+ DPImmRHS
;
1813 case 0x29: /* ADDS immed */
1817 ASSIGNZ (dest
== 0);
1818 if ((lhs
| rhs
) >> 30)
1819 { /* possible C,V,N to set */
1820 ASSIGNN (NEG (dest
));
1821 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1822 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1833 case 0x2a: /* ADC immed */
1834 dest
= LHS
+ DPImmRHS
+ CFLAG
;
1838 case 0x2b: /* ADCS immed */
1841 dest
= lhs
+ rhs
+ CFLAG
;
1842 ASSIGNZ (dest
== 0);
1843 if ((lhs
| rhs
) >> 30)
1844 { /* possible C,V,N to set */
1845 ASSIGNN (NEG (dest
));
1846 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
1847 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
1858 case 0x2c: /* SBC immed */
1859 dest
= LHS
- DPImmRHS
- !CFLAG
;
1863 case 0x2d: /* SBCS immed */
1866 dest
= lhs
- rhs
- !CFLAG
;
1867 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1869 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1870 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1880 case 0x2e: /* RSC immed */
1881 dest
= DPImmRHS
- LHS
- !CFLAG
;
1885 case 0x2f: /* RSCS immed */
1888 dest
= rhs
- lhs
- !CFLAG
;
1889 if ((rhs
>= lhs
) || ((rhs
| lhs
) >> 31))
1891 ARMul_SubCarry (state
, rhs
, lhs
, dest
);
1892 ARMul_SubOverflow (state
, rhs
, lhs
, dest
);
1902 case 0x30: /* TST immed */
1906 case 0x31: /* TSTP immed */
1910 state
->Cpsr
= GETSPSR (state
->Bank
);
1911 ARMul_CPSRAltered (state
);
1913 temp
= LHS
& DPImmRHS
;
1919 DPSImmRHS
; /* TST immed */
1921 ARMul_NegZero (state
, dest
);
1925 case 0x32: /* TEQ immed and MSR immed to CPSR */
1927 { /* MSR immed to CPSR */
1928 ARMul_FixCPSR (state
, instr
, DPImmRHS
);
1936 case 0x33: /* TEQP immed */
1940 state
->Cpsr
= GETSPSR (state
->Bank
);
1941 ARMul_CPSRAltered (state
);
1943 temp
= LHS
^ DPImmRHS
;
1949 DPSImmRHS
; /* TEQ immed */
1951 ARMul_NegZero (state
, dest
);
1955 case 0x34: /* CMP immed */
1959 case 0x35: /* CMPP immed */
1963 state
->Cpsr
= GETSPSR (state
->Bank
);
1964 ARMul_CPSRAltered (state
);
1966 temp
= LHS
- DPImmRHS
;
1973 lhs
= LHS
; /* CMP immed */
1976 ARMul_NegZero (state
, dest
);
1977 if ((lhs
>= rhs
) || ((rhs
| lhs
) >> 31))
1979 ARMul_SubCarry (state
, lhs
, rhs
, dest
);
1980 ARMul_SubOverflow (state
, lhs
, rhs
, dest
);
1990 case 0x36: /* CMN immed and MSR immed to SPSR */
1991 if (DESTReg
== 15) /* MSR */
1992 ARMul_FixSPSR (state
, instr
, DPImmRHS
);
1999 case 0x37: /* CMNP immed */
2003 state
->Cpsr
= GETSPSR (state
->Bank
);
2004 ARMul_CPSRAltered (state
);
2006 temp
= LHS
+ DPImmRHS
;
2013 lhs
= LHS
; /* CMN immed */
2016 ASSIGNZ (dest
== 0);
2017 if ((lhs
| rhs
) >> 30)
2018 { /* possible C,V,N to set */
2019 ASSIGNN (NEG (dest
));
2020 ARMul_AddCarry (state
, lhs
, rhs
, dest
);
2021 ARMul_AddOverflow (state
, lhs
, rhs
, dest
);
2032 case 0x38: /* ORR immed */
2033 dest
= LHS
| DPImmRHS
;
2037 case 0x39: /* ORRS immed */
2043 case 0x3a: /* MOV immed */
2048 case 0x3b: /* MOVS immed */
2053 case 0x3c: /* BIC immed */
2054 dest
= LHS
& ~DPImmRHS
;
2058 case 0x3d: /* BICS immed */
2064 case 0x3e: /* MVN immed */
2069 case 0x3f: /* MVNS immed */
2074 /***************************************************************************\
2075 * Single Data Transfer Immediate RHS Instructions *
2076 \***************************************************************************/
2078 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */
2080 if (StoreWord (state
, instr
, lhs
))
2081 LSBase
= lhs
- LSImmRHS
;
2084 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed */
2086 if (LoadWord (state
, instr
, lhs
))
2087 LSBase
= lhs
- LSImmRHS
;
2090 case 0x42: /* Store Word, WriteBack, Post Dec, Immed */
2091 UNDEF_LSRBaseEQDestWb
;
2094 temp
= lhs
- LSImmRHS
;
2095 state
->NtransSig
= LOW
;
2096 if (StoreWord (state
, instr
, lhs
))
2098 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2101 case 0x43: /* Load Word, WriteBack, Post Dec, Immed */
2102 UNDEF_LSRBaseEQDestWb
;
2105 state
->NtransSig
= LOW
;
2106 if (LoadWord (state
, instr
, lhs
))
2107 LSBase
= lhs
- LSImmRHS
;
2108 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2111 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed */
2113 if (StoreByte (state
, instr
, lhs
))
2114 LSBase
= lhs
- LSImmRHS
;
2117 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed */
2119 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2120 LSBase
= lhs
- LSImmRHS
;
2123 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed */
2124 UNDEF_LSRBaseEQDestWb
;
2127 state
->NtransSig
= LOW
;
2128 if (StoreByte (state
, instr
, lhs
))
2129 LSBase
= lhs
- LSImmRHS
;
2130 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2133 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed */
2134 UNDEF_LSRBaseEQDestWb
;
2137 state
->NtransSig
= LOW
;
2138 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2139 LSBase
= lhs
- LSImmRHS
;
2140 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2143 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed */
2145 if (StoreWord (state
, instr
, lhs
))
2146 LSBase
= lhs
+ LSImmRHS
;
2149 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed */
2151 if (LoadWord (state
, instr
, lhs
))
2152 LSBase
= lhs
+ LSImmRHS
;
2155 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed */
2156 UNDEF_LSRBaseEQDestWb
;
2159 state
->NtransSig
= LOW
;
2160 if (StoreWord (state
, instr
, lhs
))
2161 LSBase
= lhs
+ LSImmRHS
;
2162 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2165 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed */
2166 UNDEF_LSRBaseEQDestWb
;
2169 state
->NtransSig
= LOW
;
2170 if (LoadWord (state
, instr
, lhs
))
2171 LSBase
= lhs
+ LSImmRHS
;
2172 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2175 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed */
2177 if (StoreByte (state
, instr
, lhs
))
2178 LSBase
= lhs
+ LSImmRHS
;
2181 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed */
2183 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2184 LSBase
= lhs
+ LSImmRHS
;
2187 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed */
2188 UNDEF_LSRBaseEQDestWb
;
2191 state
->NtransSig
= LOW
;
2192 if (StoreByte (state
, instr
, lhs
))
2193 LSBase
= lhs
+ LSImmRHS
;
2194 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2197 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed */
2198 UNDEF_LSRBaseEQDestWb
;
2201 state
->NtransSig
= LOW
;
2202 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2203 LSBase
= lhs
+ LSImmRHS
;
2204 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2208 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed */
2209 (void) StoreWord (state
, instr
, LHS
- LSImmRHS
);
2212 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed */
2213 (void) LoadWord (state
, instr
, LHS
- LSImmRHS
);
2216 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed */
2217 UNDEF_LSRBaseEQDestWb
;
2219 temp
= LHS
- LSImmRHS
;
2220 if (StoreWord (state
, instr
, temp
))
2224 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed */
2225 UNDEF_LSRBaseEQDestWb
;
2227 temp
= LHS
- LSImmRHS
;
2228 if (LoadWord (state
, instr
, temp
))
2232 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed */
2233 (void) StoreByte (state
, instr
, LHS
- LSImmRHS
);
2236 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed */
2237 (void) LoadByte (state
, instr
, LHS
- LSImmRHS
, LUNSIGNED
);
2240 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed */
2241 UNDEF_LSRBaseEQDestWb
;
2243 temp
= LHS
- LSImmRHS
;
2244 if (StoreByte (state
, instr
, temp
))
2248 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed */
2249 UNDEF_LSRBaseEQDestWb
;
2251 temp
= LHS
- LSImmRHS
;
2252 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2256 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed */
2257 (void) StoreWord (state
, instr
, LHS
+ LSImmRHS
);
2260 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed */
2261 (void) LoadWord (state
, instr
, LHS
+ LSImmRHS
);
2264 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed */
2265 UNDEF_LSRBaseEQDestWb
;
2267 temp
= LHS
+ LSImmRHS
;
2268 if (StoreWord (state
, instr
, temp
))
2272 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed */
2273 UNDEF_LSRBaseEQDestWb
;
2275 temp
= LHS
+ LSImmRHS
;
2276 if (LoadWord (state
, instr
, temp
))
2280 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed */
2281 (void) StoreByte (state
, instr
, LHS
+ LSImmRHS
);
2284 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed */
2285 (void) LoadByte (state
, instr
, LHS
+ LSImmRHS
, LUNSIGNED
);
2288 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed */
2289 UNDEF_LSRBaseEQDestWb
;
2291 temp
= LHS
+ LSImmRHS
;
2292 if (StoreByte (state
, instr
, temp
))
2296 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed */
2297 UNDEF_LSRBaseEQDestWb
;
2299 temp
= LHS
+ LSImmRHS
;
2300 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2304 /***************************************************************************\
2305 * Single Data Transfer Register RHS Instructions *
2306 \***************************************************************************/
2308 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */
2311 ARMul_UndefInstr (state
, instr
);
2314 UNDEF_LSRBaseEQOffWb
;
2315 UNDEF_LSRBaseEQDestWb
;
2319 if (StoreWord (state
, instr
, lhs
))
2320 LSBase
= lhs
- LSRegRHS
;
2323 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg */
2326 ARMul_UndefInstr (state
, instr
);
2329 UNDEF_LSRBaseEQOffWb
;
2330 UNDEF_LSRBaseEQDestWb
;
2334 temp
= lhs
- LSRegRHS
;
2335 if (LoadWord (state
, instr
, lhs
))
2339 case 0x62: /* Store Word, WriteBack, Post Dec, Reg */
2342 ARMul_UndefInstr (state
, instr
);
2345 UNDEF_LSRBaseEQOffWb
;
2346 UNDEF_LSRBaseEQDestWb
;
2350 state
->NtransSig
= LOW
;
2351 if (StoreWord (state
, instr
, lhs
))
2352 LSBase
= lhs
- LSRegRHS
;
2353 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2356 case 0x63: /* Load Word, WriteBack, Post Dec, Reg */
2359 ARMul_UndefInstr (state
, instr
);
2362 UNDEF_LSRBaseEQOffWb
;
2363 UNDEF_LSRBaseEQDestWb
;
2367 temp
= lhs
- LSRegRHS
;
2368 state
->NtransSig
= LOW
;
2369 if (LoadWord (state
, instr
, lhs
))
2371 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2374 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg */
2377 ARMul_UndefInstr (state
, instr
);
2380 UNDEF_LSRBaseEQOffWb
;
2381 UNDEF_LSRBaseEQDestWb
;
2385 if (StoreByte (state
, instr
, lhs
))
2386 LSBase
= lhs
- LSRegRHS
;
2389 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg */
2392 ARMul_UndefInstr (state
, instr
);
2395 UNDEF_LSRBaseEQOffWb
;
2396 UNDEF_LSRBaseEQDestWb
;
2400 temp
= lhs
- LSRegRHS
;
2401 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2405 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg */
2408 ARMul_UndefInstr (state
, instr
);
2411 UNDEF_LSRBaseEQOffWb
;
2412 UNDEF_LSRBaseEQDestWb
;
2416 state
->NtransSig
= LOW
;
2417 if (StoreByte (state
, instr
, lhs
))
2418 LSBase
= lhs
- LSRegRHS
;
2419 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2422 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg */
2425 ARMul_UndefInstr (state
, instr
);
2428 UNDEF_LSRBaseEQOffWb
;
2429 UNDEF_LSRBaseEQDestWb
;
2433 temp
= lhs
- LSRegRHS
;
2434 state
->NtransSig
= LOW
;
2435 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2437 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2440 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg */
2443 ARMul_UndefInstr (state
, instr
);
2446 UNDEF_LSRBaseEQOffWb
;
2447 UNDEF_LSRBaseEQDestWb
;
2451 if (StoreWord (state
, instr
, lhs
))
2452 LSBase
= lhs
+ LSRegRHS
;
2455 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg */
2458 ARMul_UndefInstr (state
, instr
);
2461 UNDEF_LSRBaseEQOffWb
;
2462 UNDEF_LSRBaseEQDestWb
;
2466 temp
= lhs
+ LSRegRHS
;
2467 if (LoadWord (state
, instr
, lhs
))
2471 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg */
2474 ARMul_UndefInstr (state
, instr
);
2477 UNDEF_LSRBaseEQOffWb
;
2478 UNDEF_LSRBaseEQDestWb
;
2482 state
->NtransSig
= LOW
;
2483 if (StoreWord (state
, instr
, lhs
))
2484 LSBase
= lhs
+ LSRegRHS
;
2485 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2488 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg */
2491 ARMul_UndefInstr (state
, instr
);
2494 UNDEF_LSRBaseEQOffWb
;
2495 UNDEF_LSRBaseEQDestWb
;
2499 temp
= lhs
+ LSRegRHS
;
2500 state
->NtransSig
= LOW
;
2501 if (LoadWord (state
, instr
, lhs
))
2503 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2506 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg */
2509 ARMul_UndefInstr (state
, instr
);
2512 UNDEF_LSRBaseEQOffWb
;
2513 UNDEF_LSRBaseEQDestWb
;
2517 if (StoreByte (state
, instr
, lhs
))
2518 LSBase
= lhs
+ LSRegRHS
;
2521 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg */
2524 ARMul_UndefInstr (state
, instr
);
2527 UNDEF_LSRBaseEQOffWb
;
2528 UNDEF_LSRBaseEQDestWb
;
2532 temp
= lhs
+ LSRegRHS
;
2533 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2537 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg */
2540 ARMul_UndefInstr (state
, instr
);
2543 UNDEF_LSRBaseEQOffWb
;
2544 UNDEF_LSRBaseEQDestWb
;
2548 state
->NtransSig
= LOW
;
2549 if (StoreByte (state
, instr
, lhs
))
2550 LSBase
= lhs
+ LSRegRHS
;
2551 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2554 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg */
2557 ARMul_UndefInstr (state
, instr
);
2560 UNDEF_LSRBaseEQOffWb
;
2561 UNDEF_LSRBaseEQDestWb
;
2565 temp
= lhs
+ LSRegRHS
;
2566 state
->NtransSig
= LOW
;
2567 if (LoadByte (state
, instr
, lhs
, LUNSIGNED
))
2569 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
2573 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg */
2576 ARMul_UndefInstr (state
, instr
);
2579 (void) StoreWord (state
, instr
, LHS
- LSRegRHS
);
2582 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg */
2585 ARMul_UndefInstr (state
, instr
);
2588 (void) LoadWord (state
, instr
, LHS
- LSRegRHS
);
2591 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg */
2594 ARMul_UndefInstr (state
, instr
);
2597 UNDEF_LSRBaseEQOffWb
;
2598 UNDEF_LSRBaseEQDestWb
;
2601 temp
= LHS
- LSRegRHS
;
2602 if (StoreWord (state
, instr
, temp
))
2606 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg */
2609 ARMul_UndefInstr (state
, instr
);
2612 UNDEF_LSRBaseEQOffWb
;
2613 UNDEF_LSRBaseEQDestWb
;
2616 temp
= LHS
- LSRegRHS
;
2617 if (LoadWord (state
, instr
, temp
))
2621 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg */
2624 ARMul_UndefInstr (state
, instr
);
2627 (void) StoreByte (state
, instr
, LHS
- LSRegRHS
);
2630 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg */
2633 ARMul_UndefInstr (state
, instr
);
2636 (void) LoadByte (state
, instr
, LHS
- LSRegRHS
, LUNSIGNED
);
2639 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg */
2642 ARMul_UndefInstr (state
, instr
);
2645 UNDEF_LSRBaseEQOffWb
;
2646 UNDEF_LSRBaseEQDestWb
;
2649 temp
= LHS
- LSRegRHS
;
2650 if (StoreByte (state
, instr
, temp
))
2654 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg */
2657 ARMul_UndefInstr (state
, instr
);
2660 UNDEF_LSRBaseEQOffWb
;
2661 UNDEF_LSRBaseEQDestWb
;
2664 temp
= LHS
- LSRegRHS
;
2665 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2669 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg */
2672 ARMul_UndefInstr (state
, instr
);
2675 (void) StoreWord (state
, instr
, LHS
+ LSRegRHS
);
2678 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg */
2681 ARMul_UndefInstr (state
, instr
);
2684 (void) LoadWord (state
, instr
, LHS
+ LSRegRHS
);
2687 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg */
2690 ARMul_UndefInstr (state
, instr
);
2693 UNDEF_LSRBaseEQOffWb
;
2694 UNDEF_LSRBaseEQDestWb
;
2697 temp
= LHS
+ LSRegRHS
;
2698 if (StoreWord (state
, instr
, temp
))
2702 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg */
2705 ARMul_UndefInstr (state
, instr
);
2708 UNDEF_LSRBaseEQOffWb
;
2709 UNDEF_LSRBaseEQDestWb
;
2712 temp
= LHS
+ LSRegRHS
;
2713 if (LoadWord (state
, instr
, temp
))
2717 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg */
2720 ARMul_UndefInstr (state
, instr
);
2723 (void) StoreByte (state
, instr
, LHS
+ LSRegRHS
);
2726 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg */
2729 ARMul_UndefInstr (state
, instr
);
2732 (void) LoadByte (state
, instr
, LHS
+ LSRegRHS
, LUNSIGNED
);
2735 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg */
2738 ARMul_UndefInstr (state
, instr
);
2741 UNDEF_LSRBaseEQOffWb
;
2742 UNDEF_LSRBaseEQDestWb
;
2745 temp
= LHS
+ LSRegRHS
;
2746 if (StoreByte (state
, instr
, temp
))
2750 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg */
2753 /* Check for the special breakpoint opcode.
2754 This value should correspond to the value defined
2755 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2756 if (BITS (0, 19) == 0xfdefe)
2758 if (!ARMul_OSHandleSWI (state
, SWI_Breakpoint
))
2759 ARMul_Abort (state
, ARMul_SWIV
);
2762 ARMul_UndefInstr (state
, instr
);
2765 UNDEF_LSRBaseEQOffWb
;
2766 UNDEF_LSRBaseEQDestWb
;
2769 temp
= LHS
+ LSRegRHS
;
2770 if (LoadByte (state
, instr
, temp
, LUNSIGNED
))
2774 /***************************************************************************\
2775 * Multiple Data Transfer Instructions *
2776 \***************************************************************************/
2778 case 0x80: /* Store, No WriteBack, Post Dec */
2779 STOREMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2782 case 0x81: /* Load, No WriteBack, Post Dec */
2783 LOADMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2786 case 0x82: /* Store, WriteBack, Post Dec */
2787 temp
= LSBase
- LSMNumRegs
;
2788 STOREMULT (instr
, temp
+ 4L, temp
);
2791 case 0x83: /* Load, WriteBack, Post Dec */
2792 temp
= LSBase
- LSMNumRegs
;
2793 LOADMULT (instr
, temp
+ 4L, temp
);
2796 case 0x84: /* Store, Flags, No WriteBack, Post Dec */
2797 STORESMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2800 case 0x85: /* Load, Flags, No WriteBack, Post Dec */
2801 LOADSMULT (instr
, LSBase
- LSMNumRegs
+ 4L, 0L);
2804 case 0x86: /* Store, Flags, WriteBack, Post Dec */
2805 temp
= LSBase
- LSMNumRegs
;
2806 STORESMULT (instr
, temp
+ 4L, temp
);
2809 case 0x87: /* Load, Flags, WriteBack, Post Dec */
2810 temp
= LSBase
- LSMNumRegs
;
2811 LOADSMULT (instr
, temp
+ 4L, temp
);
2815 case 0x88: /* Store, No WriteBack, Post Inc */
2816 STOREMULT (instr
, LSBase
, 0L);
2819 case 0x89: /* Load, No WriteBack, Post Inc */
2820 LOADMULT (instr
, LSBase
, 0L);
2823 case 0x8a: /* Store, WriteBack, Post Inc */
2825 STOREMULT (instr
, temp
, temp
+ LSMNumRegs
);
2828 case 0x8b: /* Load, WriteBack, Post Inc */
2830 LOADMULT (instr
, temp
, temp
+ LSMNumRegs
);
2833 case 0x8c: /* Store, Flags, No WriteBack, Post Inc */
2834 STORESMULT (instr
, LSBase
, 0L);
2837 case 0x8d: /* Load, Flags, No WriteBack, Post Inc */
2838 LOADSMULT (instr
, LSBase
, 0L);
2841 case 0x8e: /* Store, Flags, WriteBack, Post Inc */
2843 STORESMULT (instr
, temp
, temp
+ LSMNumRegs
);
2846 case 0x8f: /* Load, Flags, WriteBack, Post Inc */
2848 LOADSMULT (instr
, temp
, temp
+ LSMNumRegs
);
2852 case 0x90: /* Store, No WriteBack, Pre Dec */
2853 STOREMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2856 case 0x91: /* Load, No WriteBack, Pre Dec */
2857 LOADMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2860 case 0x92: /* Store, WriteBack, Pre Dec */
2861 temp
= LSBase
- LSMNumRegs
;
2862 STOREMULT (instr
, temp
, temp
);
2865 case 0x93: /* Load, WriteBack, Pre Dec */
2866 temp
= LSBase
- LSMNumRegs
;
2867 LOADMULT (instr
, temp
, temp
);
2870 case 0x94: /* Store, Flags, No WriteBack, Pre Dec */
2871 STORESMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2874 case 0x95: /* Load, Flags, No WriteBack, Pre Dec */
2875 LOADSMULT (instr
, LSBase
- LSMNumRegs
, 0L);
2878 case 0x96: /* Store, Flags, WriteBack, Pre Dec */
2879 temp
= LSBase
- LSMNumRegs
;
2880 STORESMULT (instr
, temp
, temp
);
2883 case 0x97: /* Load, Flags, WriteBack, Pre Dec */
2884 temp
= LSBase
- LSMNumRegs
;
2885 LOADSMULT (instr
, temp
, temp
);
2889 case 0x98: /* Store, No WriteBack, Pre Inc */
2890 STOREMULT (instr
, LSBase
+ 4L, 0L);
2893 case 0x99: /* Load, No WriteBack, Pre Inc */
2894 LOADMULT (instr
, LSBase
+ 4L, 0L);
2897 case 0x9a: /* Store, WriteBack, Pre Inc */
2899 STOREMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2902 case 0x9b: /* Load, WriteBack, Pre Inc */
2904 LOADMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2907 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc */
2908 STORESMULT (instr
, LSBase
+ 4L, 0L);
2911 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc */
2912 LOADSMULT (instr
, LSBase
+ 4L, 0L);
2915 case 0x9e: /* Store, Flags, WriteBack, Pre Inc */
2917 STORESMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2920 case 0x9f: /* Load, Flags, WriteBack, Pre Inc */
2922 LOADSMULT (instr
, temp
+ 4L, temp
+ LSMNumRegs
);
2925 /***************************************************************************\
2927 \***************************************************************************/
2937 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2941 /***************************************************************************\
2943 \***************************************************************************/
2953 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2957 /***************************************************************************\
2958 * Branch and Link forward *
2959 \***************************************************************************/
2970 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2972 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2974 state
->Reg
[15] = pc
+ 8 + POSBRANCH
;
2978 /***************************************************************************\
2979 * Branch and Link backward *
2980 \***************************************************************************/
2991 state
->Reg
[14] = pc
+ 4; /* put PC into Link */
2993 state
->Reg
[14] = (pc
+ 4) | ECC
| ER15INT
| EMODE
; /* put PC into Link */
2995 state
->Reg
[15] = pc
+ 8 + NEGBRANCH
;
2999 /***************************************************************************\
3000 * Co-Processor Data Transfers *
3001 \***************************************************************************/
3004 if (state
->is_XScale
)
3006 if (BITS (4, 7) != 0x00)
3007 ARMul_UndefInstr (state
, instr
);
3009 if (BITS (8, 11) != 0x00)
3010 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3012 /* XScale MAR insn. Move two registers into accumulator. */
3013 if (BITS (0, 3) == 0x00)
3015 state
->Accumulator
= state
->Reg
[BITS (12, 15)];
3016 state
->Accumulator
+= (ARMdword
) state
->Reg
[BITS (16, 19)] << 32;
3019 /* Access to any other acc is unpredicatable. */
3024 case 0xc0: /* Store , No WriteBack , Post Dec */
3025 ARMul_STC (state
, instr
, LHS
);
3029 if (state
->is_XScale
)
3031 if (BITS (4, 7) != 0x00)
3032 ARMul_UndefInstr (state
, instr
);
3034 if (BITS (8, 11) != 0x00)
3035 ARMul_UndefInstr (state
, instr
); /* Not CP0. */
3037 /* XScale MRA insn. Move accumulator into two registers. */
3038 if (BITS (0, 3) == 0x00)
3040 ARMword t1
= (state
->Accumulator
>> 32) & 255;
3045 state
->Reg
[BITS (12, 15)] = state
->Accumulator
;
3046 state
->Reg
[BITS (16, 19)] = t1
;
3049 /* Access to any other acc is unpredicatable. */
3054 case 0xc1: /* Load , No WriteBack , Post Dec */
3055 ARMul_LDC (state
, instr
, LHS
);
3059 case 0xc6: /* Store , WriteBack , Post Dec */
3061 state
->Base
= lhs
- LSCOff
;
3062 ARMul_STC (state
, instr
, lhs
);
3066 case 0xc7: /* Load , WriteBack , Post Dec */
3068 state
->Base
= lhs
- LSCOff
;
3069 ARMul_LDC (state
, instr
, lhs
);
3073 case 0xcc: /* Store , No WriteBack , Post Inc */
3074 ARMul_STC (state
, instr
, LHS
);
3078 case 0xcd: /* Load , No WriteBack , Post Inc */
3079 ARMul_LDC (state
, instr
, LHS
);
3083 case 0xce: /* Store , WriteBack , Post Inc */
3085 state
->Base
= lhs
+ LSCOff
;
3086 ARMul_STC (state
, instr
, LHS
);
3090 case 0xcf: /* Load , WriteBack , Post Inc */
3092 state
->Base
= lhs
+ LSCOff
;
3093 ARMul_LDC (state
, instr
, LHS
);
3098 case 0xd4: /* Store , No WriteBack , Pre Dec */
3099 ARMul_STC (state
, instr
, LHS
- LSCOff
);
3103 case 0xd5: /* Load , No WriteBack , Pre Dec */
3104 ARMul_LDC (state
, instr
, LHS
- LSCOff
);
3108 case 0xd6: /* Store , WriteBack , Pre Dec */
3111 ARMul_STC (state
, instr
, lhs
);
3115 case 0xd7: /* Load , WriteBack , Pre Dec */
3118 ARMul_LDC (state
, instr
, lhs
);
3122 case 0xdc: /* Store , No WriteBack , Pre Inc */
3123 ARMul_STC (state
, instr
, LHS
+ LSCOff
);
3127 case 0xdd: /* Load , No WriteBack , Pre Inc */
3128 ARMul_LDC (state
, instr
, LHS
+ LSCOff
);
3132 case 0xde: /* Store , WriteBack , Pre Inc */
3135 ARMul_STC (state
, instr
, lhs
);
3139 case 0xdf: /* Load , WriteBack , Pre Inc */
3142 ARMul_LDC (state
, instr
, lhs
);
3145 /***************************************************************************\
3146 * Co-Processor Register Transfers (MCR) and Data Ops *
3147 \***************************************************************************/
3150 if (state
->is_XScale
)
3151 switch (BITS (18, 19))
3155 /* XScale MIA instruction. Signed multiplication of two 32 bit
3156 values and addition to 40 bit accumulator. */
3157 long long Rm
= state
->Reg
[MULLHSReg
];
3158 long long Rs
= state
->Reg
[MULACCReg
];
3164 state
->Accumulator
+= Rm
* Rs
;
3170 /* XScale MIAPH instruction. */
3171 ARMword t1
= state
->Reg
[MULLHSReg
] >> 16;
3172 ARMword t2
= state
->Reg
[MULACCReg
] >> 16;
3173 ARMword t3
= state
->Reg
[MULLHSReg
] & 0xffff;
3174 ARMword t4
= state
->Reg
[MULACCReg
] & 0xffff;
3189 state
->Accumulator
+= t5
;
3194 state
->Accumulator
+= t5
;
3200 /* XScale MIAxy instruction. */
3206 t1
= state
->Reg
[MULLHSReg
] >> 16;
3208 t1
= state
->Reg
[MULLHSReg
] & 0xffff;
3211 t2
= state
->Reg
[MULACCReg
] >> 16;
3213 t2
= state
->Reg
[MULACCReg
] & 0xffff;
3223 state
->Accumulator
+= t5
;
3245 ARMul_MCR (state
, instr
, state
->Reg
[15] + isize
);
3247 ARMul_MCR (state
, instr
, ECC
| ER15INT
| EMODE
|
3248 ((state
->Reg
[15] + isize
) & R15PCBITS
));
3252 ARMul_MCR (state
, instr
, DEST
);
3254 else /* CDP Part 1 */
3255 ARMul_CDP (state
, instr
);
3258 /***************************************************************************\
3259 * Co-Processor Register Transfers (MRC) and Data Ops *
3260 \***************************************************************************/
3272 temp
= ARMul_MRC (state
, instr
);
3275 ASSIGNN ((temp
& NBIT
) != 0);
3276 ASSIGNZ ((temp
& ZBIT
) != 0);
3277 ASSIGNC ((temp
& CBIT
) != 0);
3278 ASSIGNV ((temp
& VBIT
) != 0);
3283 else /* CDP Part 2 */
3284 ARMul_CDP (state
, instr
);
3287 /***************************************************************************\
3289 \***************************************************************************/
3307 if (instr
== ARMul_ABORTWORD
&& state
->AbortAddr
== pc
)
3308 { /* a prefetch abort */
3309 ARMul_Abort (state
, ARMul_PrefetchAbortV
);
3313 if (!ARMul_OSHandleSWI (state
, BITS (0, 23)))
3315 ARMul_Abort (state
, ARMul_SWIV
);
3318 } /* 256 way main switch */
3325 #ifdef NEED_UI_LOOP_HOOK
3326 if (ui_loop_hook
!= NULL
&& ui_loop_hook_counter
-- < 0)
3328 ui_loop_hook_counter
= UI_LOOP_POLL_INTERVAL
;
3331 #endif /* NEED_UI_LOOP_HOOK */
3333 if (state
->Emulate
== ONCE
)
3334 state
->Emulate
= STOP
;
3335 /* If we have changed mode, allow the PC to advance before stopping. */
3336 else if (state
->Emulate
== CHANGEMODE
)
3338 else if (state
->Emulate
!= RUN
)
3341 while (!stop_simulator
); /* do loop */
3343 state
->decoded
= decoded
;
3344 state
->loaded
= loaded
;
3348 } /* Emulate 26/32 in instruction based mode */
3351 /***************************************************************************\
3352 * This routine evaluates most Data Processing register RHS's with the S *
3353 * bit clear. It is intended to be called from the macro DPRegRHS, which *
3354 * filters the common case of an unshifted register with in line code *
3355 \***************************************************************************/
3358 GetDPRegRHS (ARMul_State
* state
, ARMword instr
)
3360 ARMword shamt
, base
;
3364 { /* shift amount in a register */
3369 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3372 base
= state
->Reg
[base
];
3373 ARMul_Icycles (state
, 1, 0L);
3374 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3375 switch ((int) BITS (5, 6))
3380 else if (shamt
>= 32)
3383 return (base
<< shamt
);
3387 else if (shamt
>= 32)
3390 return (base
>> shamt
);
3394 else if (shamt
>= 32)
3395 return ((ARMword
) ((long int) base
>> 31L));
3397 return ((ARMword
) ((long int) base
>> (int) shamt
));
3403 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3407 { /* shift amount is a constant */
3410 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3413 base
= state
->Reg
[base
];
3414 shamt
= BITS (7, 11);
3415 switch ((int) BITS (5, 6))
3418 return (base
<< shamt
);
3423 return (base
>> shamt
);
3426 return ((ARMword
) ((long int) base
>> 31L));
3428 return ((ARMword
) ((long int) base
>> (int) shamt
));
3430 if (shamt
== 0) /* its an RRX */
3431 return ((base
>> 1) | (CFLAG
<< 31));
3433 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3436 return (0); /* just to shut up lint */
3439 /***************************************************************************\
3440 * This routine evaluates most Logical Data Processing register RHS's *
3441 * with the S bit set. It is intended to be called from the macro *
3442 * DPSRegRHS, which filters the common case of an unshifted register *
3443 * with in line code *
3444 \***************************************************************************/
3447 GetDPSRegRHS (ARMul_State
* state
, ARMword instr
)
3449 ARMword shamt
, base
;
3453 { /* shift amount in a register */
3458 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3461 base
= state
->Reg
[base
];
3462 ARMul_Icycles (state
, 1, 0L);
3463 shamt
= state
->Reg
[BITS (8, 11)] & 0xff;
3464 switch ((int) BITS (5, 6))
3469 else if (shamt
== 32)
3474 else if (shamt
> 32)
3481 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3482 return (base
<< shamt
);
3487 else if (shamt
== 32)
3489 ASSIGNC (base
>> 31);
3492 else if (shamt
> 32)
3499 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3500 return (base
>> shamt
);
3505 else if (shamt
>= 32)
3507 ASSIGNC (base
>> 31L);
3508 return ((ARMword
) ((long int) base
>> 31L));
3512 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3513 return ((ARMword
) ((long int) base
>> (int) shamt
));
3521 ASSIGNC (base
>> 31);
3526 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3527 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3532 { /* shift amount is a constant */
3535 base
= ECC
| ER15INT
| R15PC
| EMODE
;
3538 base
= state
->Reg
[base
];
3539 shamt
= BITS (7, 11);
3540 switch ((int) BITS (5, 6))
3543 ASSIGNC ((base
>> (32 - shamt
)) & 1);
3544 return (base
<< shamt
);
3548 ASSIGNC (base
>> 31);
3553 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3554 return (base
>> shamt
);
3559 ASSIGNC (base
>> 31L);
3560 return ((ARMword
) ((long int) base
>> 31L));
3564 ASSIGNC ((ARMword
) ((long int) base
>> (int) (shamt
- 1)) & 1);
3565 return ((ARMword
) ((long int) base
>> (int) shamt
));
3572 return ((base
>> 1) | (shamt
<< 31));
3576 ASSIGNC ((base
>> (shamt
- 1)) & 1);
3577 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3581 return (0); /* just to shut up lint */
3584 /***************************************************************************\
3585 * This routine handles writes to register 15 when the S bit is not set. *
3586 \***************************************************************************/
3589 WriteR15 (ARMul_State
* state
, ARMword src
)
3591 /* The ARM documentation states that the two least significant bits
3592 are discarded when setting PC, except in the cases handled by
3593 WriteR15Branch() below. It's probably an oversight: in THUMB
3594 mode, the second least significant bit should probably not be
3603 state
->Reg
[15] = src
& PCBITS
;
3605 state
->Reg
[15] = (src
& R15PCBITS
) | ECC
| ER15INT
| EMODE
;
3606 ARMul_R15Altered (state
);
3611 /***************************************************************************\
3612 * This routine handles writes to register 15 when the S bit is set. *
3613 \***************************************************************************/
3616 WriteSR15 (ARMul_State
* state
, ARMword src
)
3619 if (state
->Bank
> 0)
3621 state
->Cpsr
= state
->Spsr
[state
->Bank
];
3622 ARMul_CPSRAltered (state
);
3630 state
->Reg
[15] = src
& PCBITS
;
3634 abort (); /* ARMul_R15Altered would have to support it. */
3638 if (state
->Bank
== USERBANK
)
3639 state
->Reg
[15] = (src
& (CCBITS
| R15PCBITS
)) | ER15INT
| EMODE
;
3641 state
->Reg
[15] = src
;
3642 ARMul_R15Altered (state
);
3647 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3648 will switch to Thumb mode if the least significant bit is set. */
3651 WriteR15Branch (ARMul_State
* state
, ARMword src
)
3657 state
->Reg
[15] = src
& 0xfffffffe;
3662 state
->Reg
[15] = src
& 0xfffffffc;
3666 WriteR15 (state
, src
);
3670 /***************************************************************************\
3671 * This routine evaluates most Load and Store register RHS's. It is *
3672 * intended to be called from the macro LSRegRHS, which filters the *
3673 * common case of an unshifted register with in line code *
3674 \***************************************************************************/
3677 GetLSRegRHS (ARMul_State
* state
, ARMword instr
)
3679 ARMword shamt
, base
;
3684 base
= ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but .... */
3687 base
= state
->Reg
[base
];
3689 shamt
= BITS (7, 11);
3690 switch ((int) BITS (5, 6))
3693 return (base
<< shamt
);
3698 return (base
>> shamt
);
3701 return ((ARMword
) ((long int) base
>> 31L));
3703 return ((ARMword
) ((long int) base
>> (int) shamt
));
3705 if (shamt
== 0) /* its an RRX */
3706 return ((base
>> 1) | (CFLAG
<< 31));
3708 return ((base
<< (32 - shamt
)) | (base
>> shamt
));
3710 return (0); /* just to shut up lint */
3713 /***************************************************************************\
3714 * This routine evaluates the ARM7T halfword and signed transfer RHS's. *
3715 \***************************************************************************/
3718 GetLS7RHS (ARMul_State
* state
, ARMword instr
)
3724 return ECC
| ER15INT
| R15PC
| EMODE
; /* Now forbidden, but ... */
3726 return state
->Reg
[RHSReg
];
3729 /* else immediate */
3730 return BITS (0, 3) | (BITS (8, 11) << 4);
3733 /***************************************************************************\
3734 * This function does the work of loading a word for a LDR instruction. *
3735 \***************************************************************************/
3738 LoadWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3744 if (ADDREXCEPT (address
))
3746 INTERNALABORT (address
);
3749 dest
= ARMul_LoadWordN (state
, address
);
3753 return (state
->lateabtSig
);
3756 dest
= ARMul_Align (state
, address
, dest
);
3758 ARMul_Icycles (state
, 1, 0L);
3760 return (DESTReg
!= LHSReg
);
3764 /***************************************************************************\
3765 * This function does the work of loading a halfword. *
3766 \***************************************************************************/
3769 LoadHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
,
3776 if (ADDREXCEPT (address
))
3778 INTERNALABORT (address
);
3781 dest
= ARMul_LoadHalfWord (state
, address
);
3785 return (state
->lateabtSig
);
3790 if (dest
& 1 << (16 - 1))
3791 dest
= (dest
& ((1 << 16) - 1)) - (1 << 16);
3794 ARMul_Icycles (state
, 1, 0L);
3795 return (DESTReg
!= LHSReg
);
3800 /***************************************************************************\
3801 * This function does the work of loading a byte for a LDRB instruction. *
3802 \***************************************************************************/
3805 LoadByte (ARMul_State
* state
, ARMword instr
, ARMword address
, int signextend
)
3811 if (ADDREXCEPT (address
))
3813 INTERNALABORT (address
);
3816 dest
= ARMul_LoadByte (state
, address
);
3820 return (state
->lateabtSig
);
3825 if (dest
& 1 << (8 - 1))
3826 dest
= (dest
& ((1 << 8) - 1)) - (1 << 8);
3829 ARMul_Icycles (state
, 1, 0L);
3830 return (DESTReg
!= LHSReg
);
3833 /***************************************************************************\
3834 * This function does the work of storing a word from a STR instruction. *
3835 \***************************************************************************/
3838 StoreWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3843 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3846 ARMul_StoreWordN (state
, address
, DEST
);
3848 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3850 INTERNALABORT (address
);
3851 (void) ARMul_LoadWordN (state
, address
);
3854 ARMul_StoreWordN (state
, address
, DEST
);
3859 return (state
->lateabtSig
);
3865 /***************************************************************************\
3866 * This function does the work of storing a byte for a STRH instruction. *
3867 \***************************************************************************/
3870 StoreHalfWord (ARMul_State
* state
, ARMword instr
, ARMword address
)
3876 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3880 ARMul_StoreHalfWord (state
, address
, DEST
);
3882 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3884 INTERNALABORT (address
);
3885 (void) ARMul_LoadHalfWord (state
, address
);
3888 ARMul_StoreHalfWord (state
, address
, DEST
);
3894 return (state
->lateabtSig
);
3902 /***************************************************************************\
3903 * This function does the work of storing a byte for a STRB instruction. *
3904 \***************************************************************************/
3907 StoreByte (ARMul_State
* state
, ARMword instr
, ARMword address
)
3912 state
->Reg
[15] = ECC
| ER15INT
| R15PC
| EMODE
;
3915 ARMul_StoreByte (state
, address
, DEST
);
3917 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
3919 INTERNALABORT (address
);
3920 (void) ARMul_LoadByte (state
, address
);
3923 ARMul_StoreByte (state
, address
, DEST
);
3928 return (state
->lateabtSig
);
3934 /***************************************************************************\
3935 * This function does the work of loading the registers listed in an LDM *
3936 * instruction, when the S bit is clear. The code here is always increment *
3937 * after, it's up to the caller to get the input address correct and to *
3938 * handle base register modification. *
3939 \***************************************************************************/
3942 LoadMult (ARMul_State
* state
, ARMword instr
, ARMword address
, ARMword WBBase
)
3948 UNDEF_LSMBaseInListWb
;
3951 if (ADDREXCEPT (address
))
3953 INTERNALABORT (address
);
3956 if (BIT (21) && LHSReg
!= 15)
3959 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
3960 dest
= ARMul_LoadWordN (state
, address
);
3961 if (!state
->abortSig
&& !state
->Aborted
)
3962 state
->Reg
[temp
++] = dest
;
3963 else if (!state
->Aborted
)
3964 state
->Aborted
= ARMul_DataAbortV
;
3966 for (; temp
< 16; temp
++) /* S cycles from here on */
3968 { /* load this register */
3970 dest
= ARMul_LoadWordS (state
, address
);
3971 if (!state
->abortSig
&& !state
->Aborted
)
3972 state
->Reg
[temp
] = dest
;
3973 else if (!state
->Aborted
)
3974 state
->Aborted
= ARMul_DataAbortV
;
3977 if (BIT (15) && !state
->Aborted
)
3978 { /* PC is in the reg list */
3979 WriteR15Branch(state
, PC
);
3982 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
3986 if (BIT (21) && LHSReg
!= 15)
3992 /***************************************************************************\
3993 * This function does the work of loading the registers listed in an LDM *
3994 * instruction, when the S bit is set. The code here is always increment *
3995 * after, it's up to the caller to get the input address correct and to *
3996 * handle base register modification. *
3997 \***************************************************************************/
4000 LoadSMult (ARMul_State
* state
, ARMword instr
,
4001 ARMword address
, ARMword WBBase
)
4007 UNDEF_LSMBaseInListWb
;
4010 if (ADDREXCEPT (address
))
4012 INTERNALABORT (address
);
4016 if (!BIT (15) && state
->Bank
!= USERBANK
)
4018 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* temporary reg bank switch */
4019 UNDEF_LSMUserBankWb
;
4022 if (BIT (21) && LHSReg
!= 15)
4025 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4026 dest
= ARMul_LoadWordN (state
, address
);
4027 if (!state
->abortSig
)
4028 state
->Reg
[temp
++] = dest
;
4029 else if (!state
->Aborted
)
4030 state
->Aborted
= ARMul_DataAbortV
;
4032 for (; temp
< 16; temp
++) /* S cycles from here on */
4034 { /* load this register */
4036 dest
= ARMul_LoadWordS (state
, address
);
4037 if (!state
->abortSig
&& !state
->Aborted
)
4038 state
->Reg
[temp
] = dest
;
4039 else if (!state
->Aborted
)
4040 state
->Aborted
= ARMul_DataAbortV
;
4043 if (BIT (15) && !state
->Aborted
)
4044 { /* PC is in the reg list */
4046 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4048 state
->Cpsr
= GETSPSR (state
->Bank
);
4049 ARMul_CPSRAltered (state
);
4051 WriteR15 (state
, PC
);
4053 if (state
->Mode
== USER26MODE
|| state
->Mode
== USER32MODE
)
4054 { /* protect bits in user mode */
4055 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
4056 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
4057 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
4058 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
4061 ARMul_R15Altered (state
);
4066 if (!BIT (15) && state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4067 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4069 ARMul_Icycles (state
, 1, 0L); /* to write back the final register */
4073 if (BIT (21) && LHSReg
!= 15)
4080 /***************************************************************************\
4081 * This function does the work of storing the registers listed in an STM *
4082 * instruction, when the S bit is clear. The code here is always increment *
4083 * after, it's up to the caller to get the input address correct and to *
4084 * handle base register modification. *
4085 \***************************************************************************/
4088 StoreMult (ARMul_State
* state
, ARMword instr
,
4089 ARMword address
, ARMword WBBase
)
4095 UNDEF_LSMBaseInListWb
;
4098 BUSUSEDINCPCN
; /* N-cycle, increment the PC and update the NextInstr state */
4102 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4104 INTERNALABORT (address
);
4110 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4112 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4116 (void) ARMul_LoadWordN (state
, address
);
4117 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4119 { /* save this register */
4121 (void) ARMul_LoadWordS (state
, address
);
4123 if (BIT (21) && LHSReg
!= 15)
4129 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4131 if (state
->abortSig
&& !state
->Aborted
)
4132 state
->Aborted
= ARMul_DataAbortV
;
4134 if (BIT (21) && LHSReg
!= 15)
4137 for (; temp
< 16; temp
++) /* S cycles from here on */
4139 { /* save this register */
4141 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4142 if (state
->abortSig
&& !state
->Aborted
)
4143 state
->Aborted
= ARMul_DataAbortV
;
4151 /***************************************************************************\
4152 * This function does the work of storing the registers listed in an STM *
4153 * instruction when the S bit is set. The code here is always increment *
4154 * after, it's up to the caller to get the input address correct and to *
4155 * handle base register modification. *
4156 \***************************************************************************/
4159 StoreSMult (ARMul_State
* state
, ARMword instr
,
4160 ARMword address
, ARMword WBBase
)
4166 UNDEF_LSMBaseInListWb
;
4169 if (VECTORACCESS (address
) || ADDREXCEPT (address
))
4171 INTERNALABORT (address
);
4177 if (state
->Bank
!= USERBANK
)
4179 (void) ARMul_SwitchMode (state
, state
->Mode
, USER26MODE
); /* Force User Bank */
4180 UNDEF_LSMUserBankWb
;
4183 for (temp
= 0; !BIT (temp
); temp
++); /* N cycle first */
4185 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4189 (void) ARMul_LoadWordN (state
, address
);
4190 for (; temp
< 16; temp
++) /* Fake the Stores as Loads */
4192 { /* save this register */
4194 (void) ARMul_LoadWordS (state
, address
);
4196 if (BIT (21) && LHSReg
!= 15)
4202 ARMul_StoreWordN (state
, address
, state
->Reg
[temp
++]);
4204 if (state
->abortSig
&& !state
->Aborted
)
4205 state
->Aborted
= ARMul_DataAbortV
;
4207 if (BIT (21) && LHSReg
!= 15)
4210 for (; temp
< 16; temp
++) /* S cycles from here on */
4212 { /* save this register */
4214 ARMul_StoreWordS (state
, address
, state
->Reg
[temp
]);
4215 if (state
->abortSig
&& !state
->Aborted
)
4216 state
->Aborted
= ARMul_DataAbortV
;
4219 if (state
->Mode
!= USER26MODE
&& state
->Mode
!= USER32MODE
)
4220 (void) ARMul_SwitchMode (state
, USER26MODE
, state
->Mode
); /* restore the correct bank */
4228 /***************************************************************************\
4229 * This function does the work of adding two 32bit values together, and *
4230 * calculating if a carry has occurred. *
4231 \***************************************************************************/
4234 Add32 (ARMword a1
, ARMword a2
, int *carry
)
4236 ARMword result
= (a1
+ a2
);
4237 unsigned int uresult
= (unsigned int) result
;
4238 unsigned int ua1
= (unsigned int) a1
;
4240 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4241 or (result > RdLo) then we have no carry: */
4242 if ((uresult
== ua1
) ? (a2
!= 0) : (uresult
< ua1
))
4250 /***************************************************************************\
4251 * This function does the work of multiplying two 32bit values to give a *
4253 \***************************************************************************/
4256 Multiply64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4258 int nRdHi
, nRdLo
, nRs
, nRm
; /* operand register numbers */
4259 ARMword RdHi
= 0, RdLo
= 0, Rm
;
4260 int scount
; /* cycle count */
4262 nRdHi
= BITS (16, 19);
4263 nRdLo
= BITS (12, 15);
4267 /* Needed to calculate the cycle count: */
4268 Rm
= state
->Reg
[nRm
];
4270 /* Check for illegal operand combinations first: */
4274 && nRm
!= 15 && nRdHi
!= nRdLo
&& nRdHi
!= nRm
&& nRdLo
!= nRm
)
4276 ARMword lo
, mid1
, mid2
, hi
; /* intermediate results */
4278 ARMword Rs
= state
->Reg
[nRs
];
4283 /* Compute sign of result and adjust operands if necessary. */
4285 sign
= (Rm
^ Rs
) & 0x80000000;
4287 if (((signed long) Rm
) < 0)
4290 if (((signed long) Rs
) < 0)
4294 /* We can split the 32x32 into four 16x16 operations. This ensures
4295 that we do not lose precision on 32bit only hosts: */
4296 lo
= ((Rs
& 0xFFFF) * (Rm
& 0xFFFF));
4297 mid1
= ((Rs
& 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4298 mid2
= (((Rs
>> 16) & 0xFFFF) * (Rm
& 0xFFFF));
4299 hi
= (((Rs
>> 16) & 0xFFFF) * ((Rm
>> 16) & 0xFFFF));
4301 /* We now need to add all of these results together, taking care
4302 to propogate the carries from the additions: */
4303 RdLo
= Add32 (lo
, (mid1
<< 16), &carry
);
4305 RdLo
= Add32 (RdLo
, (mid2
<< 16), &carry
);
4307 (carry
+ ((mid1
>> 16) & 0xFFFF) + ((mid2
>> 16) & 0xFFFF) + hi
);
4311 /* Negate result if necessary. */
4315 if (RdLo
== 0xFFFFFFFF)
4324 state
->Reg
[nRdLo
] = RdLo
;
4325 state
->Reg
[nRdHi
] = RdHi
;
4326 } /* else undefined result */
4328 fprintf (stderr
, "MULTIPLY64 - INVALID ARGUMENTS\n");
4332 /* Ensure that both RdHi and RdLo are used to compute Z, but
4333 don't let RdLo's sign bit make it to N. */
4334 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4337 /* The cycle count depends on whether the instruction is a signed or
4338 unsigned multiply, and what bits are clear in the multiplier: */
4339 if (msigned
&& (Rm
& ((unsigned) 1 << 31)))
4340 Rm
= ~Rm
; /* invert the bits to make the check against zero */
4342 if ((Rm
& 0xFFFFFF00) == 0)
4344 else if ((Rm
& 0xFFFF0000) == 0)
4346 else if ((Rm
& 0xFF000000) == 0)
4354 /***************************************************************************\
4355 * This function does the work of multiplying two 32bit values and adding *
4356 * a 64bit value to give a 64bit result. *
4357 \***************************************************************************/
4360 MultiplyAdd64 (ARMul_State
* state
, ARMword instr
, int msigned
, int scc
)
4367 nRdHi
= BITS (16, 19);
4368 nRdLo
= BITS (12, 15);
4370 RdHi
= state
->Reg
[nRdHi
];
4371 RdLo
= state
->Reg
[nRdLo
];
4373 scount
= Multiply64 (state
, instr
, msigned
, LDEFAULT
);
4375 RdLo
= Add32 (RdLo
, state
->Reg
[nRdLo
], &carry
);
4376 RdHi
= (RdHi
+ state
->Reg
[nRdHi
]) + carry
;
4378 state
->Reg
[nRdLo
] = RdLo
;
4379 state
->Reg
[nRdHi
] = RdHi
;
4383 /* Ensure that both RdHi and RdLo are used to compute Z, but
4384 don't let RdLo's sign bit make it to N. */
4385 ARMul_NegZero (state
, RdHi
| (RdLo
>> 16) | (RdLo
& 0xFFFF));
4388 return scount
+ 1; /* extra cycle for addition */