.text
.arm
ENTRY(iwmmxt_undef_handler)
push {r9, r10, lr}
get_thread_info r10
mov r9, pc
b iwmmxt_task_enable
mov r0,
pop {r9, r10, pc}
ENDPROC(iwmmxt_undef_handler)
ENTRY(iwmmxt_task_enable)
inc_preempt_count r10, r3
mrc p15, 0, r2, c15, c1, 0
@ CP0 and CP1 accessible?
tst r2,
bne 4f @ if so no business here
@ enable access to CP0 and CP1
orr r2, r2,
mcr p15, 0, r2, c15, c1, 0
ldr r3, =concan_owner
ldr r2, [r0,
ldr r1, [r3] @ get current Concan owner
sub r2, r2,
str r2, [r0,
add r0, r10,
str r0, [r3] @ this task now owns Concan regs
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
bl concan_save
get_thread_info r10
4: dec_preempt_count r10, r3
ret r9 @ normal exit from exception
concan_save:
teq r1,
beq concan_load @ no owner, skip save
tmrc r2, wCon
@ CUP? wCx
tst r2,
beq 1f
concan_dump:
wstrw wCSSF, r1, MMX_WCSSF
wstrw wCASF, r1, MMX_WCASF
wstrw wCGR0, r1, MMX_WCGR0
wstrw wCGR1, r1, MMX_WCGR1
wstrw wCGR2, r1, MMX_WCGR2
wstrw wCGR3, r1, MMX_WCGR3
1: @ MUP? wRn
tst r2,
beq 2f
wstrd wR0, r1, MMX_WR0
wstrd wR1, r1, MMX_WR1
wstrd wR2, r1, MMX_WR2
wstrd wR3, r1, MMX_WR3
wstrd wR4, r1, MMX_WR4
wstrd wR5, r1, MMX_WR5
wstrd wR6, r1, MMX_WR6
wstrd wR7, r1, MMX_WR7
wstrd wR8, r1, MMX_WR8
wstrd wR9, r1, MMX_WR9
wstrd wR10, r1, MMX_WR10
wstrd wR11, r1, MMX_WR11
wstrd wR12, r1, MMX_WR12
wstrd wR13, r1, MMX_WR13
wstrd wR14, r1, MMX_WR14
wstrd wR15, r1, MMX_WR15
2: teq r0,
reteq lr @ if not, return
concan_load:
@ Load wRn
wldrd wR0, r0, MMX_WR0
wldrd wR1, r0, MMX_WR1
wldrd wR2, r0, MMX_WR2
wldrd wR3, r0, MMX_WR3
wldrd wR4, r0, MMX_WR4
wldrd wR5, r0, MMX_WR5
wldrd wR6, r0, MMX_WR6
wldrd wR7, r0, MMX_WR7
wldrd wR8, r0, MMX_WR8
wldrd wR9, r0, MMX_WR9
wldrd wR10, r0, MMX_WR10
wldrd wR11, r0, MMX_WR11
wldrd wR12, r0, MMX_WR12
wldrd wR13, r0, MMX_WR13
wldrd wR14, r0, MMX_WR14
wldrd wR15, r0, MMX_WR15
@ Load wCx
wldrw wCSSF, r0, MMX_WCSSF
wldrw wCASF, r0, MMX_WCASF
wldrw wCGR0, r0, MMX_WCGR0
wldrw wCGR1, r0, MMX_WCGR1
wldrw wCGR2, r0, MMX_WCGR2
wldrw wCGR3, r0, MMX_WCGR3
@ clear CUP/MUP (only if r1 != 0)
teq r1,
mov r2,
reteq lr
tmcr wCon, r2
ret lr
ENDPROC(iwmmxt_task_enable)
ENTRY(iwmmxt_task_disable)
stmfd sp!, {r4, lr}
mrs ip, cpsr
orr r2, ip,
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0,
ldr r1, [r3] @ get current Concan owner
teq r1,
beq 1f @ no: quit
teq r0,
teqne r1, r2 @ or specified one?
bne 1f @ no: quit
@ enable access to CP0 and CP1
mrc p15, 0, r4, c15, c1, 0
orr r4, r4,
mcr p15, 0, r4, c15, c1, 0
mov r0,
str r0, [r3] @ no more current owner
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
bl concan_save
@ disable access to CP0 and CP1
bic r4, r4,
mcr p15, 0, r4, c15, c1, 0
mrc p15, 0, r2, c2, c0, 0
mov r2, r2 @ cpwait
1: msr cpsr_c, ip @ restore interrupt mode
ldmfd sp!, {r4, pc}
ENDPROC(iwmmxt_task_disable)
ENTRY(iwmmxt_task_copy)
mrs ip, cpsr
orr r2, ip,
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0,
ldr r3, [r3] @ get current Concan owner
teq r2, r3 @ does this task own it...
beq 1f
@ current Concan values are in the task save area
msr cpsr_c, ip @ restore interrupt mode
mov r0, r1
mov r1, r2
mov r2,
b memcpy
1: @ this task owns Concan regs -- grab a copy from there
mov r0,
mov r2,
mov r3, lr @ preserve return address
bl concan_dump
msr cpsr_c, ip @ restore interrupt mode
ret r3
ENDPROC(iwmmxt_task_copy)
ENTRY(iwmmxt_task_restore)
mrs ip, cpsr
orr r2, ip,
msr cpsr_c, r2
ldr r3, =concan_owner
add r2, r0,
ldr r3, [r3] @ get current Concan owner
bic r2, r2,
teq r2, r3 @ does this task own it...
beq 1f
@ this task doesn't own Concan regs -- use its save area
msr cpsr_c, ip @ restore interrupt mode
mov r0, r2
mov r2,
b memcpy
1: @ this task owns Concan regs -- load them directly
mov r0, r1
mov r1,
mov r3, lr @ preserve return address
bl concan_load
msr cpsr_c, ip @ restore interrupt mode
ret r3
ENDPROC(iwmmxt_task_restore)
ENTRY(iwmmxt_task_switch)
mrc p15, 0, r1, c15, c1, 0
@ CP0 and CP1 accessible?
tst r1,
bne 1f @ yes: block them for next task
ldr r2, =concan_owner
add r3, r0,
ldr r2, [r2] @ get current Concan owner
teq r2, r3 @ next task owns it?
retne lr @ no: leave Concan disabled
1: @ flip Concan access
eor r1, r1,
mcr p15, 0, r1, c15, c1, 0
mrc p15, 0, r1, c2, c0, 0
sub pc, lr, r1, lsr
ENDPROC(iwmmxt_task_switch)
ENTRY(iwmmxt_task_release)
mrs r2, cpsr
orr ip, r2,
msr cpsr_c, ip
ldr r3, =concan_owner
add r0, r0,
ldr r1, [r3] @ get current Concan owner
eors r0, r0, r1 @ if equal...
streq r0, [r3] @ then clear ownership
msr cpsr_c, r2 @ restore interrupts
ret lr
ENDPROC(iwmmxt_task_release)
.data
.align 2
concan_owner:
.word 0