一下代码摘至SCPS_RI卫星链路网关程序中的一小段,主要完成的是多线程之间的切换工作。以代码段中标红的I386为例,三小段程序大致意思应该是旧线程压入堆栈,调用新的线程,恢复旧线程。小弟对汇编不胜了解,请各位高手看看,如果用ARM来实现类似的功能,需要进行哪些操作。本人希望此程序能在ARM Cortex-A8的核上运行。
/*
* NewThreads context switching implementation for the following
* architectures done by Josef Burger (
bolo@cs.wisc.edu) Sparc 68000 HP
* Precision Architecture IBM RS/6000
*
* Notes: I also changed the existing implementation of the MIPS context switch
* routine to be interrupt (signal) safe.
*
* 9/13/93 Josef Burger (
bolo@cs.wisc.edu) Created a new version of the I860
* context switching code; It is now interrupt safe, and it also tries to
* generate a stack frame for the debugger.
*
* The 386 version was already signal safe.
*
* (The new context switchers that I wrote are all interrupt safe. bolo)
*/
/*****************************************************************************
*
* hand off the CPU to another thread
*
* don't mess with this code unless you know what you're doing!
*/
void
threadHandoffCPU(struct threads * t, Th_Status status)
{
static struct threads *oldThread;
static Th_Status stat;
oldThread = scheduler.current;
scheduler.current = t;
stat = status;
/* save registers */
#ifdef Mips
asm volatile("subu $sp, 100");
asm volatile("sw $17,4($sp); \
sw $18, 8($sp); \
sw $19, 12($sp); \
sw $20, 16($sp); \
sw $21, 20($sp); \
sw $22, 24($sp); \
sw $23, 28($sp); \
sw $fp, 32($sp); \
sw $16, 36($sp) ");
#endif /* Mips */
#ifdef I386
asm volatile("pushl %ebp; \
pushl % ebx; \
pushl % edi; \
pushl % esi; \
leal - 108(%esp), %esp ");
#endif /* I386 */
#ifdef Sparc
/* most of the context is saved courtesy of the reg. windows */
/*
* the floating point registers are caller-save, so we ignore them
* However, we want to terminate all fp. activity, so the trap
* doesn't occur in the wrong process. We do this by storing the
* floating point status register to memory (I use the arg passing
* area of the save area for this scratch)
*/
/*
* if (oldThread->usesFloatingPoint) { asm volatile("st %%fsr, [%%sp
* + %0]" : : "i" (SA(WINDOWSIZE))); }
*/
/*
* on the sparcs, the current "register window save area", pointed to
* by the SP, can pretty much be over-written ANYTIME by traps,
* interrupts, etc
*
* When we start to restore the new thread's context, if we setup SP
* immediately, the machine could wipe out any saved values before we
* have a chance to restore them. And, if we left it pointed at the
* old area, the activity would wipe out the context we had just
* saved.
*
* So,... we create a new register save area on the old thread's stack
* to use in the interim.
*
* (we use o7 because the compiler doesn't; a better solution would be
* to use a register variable)
*/
asm volatile(" mov %%sp, %0;":"=r"(oldThread->stack));
/* Flush register windows to the thread stack */
asm volatile(" \
t %0; \
sub %%sp, %1, %%sp; \
mov %2, %%o7 " \
: :"i" (ST_FLUSH_WINDOWS), \
"i" (SA(WINDOWSIZE)), \
"r" (scheduler.current->stack));
#endif /* Sparc */
#ifdef Mc68000
#ifdef Mc68020
asm volatile("moveml #0x3f3e, sp@-");
#else /* Mc68020 */
asm volatile(" \
movl a6, sp @ -; \
movl a5, sp @ -; \
movl a4, sp @ -; \
movl a3, sp @ -; \
movl a2, sp @ -; \
movl d7, sp @ -; \
movl d6, sp @ -; \
movl d5, sp @ -; \
movl d4, sp @ -; \
movl d3, sp @ -; \
movl d2, sp @ -; \
");
#endif /* Mc68020 */
#endif /* Mc68000 */
/* switch stack-pointers */
#ifdef Mips
asm volatile("add %0, $sp, $0" \
: "=r"(oldThread->stack));
asm volatile("add $sp, %0, $0" \
:: "r"(scheduler.current->stack));
#endif /* Mips */
#ifdef I386
asm volatile("movl %%esp, %0; \
movl %1, %%esp " \
:"=&r"(oldThread->stack) \
:"r"(scheduler.current->stack));
#endif /* i386 */
#ifdef Sparc
/* done above */
#endif /* Sparc */
#ifdef Mc68000
asm volatile("movl sp, %0;":"=r"(oldThread->stack));
asm volatile("movl %0, sp;"::"r"(scheduler.current->stack));
#endif /* Mc68000 */
oldThread->status = stat;
if (scheduler.current->status == Created)
{
/* first time --- call procedure directly */
#ifdef Mips
/* create a "mips" stackframe (room for arg regs) */
asm volatile("subu $sp, 24");
#endif /* Mips */
#ifdef Sparc
/*
* Ok, so we don't restore anything -- just setup the SP,
* which needs to have a register save + args area! Also,
* set the FP for the new stack
*/
asm volatile(" \
sub %%o7, %0, %%sp; \
mov %%o7, %%fp " \
: : "i"(SA(MINFRAME)));
#endif /* Sparc */
#ifdef Mc68000
/* setup a frame and a frame pointer */
asm volatile("movl sp, a6; subl #32, sp");
#endif /* Mc68000 */
/* scheduler.current->startFunc(scheduler->startArg); */
scheduler.current->status = Running;
scheduler.current->switch_time =
oldThread->switch_time = scheduler.switch_time;
scheduler.current->function();
threadExit();
} else
{
/* restore registers */
#ifdef Mips
asm volatile("lw $17,4($sp); \
lw $18, 8($sp); \
lw $19, 12($sp); \
lw $20, 16($sp); \
lw $21, 20($sp); \
lw $22, 24($sp); \
lw $23, 28($sp); \
lw $fp, 32($sp); \
lw $16, 36($sp) ");
asm volatile("addu $sp, 100");
#endif /* Mips */
#ifdef I386
asm volatile("leal 108(%esp), %esp; \
popl % esi; \
popl % edi; \
popl % ebx; \
popl % ebp ");
#endif /* I386 */
#ifdef Sparc
/*
* Ok, %o7 == ®ister save area, %sp==old threads save area
*
* Now, restore all registers (except the SP) from the new
* thread's save area
*/
asm volatile(" \
ldd [%o7], %l0; \
ldd [%o7 + 0x8], %l2; \
ldd [%o7 + 0x10], %l4; \
ldd [%o7 + 0x18], %l6; \
\
ldd [%o7 + 0x20], %i0; \
ldd [%o7 + 0x28], %i2; \
ldd [%o7 + 0x30], %i4; \
ldd [%o7 + 0x38], %i6; \
");
/*
* The registers are all valid, so traps won't wipe out info
* NOW, we can set the new sp
*/
asm volatile("nop; mov %o7, %sp; nop");
/*
* floating point registers are caller-save, so we ignore
* them
*/
#endif /* Sparc */
#ifdef Mc68000
/*
* if(scheduler.current->usesFloatingPoint){ asm volatile ("
* fmovem sp@+,#0xff "); }
*/
#if defined(Mc68020)
asm volatile("moveml sp@+, #0x7cfc");
#else /* defined(Mc68020) */
asm volatile(" \
movl sp @ +, d2; \
movl sp @ +, d3; \
movl sp @ +, d4; \
movl sp @ +, d5; \
movl sp @ +, d6; \
movl sp @ +, d7; \
movl sp @ +, a2; \
movl sp @ +, a3; \
movl sp @ +, a4; \
movl sp @ +, a5; \
movl sp @ +, a6; \
");
#endif /* defined(Mc68020) */
#endif /* Mc68000 */
}
}