MIPS体系结构学习笔记

来源:百度文库 编辑:超级军网 时间:2024/04/26 17:26:37


本人订购的《MIPS体系结构与编程》到货了,刚刚读完第二章《MIPS结构体系概述》,记录若干心得如下:
和我以前学过的X86结构体系相比,MIPS结构体系给我的印象就是两个字:简洁。X86系统的寄存器有14个,划分为四类:通用寄存器,指令指针寄存器,标志寄存器,段寄存器。相比之下,MIPS的寄存器比X86要多,有35个,但其中有32个(r0~31)是通用寄存器,两个(HI,LO)是特殊功能寄存器(用于存储整数乘除和乘/累加操作的结果),还有一个是特殊功能程序计数器,由特定指令直接操作,对程序员不可见。也就是说,程序员面对的寄存器只有两种:通用寄存器和特殊功能寄存器。
在32个通用寄存器中,第一个寄存器r0被硬件连接成低位,也就是说,它的值是恒定的,总是0。因此这个寄存器一般被用于结果不需要保存的操作,以及作为需要0值时的来源。最后一个寄存器r31在没有特殊说明的情况下,是用于存放子函数的返回地址。同时,它也可以作为普通的寄存器使用。除了r0和r31,其他寄存器都是作为一般的寄存器使用。也就是说,MIPS有31个通用寄存器可以使用,这比X86(8个)要多的多。
虽然有这么多寄存器,但在实际使用中,这些寄存器的用法都遵从一些约定俗成的规定。比如r31虽然可以作为通用寄存器使用,但它一般是专用于存放子函数的返回地址,而不用做其他用途。这样可以提高程序的可读性。
一个问题:书上介绍,每个寄存器除了名字(r0,r1等)还有编程时的命名,比如r0叫zero,r1叫at,r31叫ra,等等。这是不是意味着MIPS的汇编语言中使用的是后一套名字?

本人订购的《MIPS体系结构与编程》到货了,刚刚读完第二章《MIPS结构体系概述》,记录若干心得如下:
和我以前学过的X86结构体系相比,MIPS结构体系给我的印象就是两个字:简洁。X86系统的寄存器有14个,划分为四类:通用寄存器,指令指针寄存器,标志寄存器,段寄存器。相比之下,MIPS的寄存器比X86要多,有35个,但其中有32个(r0~31)是通用寄存器,两个(HI,LO)是特殊功能寄存器(用于存储整数乘除和乘/累加操作的结果),还有一个是特殊功能程序计数器,由特定指令直接操作,对程序员不可见。也就是说,程序员面对的寄存器只有两种:通用寄存器和特殊功能寄存器。
在32个通用寄存器中,第一个寄存器r0被硬件连接成低位,也就是说,它的值是恒定的,总是0。因此这个寄存器一般被用于结果不需要保存的操作,以及作为需要0值时的来源。最后一个寄存器r31在没有特殊说明的情况下,是用于存放子函数的返回地址。同时,它也可以作为普通的寄存器使用。除了r0和r31,其他寄存器都是作为一般的寄存器使用。也就是说,MIPS有31个通用寄存器可以使用,这比X86(8个)要多的多。
虽然有这么多寄存器,但在实际使用中,这些寄存器的用法都遵从一些约定俗成的规定。比如r31虽然可以作为通用寄存器使用,但它一般是专用于存放子函数的返回地址,而不用做其他用途。这样可以提高程序的可读性。
一个问题:书上介绍,每个寄存器除了名字(r0,r1等)还有编程时的命名,比如r0叫zero,r1叫at,r31叫ra,等等。这是不是意味着MIPS的汇编语言中使用的是后一套名字?
记得有哪种CPU是基于堆栈的?
我看过X86的汇编语言教程,看了之后发现学了也没用,就做罢了……
对我这种人,即使需要执行效率,C已经很好了
X86函数调用参数传递是基于栈的,谁让它寄存器那么少,MIPS看过一些汇编代码,小于4个参数时用4个寄存器传递参数,效率比较高
RISC类机器基本都这个样子。还有变态的SPARC玩的什么寄存器窗口等等。

基本上,早期一些注重于简单设计的RISC机器,特别依赖编译器的优化与调度,汇编语言层次几乎是人类无法阅读和编写的,比如恶心的延迟槽。到了VLIW更是如此。
jiandingzhe 发表于 2010-10-14 22:26


    Java虚拟机。
