[讨论] ARM V7架构的汇编指令请教

ghkj2006   2013-6-17 13:36 楼主
一下代码摘至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 */
        }
}

回复评论 (1)

回复 楼主ghkj2006 的帖子

楼主,能不能向你请教一些有关SCPS协议啊
点赞  2013-11-11 16:24
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复