2005-04-16 15:20:36 -07:00
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
/ *
* Function : v4 t _ l a t e _ a b o r t
*
* Params : r2 = a d d r e s s o f a b o r t e d i n s t r u c t i o n
* : r3 = s a v e d S P S R
*
* Returns : r0 = a d d r e s s o f a b o r t
* : r1 = F S R , b i t 1 1 = w r i t e
* : r2 - r8 = c o r r u p t e d
* : r9 = p r e s e r v e d
* : sp = p o i n t e r t o r e g i s t e r s
*
* Purpose : o b t a i n i n f o r m a t i o n a b o u t c u r r e n t a b o r t e d i n s t r u c t i o n .
* Note : we r e a d u s e r s p a c e . T h i s m e a n s w e m i g h t c a u s e a d a t a
* abort h e r e i f t h e I - T L B a n d D - T L B a r e n ' t s e e i n g t h e s a m e
* picture. U n f o r t u n a t e l y , t h i s d o e s h a p p e n . W e l i v e w i t h i t .
* /
ENTRY( v4 t _ l a t e _ a b o r t )
tst r3 , #P S R _ T _ B I T @ c h e c k f o r t h u m b m o d e
2006-09-28 21:46:16 +09:00
# ifdef C O N F I G _ C P U _ C P 1 5 _ M M U
2005-04-16 15:20:36 -07:00
mrc p15 , 0 , r1 , c5 , c0 , 0 @ get FSR
mrc p15 , 0 , r0 , c6 , c0 , 0 @ get FAR
2006-09-28 21:46:16 +09:00
bic r1 , r1 , #1 < < 1 1 | 1 < < 1 0 @ clear bits 11 and 10 of FSR
# else
mov r0 , #0 @ clear r0, r1 (no FSR/FAR)
mov r1 , #0
# endif
2005-04-16 15:20:36 -07:00
bne . d a t a _ t h u m b _ a b o r t
ldr r8 , [ r2 ] @ read arm instruction
tst r8 , #1 < < 2 0 @ L = 1 -> write?
orreq r1 , r1 , #1 < < 1 1 @ yes.
and r7 , r8 , #15 < < 2 4
add p c , p c , r7 , l s r #22 @ Now branch to the relevant processing routine
nop
/* 0 */ b . d a t a _ a r m _ l a t e l d r h p o s t @ ldrh rd, [rn], #m/rm
/* 1 */ b . d a t a _ a r m _ l a t e l d r h p r e @ ldrh rd, [rn, #m/rm]
/* 2 */ b . d a t a _ u n k n o w n
/* 3 */ b . d a t a _ u n k n o w n
/* 4 */ b . d a t a _ a r m _ l a t e l d r p o s t c o n s t @ ldr rd, [rn], #m
/* 5 */ b . d a t a _ a r m _ l a t e l d r p r e c o n s t @ ldr rd, [rn, #m]
/* 6 */ b . d a t a _ a r m _ l a t e l d r p o s t r e g @ ldr rd, [rn], rm
/* 7 */ b . d a t a _ a r m _ l a t e l d r p r e r e g @ ldr rd, [rn, rm]
/* 8 */ b . d a t a _ a r m _ l d m s t m @ ldm*a rn, <rlist>
/* 9 */ b . d a t a _ a r m _ l d m s t m @ ldm*b rn, <rlist>
/* a */ b . d a t a _ u n k n o w n
/* b */ b . d a t a _ u n k n o w n
/* c */ mov p c , l r @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m
/* d */ mov p c , l r @ ldc rd, [rn, #m]
/* e */ b . d a t a _ u n k n o w n
/* f */
.data_unknown : @ Part of jumptable
mov r0 , r2
mov r1 , r8
mov r2 , s p
bl b a d d a t a a b o r t
b r e t _ f r o m _ e x c e p t i o n
.data_arm_ldmstm :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
mov r7 , #0x11
orr r7 , r7 , #0x1100
and r6 , r8 , r7
and r2 , r8 , r7 , l s l #1
add r6 , r6 , r2 , l s r #1
and r2 , r8 , r7 , l s l #2
add r6 , r6 , r2 , l s r #2
and r2 , r8 , r7 , l s l #3
add r6 , r6 , r2 , l s r #3
add r6 , r6 , r6 , l s r #8
add r6 , r6 , r6 , l s r #4
and r6 , r6 , #15 @ r6 = no. of registers to transfer.
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r6 , l s l #2 @ Undo increment
addeq r7 , r7 , r6 , l s l #2 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_lateldrhpre :
tst r8 , #1 < < 2 1 @ Check writeback bit
moveq p c , l r @ No writeback -> no fixup
.data_arm_lateldrhpost :
and r5 , r8 , #0x00f @ get Rm / low nibble of immediate value
tst r8 , #1 < < 2 2 @ if (immediate offset)
andne r6 , r8 , #0xf00 @ { immediate high nibble
orrne r6 , r5 , r6 , l s r #4 @ combine nibbles } else
ldreq r6 , [ s p , r5 , l s l #2 ] @ { load Rm value }
.data_arm_apply_r6_and_rn :
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r6 @ Undo incrmenet
addeq r7 , r7 , r6 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_lateldrpreconst :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
.data_arm_lateldrpostconst :
movs r2 , r8 , l s l #20 @ Get offset
moveq p c , l r @ zero -> no fixup
and r5 , r8 , #15 < < 1 6 @ Extract 'n' from instruction
ldr r7 , [ s p , r5 , l s r #14 ] @ Get register 'Rn'
tst r8 , #1 < < 2 3 @ Check U bit
subne r7 , r7 , r2 , l s r #20 @ Undo increment
addeq r7 , r7 , r2 , l s r #20 @ Undo decrement
str r7 , [ s p , r5 , l s r #14 ] @ Put register 'Rn'
mov p c , l r
.data_arm_lateldrprereg :
tst r8 , #1 < < 2 1 @ check writeback bit
moveq p c , l r @ no writeback -> no fixup
.data_arm_lateldrpostreg :
and r7 , r8 , #15 @ Extract 'm' from instruction
ldr r6 , [ s p , r7 , l s l #2 ] @ Get register 'Rm'
mov r5 , r8 , l s r #7 @ get shift count
ands r5 , r5 , #31
and r7 , r8 , #0x70 @ get shift type
orreq r7 , r7 , #8 @ shift count = 0
add p c , p c , r7
nop
mov r6 , r6 , l s l r5 @ 0: LSL #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n @ 1: LSL #0
nop
b . d a t a _ u n k n o w n @ 2: MUL?
nop
b . d a t a _ u n k n o w n @ 3: MUL?
nop
mov r6 , r6 , l s r r5 @ 4: LSR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , l s r #32 @ 5: LSR #32
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ 6: MUL?
nop
b . d a t a _ u n k n o w n @ 7: MUL?
nop
mov r6 , r6 , a s r r5 @ 8: ASR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , a s r #32 @ 9: ASR #32
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ A: MUL?
nop
b . d a t a _ u n k n o w n @ B: MUL?
nop
mov r6 , r6 , r o r r5 @ C: ROR #!0
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
mov r6 , r6 , r r x @ D: RRX
b . d a t a _ a r m _ a p p l y _ r6 _ a n d _ r n
b . d a t a _ u n k n o w n @ E: MUL?
nop
b . d a t a _ u n k n o w n @ F: MUL?
.data_thumb_abort :
ldrh r8 , [ r2 ] @ read instruction
tst r8 , #1 < < 1 1 @ L = 1 -> write?
orreq r1 , r1 , #1 < < 8 @ yes
and r7 , r8 , #15 < < 1 2
add p c , p c , r7 , l s r #10 @ lookup in table
nop
/* 0 */ b . d a t a _ u n k n o w n
/* 1 */ b . d a t a _ u n k n o w n
/* 2 */ b . d a t a _ u n k n o w n
/* 3 */ b . d a t a _ u n k n o w n
/* 4 */ b . d a t a _ u n k n o w n
/* 5 */ b . d a t a _ t h u m b _ r e g
/* 6 */ mov p c , l r
/* 7 */ mov p c , l r
/* 8 */ mov p c , l r
/* 9 */ mov p c , l r
/* A */ b . d a t a _ u n k n o w n
/* B */ b . d a t a _ t h u m b _ p u s h p o p
/* C */ b . d a t a _ t h u m b _ l d m s t m
/* D */ b . d a t a _ u n k n o w n
/* E */ b . d a t a _ u n k n o w n
/* F */ b . d a t a _ u n k n o w n
.data_thumb_reg :
tst r8 , #1 < < 9
moveq p c , l r
tst r8 , #1 < < 1 0 @ If 'S' (signed) bit is set
movne r1 , #0 @ it must be a load instr
mov p c , l r
.data_thumb_pushpop :
tst r8 , #1 < < 1 0
beq . d a t a _ u n k n o w n
and r6 , r8 , #0x55 @ hweight8(r8) + R bit
and r2 , r8 , #0xaa
add r6 , r6 , r2 , l s r #1
and r2 , r6 , #0xcc
and r6 , r6 , #0x33
add r6 , r6 , r2 , l s r #2
movs r7 , r8 , l s r #9 @ C = r8 bit 8 (R bit)
adc r6 , r6 , r6 , l s r #4 @ high + low nibble + R bit
and r6 , r6 , #15 @ number of regs to transfer
ldr r7 , [ s p , #13 < < 2 ]
tst r8 , #1 < < 1 1
addeq r7 , r7 , r6 , l s l #2 @ increment SP if PUSH
subne r7 , r7 , r6 , l s l #2 @ decrement SP if POP
str r7 , [ s p , #13 < < 2 ]
mov p c , l r
.data_thumb_ldmstm :
and r6 , r8 , #0x55 @ hweight8(r8)
and r2 , r8 , #0xaa
add r6 , r6 , r2 , l s r #1
and r2 , r6 , #0xcc
and r6 , r6 , #0x33
add r6 , r6 , r2 , l s r #2
add r6 , r6 , r6 , l s r #4
and r5 , r8 , #7 < < 8
ldr r7 , [ s p , r5 , l s r #6 ]
and r6 , r6 , #15 @ number of regs to transfer
sub r7 , r7 , r6 , l s l #2 @ always decrement
str r7 , [ s p , r5 , l s r #6 ]
mov p c , l r