LZ, x86-64bit 扩充到16个通用寄存器了,增加了R8~R15
RAX, RBX, RCX, RDX, RBP, RSP, RSI, RDI, R8~815
不过x86的寄存器越来越杂了……
馒头簸箕 发表于 2010-10-14 22:47
要活的,不要假的
{:2_68:}
簡單的說: MIPS靠Clock吃飯,MOPS靠複雜指令吃飯。
過去一顆IBM MOPS CPU (2 Floating Pipeline + 2 Integer)速度跑的clock只有HP MIPS的1/3.  DEC的1/4.
兄弟要玩硬件?
馒头簸箕 发表于 2010-10-14 22:46
寄存器窗口对于状态切换和显式寄存器换名很有用啊,主要是用来进行硬件机制的加速和动态调度的。这种技术实现难度较低,比较常见的。
相比MIPS,X86中用的一些技术才是变态(因为原始的X86指令太复杂,而Intel又很有钱可以使用一些复杂的技术来提高性能)
我对RISC VS CISC的理解是:
RISC的优势在于译码简单, 可以非常容易翻译成微码
CSIC的译码可能需要查表, 相当复杂, 但优势是代码信息容量大, 占用空间小.

在当前的CPU中, 译码过程的延时能被流水线很好的遮盖, 所以RISC的优势减弱了, 但是随着频率的提升, CACHE利用率对性能的影响越来越大, CISC代码尺寸小的优势体现出来了
回复 1# zlaser

不错啊:D
转一段文章看看

CISC,复杂指令集,是早期储存器昂贵、传输带宽小、逻辑器件体积庞大一致性差、软件模型粗糙的条件下,建立的最优体系架构。而RISC,精简指令集,,则是在以上条件发生变化的过程中诞生的,这时储存器价格下降、传输带宽扩大、逻辑器件半导体化、软件模型研究逐步深入。

而RISC 中以ARM为代表的流水线互锁,和MIPS为代表的流水线无互锁,这两种体系架构思路则是RISC大框架下软硬件切分点的不同选择。ARM通过硬件互锁简化了编译器,指令集扩充是容易,所以ARM成为了兼容性CPU的代表,可以很轻松在其上扩充如滤波指令等协处理器指令。相对而言,MIPS指令扩充就没那么容易,往往一点点改动就足以把编译器重做一次,而且正由于无互锁结构,协处理器并不容易做得和主流水线一样高效。这个差异导致了ARM和MIPS两个公司的此起彼落。ARM发展为全球最大的IP供应商,而MIPS则仍停留在技术型小公司。

然而,新的时代仍然会到来。

算术流水线才是计算的核心内容,因为计算机的本质目的就似乎做计算。这点仿佛被大多数硬件设计师忘记,把太多精力放在算术以外的例外处理。当工艺往深走时,更微观化的算术流水线将导致不同体系架构在复杂度和功耗上面不同阶的增长速度。例如主频,作为硬件设计师必须知道,硬件频率取决于最长组合延时路径,只要有一个环节在设计师的全盘把控之外,那么硬件主频的提高就是泡影。这时ARM美丽的硬件互锁结构在制造难优化的关键路径和高功耗的能力上,简直无敌。

转一段文章看看

CISC,复杂指令集,是早期储存器昂贵、传输带宽小、逻辑器件体积庞大一致性差、软件模型 ...
acoustics 发表于 2010-10-15 12:32

这段文章初读入门还可以,但是仔细读还是有太多的问题。比如说ARM和MISP在商业上的成功与否本质上不是由于技术上的区别,而是商业模式的问题…………
其次,对于提高频率而言,非互锁结构要比互锁的更有优势……
转一段文章看看

CISC,复杂指令集,是早期储存器昂贵、传输带宽小、逻辑器件体积庞大一致性差、软件模型 ...
acoustics 发表于 2010-10-15 12:32

这段文章初读入门还可以,但是仔细读还是有太多的问题。比如说ARM和MISP在商业上的成功与否本质上不是由于技术上的区别,而是商业模式的问题…………
其次,对于提高频率而言,非互锁结构要比互锁的更有优势……
roadrunner 发表于 2010-10-15 10:15
本质上,现在CISC也在使用RISC的技术,所以说两者的优劣没有太明显区别。而所谓CISC的代码密度大的优势也主要是厂家的宣传。
回复 4# liwangli


    x86-64默认用寄存器传参。
yigua 发表于 2010-10-15 13:12

