免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1013 | 回复: 0
打印 上一主题 下一主题

mips研究--1 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-14 18:26 |只看该作者 |倒序浏览
# $4: start location ,存放cache 的开始地址
# $5: length ,存放cache的长度
invalidate_icache_region:
  ins $4, $0, 0, 6                # align to 64 bytes, 将$4的最后6位置0,也就是让开始地址64字节对齐
  addiu $2, $5, 63                # align up to 64 bytes, $2=$5+63
  srl $2, $2, 6                   # divide by 64,  $2=$2 >> 6,长度加63除64什么意思呢?一共有多少个64字节的块?
  beq $2, $0, done                # exit early on 0
  nop
iir_loop:
  cache 0x08, ($4)                # hit invalidate icache line,注意这种间接寻址方式,括号内寄存器值为内存base地址,括号前为偏移,这里偏移为0
  addiu $2, $2, -1                # next loop iteration,块个数--,
  bne $2, $0, iir_loop            # loop
  addiu $4, $4, 64                # go to next cache line (delay slot),cache检索位置+64
  
done:
  jr $ra                          # return,ra就是r31,里面保存了函数的返回地址,在调用这个函数的时候调用者会将返回地址写入这个寄存器。
  nop
==========================================
ins $4, $0, 0, 6   
    rt, rs, pos, size
        将rs的最后size个bit放到rt的pos位置。
addiu $2, $5, 63
srl $2, $2, 6
    rt, rs, 6     rt=rs>>6
         逻辑右移
beq  $2, $0, done     #branch if equal
   
======================================================================
mips汇编中的寄存器通用用法
一般函数调用的时候,函数参数放在4,5,6,7中,当函数参数比较少的时候。返回值放在$2,$3里面。
栈指针是$29寄存器。
ra就是r31,里面保存了函数的返回地址,在调用这个函数的时候调用者会将返回地址写入这个寄存器。jal指令会保存返回值。
jal指令写入$31的是其下下一条指令的地址
jal printf
move $4, $6
xxx   #return here after call
因为紧跟在调用指令后面的下一条指令是调用指令的延迟槽。该指令必须在分支目标指令之前执行。这个指令经常用来建立调用的参数。(??really)
寄存器编号 助记符 用法
0 zero 永远返回值为0
1 at 用做汇编器的暂时变量
2-3 v0, v1 子函数调用返回结果
4-7 a0-a3 子函数调用的参数
8-15 t0-t7 24-25 t8-t9 暂时变量,子函数使用时不需要保存与恢复
16-23 s0-s7 子函数寄存器变量。子函数必须保存和恢复使用过的变量在函数返回之前,从而调用函数知道这些寄存器的值没有变化。
26,27 k0,k1 通常被中断或异常处理程序使用作为保存一些系统参数
28 gp 全局指针。一些运行系统维护这个指针来更方便的存取“static“和”extern"变量。
29 sp 堆栈指针
30 s8/fp 第9个寄存器变量。子函数可以用来做桢指针
31 ra 子函数的返回地址
==========================================================================================================
mips只有一种寻址方式,任何一种加载或者存储机器指令的代码都可以写成:  lw $1, offset($2)
lw rt, offset(base)
偏移量是一个有符号的16位的数字。-32768--32767
符号扩展的意义:符号扩展指令lb和lh(byte and halfword)指令将数据存放在32位寄存器的低位,并将高位用符号位来填充。
         符号填充的意义在于,可以正确的将一个16/8位有符号整数转换为一个32位有符号整数。负数用补码来表示,反码+1
8      0x08  --> 0x00000008 = 8
-8       0xf8  --> 0xfffffff8 = -8
对应的,lbu和lhu将指令数据方在32位寄存器的低位,高位用0来填充。
===========================================================================================================
lh,lhu为16位立即数加载
mips体系结构不能够使用一条指令,将1个32位的立即数加载到寄存器中,只能每次加载16位立即数(没有li这个指令,)
lhu rt, offset(base)   0 扩展
lh  rt, offset(base)   符号扩展
==========================================================================================================
关于地址空间:
我们知道,mips cpu有一个地址空间的描述,jz4740也有一个地址空间的map,这两者有什么区别与联系呢?
下面所讲的地址,都是程序地址。mips的程序地址和物理地址不会相等,但对于kseg0和kseg1虚拟地址和物理地址对应起来很方便。
mips cpu有用户模式与特权模式,在用户模式下,地址最高位为1的任何程序都会导致cpu的一个自陷。有些指令在用户态也会异常。
mips cpu:
0x00000000 ------- 0x80000000(2G)    user space, kuseg
0x80000000 ------- 0xa0000000(512M)    unmapped cached, kseg0
0x80000000 ------- 0xc0000000(512M)   unmapped uncached, kseg1
0xc0000000 ------- 0xffffffff(1G)    Mapped, kseg2
kuseg:用户态可见地址,在有mmu的机器中,这些地址将一概被转换。除非mmu已经被设置好,否则不应该使用这些地址。
kseg0:该区域的地址,几乎总要通过高速缓存来取,所以在告诉缓存适当初始化以前,不应该使用。这个区域在有MMU的系统中用来存放操作系统的核心。
              该区域地址通过把最高位清零来映射到物理地址。低512M.
kseg1:系统重启的入口点0xbfc00000房子这个区域。入口点相应的物理地址是0x1fc00000,这是什么意思?所以我们需要这个区域来存取系统初始的rom,大多数
             人也把该区域用作IO寄存器空间。该区域地址通过把最高3位清零来映射到物理地址。低512M.
kseg2:该区域只能在核心态下使用,并且要经过MMU的转换。在MMU被设置之前,不要使用。可以看出,这快区域被用来存放操作系统。
kseg0,kseg1和物理地址有非常简单的映射关系,不需要mmu转换。
程序地址就是我们送给cpu的指令中所使用的地址。我们一开始会在程序地址的0xbfc00000处,但这个地址会被cpu映射到物理地址的0x1fc00000处。
也就是说最后cpu的地址总线送出去的其实是0x1fc00000这个地址,而我们在start.S中使用的是0xbfc00000这个地址。
这个地址属于kseg2,可以直接在核心态下使用,不会被mmu转换。
我们再来看看jz4740的地址映射:
0x00000000 ---- 0x08000000    SDRAM space
0x80000000 ---- 0x10000000    Default Static Memory bank 3,4
0x10000000 ---- 0x14000000    IO Space
0x14000000 ---- 0x1c000000    Default Static Memory bank 1,2
0x1c000000 ---- 0x20000000    Default Static Memory bank 0
这bank0中,0x1fc00000 ---- 0x1fc01000中放着bootrom.和上面mips的物理地址于虚拟地址对应上了。
我们再看内核和bootloader中使用的地址:
#define UART0_BASE  0xB0030000
这是串口寄存器的地址。这个地址的意义是什么呢:显然,这个地址在kseg1中,从上面我们知道,这个地址必须在核心态才能访问,不会被mmu转换。
而且最后会被映射到物理地址:0x10030000。也就是说,二进制代码中使用的是0xb0030000,而cpu根据这个地址去寻址的时候,会访问物理地址
0x10030000。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/59615/showart_1001411.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP