龙芯软件开发(18)-- 乾坤大挪移,从ROM到RAM

               
前面已经初始化内存和龙芯的缓存,那么现在已经差不多把新房子已经建立好了,要进入新房居住了。在 SDRAM 里的存取速度比 ROM 里快很多,并且可以随时修改数据,而在 ROM 是不能修改的,就算可以修改,也是非常慢的。
从上面初始化缓存回来后,就运行到下面的程序:
#####xuhua########open cp1
#if 1
        mfc0   t0,COP_0_STATUS_REG
      and    t0,0xdbffffff
      or     t0,t0,0x24000000
       mtc0   t0,COP_0_STATUS_REG
#endif
#################
上面的程序打开了 CP1 处理器,也就是浮点处理器。先从状态寄存器里取得 32 位中高 4 位的协处理器状态,然后先用通过 0x2400 0000 来打开浮点协处理器,把值改写回到状态寄存器。
 
/* close L2 cache */
    li      a0, 0xbfe00164
        sw      zero, 0(a0);
 
        mfc0   a0,COP_0_CONFIG
        and    a0,a0,~((1<<12) | 3)
    or     a0,a0,2
        mtc0   a0,COP_0_CONFIG
上面的程序关闭了二级缓存。
 
TTYDBG("Copy PMON to execute location.../r/n")
#ifdef DEBUG_LOCORE
    TTYDBG(" start = 0x")
    la a0, start
    bal hexserial
    nop
    TTYDBG("/r/n s0 = 0x")
    move   a0, s0
    bal hexserial
    nop
    TTYDBG("/r/n")
#endif
上面的代码是调试时显示当前 ROM 开始地址。
 
    la a0, start
    li a1, 0xbfc00000
    la a2, _edata
        or      a0, 0xa0000000
        or      a2, 0xa0000000
    subu   t1, a2, a0
    srl t1, t1, 2
 
    move   t0, a0
    move   t1, a1
    move   t2, a2
上面的代码是计算 ROM 里的代码开始位置和代码的长度,以及 RAM 里的开始。 a0 保存要 RAM 的开始地址 0xa001 0000, a1 保存 ROM 的开始地址 0xbfc0 0000 a2 保存 RAM 里的结束地址。
 
    /* copy text section */
   
1: and t3,t0,0x0000ffff
    bnez   t3,2f
    nop
    move   a0,t0
    bal hexserial
    nop
    li a0,'/r'
    bal    tgt_putchar
    nop
2: lw t3, 0(t1)
    nop
    sw t3, 0(t0)
    addu   t0, 4
    addu   t1, 4
    bne t2, t0, 1b
    nop
上面的代码是首先显示拷贝的字符,然后在 2 标号那里用 lw ROM 读取 4 字节数据,接着在后面用 sw 保存 4 字节数据到 RAM 里,最后判断是否拷贝数据完成。
 
    PRINTSTR("/ncopy text section done./r/n")
   
    /* Clear BSS */
    la a0, _edata
    la a2, _end
2: sw zero, 0(a0)
    bne a2, a0, 2b
    addu   a0, 4
 
    TTYDBG("Copy PMON to execute location done./r/n")
上面的代码是清空数据区。
 
TTYDBG("sp=");
    move a0, sp
    bal hexserial
    nop
 
#if 1
        mfc0   a0,COP_0_CONFIG
        and    a0,a0,0xfffffff8
        or     a0,a0,0x3
        mtc0   a0,COP_0_CONFIG
#endif
 
 
    li a0, 4096*1024
    sw a0, CpuTertiaryCacheSize /* Set L3 cache size */
上面的代码显示栈的位置,然后设置配置寄存里的 kseg0 的一致性算法。最后就是保存三级缓存的大小到变量里。
 
move   a0,msize
    srl a0,20
 
    /* pass pointer to kseg1 tgt_putchar */
    la a1, tgt_putchar
    addu a1,a1,s0
 
    la a2, stringserial
    addu a2,a2,s0
 
    la v0, initmips
    jalr   v0
    nop
上面代码先把内存大小 msize 放到参数 0 里,把输出字符函数指针放到参数 1 里,把字符串输出函数指针放到参数 2 里,然后取得 C 函数 initmips 入口地址,直接跳到那里运行,永远不再返回来。不过,后面还有一段防止出错的代码,如下:
 
stuck:
#ifdef DEBUG_LOCORE
    TTYDBG("Dumping GT64240 setup./r/n")
    TTYDBG("offset----data------------------------./r/n")
    li s3, 0
1:
    move   a0, s3
    bal hexserial
    nop
    TTYDBG(": ")
2:
    add a0, s3, bonito
    lw a0, 0(a0)
    bal hexserial
    addiu s3, 4
    TTYDBG(" ")
    li a0, 0xfff
    and a0, s3
    beqz   a0, 3f
    li a0, 0x01f
    and a0, s3
    bnez   a0, 2b
    TTYDBG("/r/n")
    b   1b
    nop
3:
    b   3b
    nop
 
#else
    b   stuck
    nop
#endif
 
上面主要是调试的代码,其实就是一个死循环在那里。
到这里,就已经把汇编代码看完了,进入到 C 的世界,就是更加方便编程和理解了,尽可能写更多的 C 代码,减少 BUG 的出现。
            

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/uytrrfg/article/details/86580751