相反我很少看到厂家宣传CISC代码密度大, 但CISC代码密度大是客观现实, 相同的C源码, 编译成CISC和RISC, 代码尺寸至少差个20%吧.
纯粹的CISC和纯粹的RISC目前都不存在了,剩下的一些体系结构,x86是靠巨大的人力物力代价深度优化获得高性能(内部是把CISC指令翻译成类似RISC的指令在跑),其他原来的RISC体系也变得更加复杂,靠超标量多发射、超流水线、甚长指令字等方法提高性能,不过除了IBM,其他总体而言在技术投入上没有Intel来的大,更加注重于桌面之外的特定市场。
作为一种RISC指令集,MIPS指令集的所有指令的长度都相同,都是32位。按功能可划分为五类:加载和存储指令、算术指令、跳转和分支指令、杂类指令和协处理器指令。
1、加载/存储指令
因为CPU与外部存储器打交道的指令执行时间远大于在寄存器内操作的指令执行时间,因此RISC型CPU都采用加载/存储结构,只有加载和存储指令才能对存储器进行操作。MIPS处理器也是如此。加载和存储指令主要完成以下操作:
(1)传输可变大小的字段,比如字节、半字和字。
(2)访问有/无符号整型数据。
(3)访问未对齐的字段。
(4)选择寻址模式。
(5)原子内存刷新,即读取-修改-写回操作序列。
MIPS加载和存储指令的命名规则如下:
(1)首字母L表示“加载”,S表示“存储”。
(2)首字母U表示“无符号”,其余默认为有符号。
(3)尾字母R表示“右”,L表示“左”。
(4)字母B表示“字节”,H表示“半字”,W表示“字”。
比如,LWL的功能是加载字头,LWR的功能是加载字尾,SWL的功能是存储字头,SWR的功能是存储字尾。
根据用途的不同,还可以将加载和存储指令分为对齐加载和存储指令、非对齐加载和存储指令以及原子刷新加载和存储指令等。
zlaser 发表于 2010-10-15 20:24


    没必要这么花力气吧?MIPS已经是没啥市场的东西了。
楼主是要研究龙芯。我对CISC, RISC一度很感兴趣。CISC和RISC的区别只能是指令集上的,而不能是实现上的。比如,同样的486指令集,Intel来实现就是CISC, NexGen来实现就成了RISC?这说不过去。现在的芯片门多,CISC为解码多用门没关系。而传输瓶颈的影响大,所以CISC对RISC来说反而具有了优势。12楼说得很对。
2、非对齐加载和存储指令
一般来说,硬件访问内存时传递的是4或8个字节的对齐数据,这样与应届的设计相一致,提高了访问效率。非对齐字的存储可以让存储区域中的某些字节不被改变(比如一个对齐字的上半部分),也可以让RMW序列对字或双字进行操作。通过使用非对齐加载和存储指令,需要用两条指令来加载和存储内存中未对齐的字或双字。一条加载指令从内存中一个对齐的字中读其左端或右端某些字节(放在寄存器的左或右边),另一条加载指令从内存中刚读取字的相邻位置读取右端或左端字节,然后将其合并为目标寄存器中正确的字。存储指令将一个对齐的字中左端或右端字节(源自寄存器的左或右边),存储至不对齐的内存地址。
LWL(load word left)
该指令从未对齐的内存地址(有效地址)中加载一个字的最高有效部分,作为一个有符号的值,放入目标寄存器中。
指令格式: LWL rt,offset(base)
指令描述: rt<-rt MERGE memory[base+offset]
16位的有符号地址偏移量offset与通用基址寄存器base相加以形成有效地址,此地址是内存中起始于任意字节边界的4个连续字节(组成一个字W)的最高有效字节地址。W中的1到4个最高有效字节处于包含此有效地址的对齐字中,这部分字节加载到目标寄存器rt的最高有效位置(左边),rt中剩下的最低有效位置(右边)保持不变。
LWR的有效位定义与LWL相反。在LWR $24,5($0)指令中,偏移量5与基址寄存器相加形成有效地址。从位置5开始向前连续4个字节形成一个非对齐字(位置5对应LSB)。对齐字(包含4~7字节)包含了非对齐字的2个LSB字节。LWR加载这两个字节到目标寄存器的右半部分(最低的2个字节),目标字左半部分不变。
LWL/LWR指令加载的字节数取决于非对齐字相对于对齐字的偏移量,即与有效地址的低两位(vAddr1.0)及处理器的当前字节顺序(大尾端或小尾端)有关。
回答lz的问题  我看同事的代码都是用zero ra这样的缩写