MIPS体系结构.docx

上传人:b****5 文档编号:30309263 上传时间:2023-08-13 格式:DOCX 页数:70 大小:53.89KB
下载 相关 举报
MIPS体系结构.docx_第1页
第1页 / 共70页
MIPS体系结构.docx_第2页
第2页 / 共70页
MIPS体系结构.docx_第3页
第3页 / 共70页
MIPS体系结构.docx_第4页
第4页 / 共70页
MIPS体系结构.docx_第5页
第5页 / 共70页
点击查看更多>>
下载资源
资源描述

MIPS体系结构.docx

《MIPS体系结构.docx》由会员分享,可在线阅读,更多相关《MIPS体系结构.docx(70页珍藏版)》请在冰豆网上搜索。

MIPS体系结构.docx

MIPS体系结构

MIPSCPU体系结构概述http:

//www.xtrj.org/mips/

陈怀临

1。

序言

本文介绍MIPS体系结构,着重于其寄存器约定,MMU及存储管理,异常和中断处理等等。

通过本文,希望能提供一个基本的轮廓概念给对MIPSCPU及之上OS有兴趣的读者。

并能开始阅读更详细的归约(SPECIFICATION)资料。

MIPS是最早的,最成功的RISC(ReducedInstructionSetComputer)处理器之一,起源于StanfordUniv的电机系.其创始人JohnL.Hennessy在1984年在硅谷创立

了MIPSINC.公司()。

JohnL.Hennessy目前是StanfordUniv.的校长。

在此之前,他是Stanford电子工程学院的Dean。

CS专业的学生都知道两本著名的书:

“ComputerOrganizationandDesign:

TheHardware/SoftwareInterface”和

”ComputerArchitecture:

AQuantitativeApproach“。

其Co-author就是Hennessy.

MIPS的名字为“Microcomputerwithoutinterlockedpipelinestages"的缩写。

另外一个通常的非正式的说法是”Millionsofinstructionspersecond".

MIPS芯片在工业界目前用的比较多的是:

MIPSINC。

的R10000;QED(。

1996年从MIPSINC。

分(SPINOFF)出来的)的R5000,R7000等。

指令集

详细的资料请参阅MIPS归约。

一般而言,MIPS指令系统有:

MIPSI;MIPSII;MIPSIII和MIPSIV。

可想而知,指令系统是向后兼容的。

例如,基于MIPSII的代码可以在MIPIII和MIPSIV的处理器上跑一跑:

-)

下面是当我们用gcc时,如何指定指令和CPU的选项。

-mcpu=cputype

Assumethedefaultsforthemachinetypecputypewhenschedulinginstructions.Thechoicesforcputypeare`r2000',`r3000',`r4000',`r4400',`r4600',

and`r6000'.Whilepickingaspecificcputypewillschedulethingsappropriatelyforthatparticularchip,thecompilerwillnotgenerateanycodethatdoes

notmeetlevel1oftheMIPSISA(instructionsetarchitecture)withoutthe`-mips2'or`-mips3'switchesbeingused.

-mips1

Issueinstructionsfromlevel1oftheMIPSISA.Thisisthedefault.`r3000'isthedefaultcputypeatthisISAlevel.

-mips2

Issueinstructionsfromlevel2oftheMIPSISA(branchlikely,squarerootinstructions).`r6000'isthedefaultcputypeatthisISAlevel.

-mips3

Issueinstructionsfromlevel3oftheMIPSISA(64bitinstructions).`r4000'isthedefaultcputypeatthisISAlevel.ThisoptiondoesnotchangethesizesofanyoftheCdatatypes.

读者可能发现,对于大多数而言,我们应该是用MIPSIII或-mips3。

要提醒的是R5000和R10000也都是R4000的延伸产品。

下面是几点补充:

*MIPS指令是32位长,即使在64位的CPU上。

这对于局部跳转指令的理解很有帮助。

比如:

J(TARGET);JAL(TARGET)。

J和JAL的OPERCODE是6位,剩下的26为存放跳转偏移量。

由于任何一个指令都是32位(或4字节)对齐(ALIGN)的,所以J和JAL最大的伸缩空间是2^28=256M。

如果你的程序要作超过256M的跳转,你就必须用JALR或JR,通过一个GPR寄存器来存放你的跳转地址。

由于一个寄存器是32或64位的,你就没有任何限制了。

*MIPSCPU的SR(STATUSREGISTER)中有几位是很重要的设置,当我们选择指令系统或要用64位的MIPS的CPUCORE在32模式下(绝大多数情况,弟兄们别告诉我你在写64位的程序:

--))。

SR[XX]:

1:

MIPSIVINSTRUCTIONSETUSABLE

0:

MIPSIVINSTRUCTIONSETUNUSABLE

SR[KX]

SR[SX]

SR[UX]:

0:

CPU工作在32位模式下

1:

CPU工作在64位模式下

一般而言,如果你要从头写一个MIPS核心为32位程序,最好把上述值设为0。

为什么最好呢?

因为我在工作中没有去冒风险,设她们为1,whoknowswhatwouldhappen?

:

-)Andthenwhybother:

--)?

*在以后我们会单独的一章讲将流水线和指令系统,特别是跳转指令的关系。

在这里,我们只简单提一下。

对任何一个跳传指令后面,FORSIMPLITY,要加上一个空转指令(NOP)。

从而使得CPU的PIPELINE不会错误的执行一个预取(PRE_FETCH)得指令。

当然这个NOP可以替换为别的。

以后再讲。

放一个NOP是最简单和安全的。

有兴趣的读者可以用mips64-elf-objdump-d来反汇编一个

OBJECT文件。

你就会一目了然了。

*一定要记住:

MIPSI,II,III和IV指令系统不包含PRIVILEDGEDINSTRUCTIONS。

换句话说,都是那些在USERMODE下可以用的指令(当然KERNEL下也能用)。

对于CPO的操作不属于指令系统。

*有一点在MIPSCPU下,要千万注意:

ALIGN。

MIPS对ALIGN的要求是严厉的。

这一点与POWERPC是天壤之别。

指令必须是32位对齐。

数据类型必须在她们的的

大小边界对齐。

简单的比如:

WhenCPUrunningunder32bitmode,intmust32bitaligned;long32bitaligned;pointermustbe32bitaligned;charmust8bitaligned.longlongmust64bitaligned;关于这一点,我是吃过苦头的。

当然我知道大家还会犯错在这里:

--),即使知道了。

有些事情学是没用的:

--)。

一定要注意。

*我建议读者阅读SPECIFICATION时要花时间看一看指令系统的定义。

其实不难。

每一种指令不外乎几个域(FIELDS)。

寄存器约定

对于在一个CPU上进行开发,掌握其工作的CPU的寄存器约定是非常重要的。

MIPS体系结构提供了32个GPR(GENERALPURPOSEREGISTER)。

这32个寄存器的用法大致如下:

REGISTERNAMEUSAGE

$0$zero常量0(constantvalue0)

$2-$3$v0-$v1函数调用返回值(valuesforresultsandexpressionevaluation)

$4-$7$a0-$a3函数调用参数(arguments)

$8-$15$t0-$t7暂时的(或随便用的)

$16-$23$s0-$s7保存的(或如果用,需要SAVE/RESTORE的)(saved)

$24-$25$t8-$t9暂时的(或随便用的)

$28$gp全局指针(GlobalPointer)

$29$sp堆栈指针(StackPointer)

$30$fp帧指针(FramePointer)

(BNN:

fpisstaleacutally,andcanbesimplyusedas$t8)

$31$ra返回地址(returnaddress)

对一个CPU的寄存器约定的正确用法是非常重要的。

当然对C语言开发者不需要关心,因为COMPILER会TAKECARE。

但对于KERNEL的开发或DRIVER开发的人就**必须**清楚。

一般来讲,你通过objdump-d可以清醒的看到寄存器的用法。

下面通过我刚才写的一个简单例子来讲解:

~/viHello.c

"Hello.c"[Newfile]

/*Exampletoillustratemipsregisterconvention

*-Author:

BNN

*11/29/2001

*/

intaddFunc(int,int);

intsubFunc(int);

voidmain()

{

intx,y,z;

x=1;

y=2;

z=addFunc(x,y);

}

intaddFunc(intx,inty)

{

intvalue1=5;

intvalue2;

value2=subFunc(value1);

return(x+y+value2);

}

intsubFunc(intvalue)

{

returnvalue--;

}

上面是一个C程序,main()函数调用一个加法的子函数。

让我们来看看编译器是如何产生代码的。

~/bnn:

74>/bin/mips-elf-gcc-cHello.oHello.c-mips3-mcpu=r4000-mgp32-mfp32-O1

~/bnn:

75>/bin/mips64-elf-objdump-dHello.o

Hello.o:

fileformatelf32-bigmips

Disassemblyofsection.text:

/*mainFunction*/

0000000000000000:

/*createastackframebymovingthestackpointer8

*bytesdownandmeantimeupdatethespvalue

*/

0:

27bdfff8addiu$sp,$sp,-8

/*Savethereturnaddresstothecurrentspposition.*/

4:

afbf0000sw$ra,0($sp)

8:

0c000000jal0

/*nopisforthedelayslot*/

c:

00000000nop

/*Filltheargumenta0withthevalue1*/

10:

24040001li$a0,1

/*JumptheaddFunc*/

14:

0c00000ajal28

/*NOTEHERE:

Whywefillthesecondargument

*behindtheaddFuncfunctioncall?

*Thisisallaboutthe"-O1"compilationoptimizaiton.

*Withmipsarchitecture,theinstrucitonafterjump

*willalsobefetchedintothepiplineandget

*exectuted.Therefore,wecanpromisethatthe

*secondargumentwillbefilledwiththevalueof

*integer2.

*/

18:

24050002li$a1,2

/*Loadthereturnaddressfromthestackpointer

*Noteherethattheresultv0containstheresultof

*addFuncfunctioncall

*/

1c:

8fbf0000lw$ra,0($sp)

/*Return*/

20:

03e00008jr$ra

/*Restorethestackframe*/

24:

27bd0008addiu$sp,$sp,8

/*addFuncFunction*/

0000000000000028:

/*Createastackframebyallocating16bytesor4

*wordssize

*/

28:

27bdfff0addiu$sp,$sp,-16

/*Savethereturnaddressintothestackwith8bytes

*offset.Pleasenotethatcompilerdoesnotsavethe

*rato0($sp).

*Thinkofwhy,incontrastofthepreviousPowerPC

*EABIconvention

*/

2c:

afbf0008sw$ra,8($sp)

/*Wesavethes1reg.valueintothestack

*becausewewilluses1inthisfunction

*Notethatthe4,5,6,7($sp)positionswillthen

*beoccupiedbythis32bitssizeregister

*/

30:

afb10004sw$s1,4($sp)

/*Withesamereason,saves0reg.*/

34:

afb00000sw$s0,0($sp)

/*Retrievetheargument0intos0reg.*/

38:

0080802dmove$s0,$a0

/*Retrievetheargument1intos1reg.*/

3c:

00a0882dmove$s1,$a1

/*CallthesubFuncwitha0with5*/

40:

0c000019jal64

/*Inthedelayslot,weloadthe5intoargumenta0reg

*forsubFunccall.

*/

44:

24040005li$a0,5

/*s0=s0+s1;notethats0ands1holdsthevaluesof

*x,y,respectively

*/

48:

02118021addu$s0,$s0,$s1

/*v0=s0+v0;v0holdsthereturnresultsofsubFunc

*call;Andweletv0holdthefinalresults

*/

4c:

02021021addu$v0,$s0,$v0

/*Retrievetheravaluefromstack*/

50:

8fbf0008lw$ra,8($sp)

/*!

!

!

!

restorethes1reg.value*/

54:

8fb10004lw$s1,4($sp)

/*!

!

!

!

restorethes0reg.value*/

58:

8fb00000lw$s0,0($sp)

/*Returnbacktomainfunc*/

5c:

03e00008jr$ra

/*Update/restorethestackpointer/frame*/

60:

27bd0010addiu$sp,$sp,16

/*subFuncFunction*/

0000000000000064:

/*returnbacktoaddFuncfunction*/

64:

03e00008jr$ra

/*Takingadvantageofthemipsdelayslot,fillingthe

*resultregv0bysimplyassigningthev0asthevalue

*ofa0.Thisisabugfrommycsource

*codes--"value--".Ishouldwritemycodes

*like"--value",instead.

68:

0080102dmove$v0,$a0

希望大家静下心来把上面的代码看懂。

一定要注意编译器为什么在使用s0和s1之前要先把她们SAVE起来,然后再RESTORE,虽然在这个例子中虽然main函数没用s0和s1。

另外的一点是:

由于我们加了“-O1”优化,编译器利用了“delayslot"来执行那些必须执行的指令,而不是简单的塞一个”nop"指令在那里。

非常的漂亮。

最后,考大家一个问题,为了使得大家更加理解寄存器的用法:

*在写一个核心调度contextswitch()例程时,我们需要SAVE/RESTORE$t0-$t7吗?

如果不,为什么?

*在写一个时钟中断处理例程时,我们需要SAVE/RESTORE$t0-$t7吗?

如果是,为什么?

MMU和MemoryManagement

对于MIPS的MMU和MemoryManagement,thefirstandyetimportantoneweneed

always

keepinmindis:

Noreal-mode

没有实模式。

这一点是MIPSCPU的一个很重要的特点(或缺点)。

我们会问了:

BNN,Givemeabreak.WithoutCPUrunninginthereal-mode,

howcouldyoubootupakernel?

Well,hereisthething:

Bydefault,MIPSarchitecture,whenpoweron,hasenabled/mappedtwomemory

areas.Inotherwords,thosetwomemoryareasaretheplaceswhereyour

bootcodesHAVETOresidentandrunontopof.Ifyoureadthemakefiles

ofMIPSlinuxsourcetree,youwouldeasilyfindtheinfor.Forexample,

0x8000xxxxorsomethingslikethat.

*MIPS存储体系结构

我们在这里不谈64位CPU,只谈32位的。

MIPS将存储空间划分为4大块--kuseg,kseg0,kseg1andkseg2.

------------------------------------------------------------------

0xFFFFFFFF

mappedkseg2

0xC0000000

unmappeduncachedkseg1

0xA0000000

unmappedcachedkseg0

0x80000000

2Gkuseg

0x00000000

------------------------------------------------------------------

对于上述图表,弟兄们要记住以下几点:

*当开电(PowerOn)的时候,只有kseg0andkseg1是可以存取的。

*kseg0512M(From0x80000000to0xA0000000)areDIRECTLYmappedtophyiscal_

memoryrangingfrom0x00000000to0x20000000,withcache-able(eitherwrite

backorwritethrough,whichisdecidedbySR(StatusRegisterofMIPSCPU)_

*kseg1512M(From0xA0000000to0xC0000000)are(also)DIRECTLymapped

tophysicalmemoryrangingfrom0x00000000t00x20000000,withnon-cachable.

以上两点对于理解MIPSOS的启动是至关重要的。

细心的读者会发现:

kseg1有点象

其他CPU的real-mode方式。

*(虚拟)地址from0x00000000to0x80000000是不可以存取的,在加电时(POWER

ON)!

必须等到MMUTLB初始化之后才可以。

*同理对地址from0xC0000000to0xFFFF0000

*MIPS的CPU运行有3个态--UserMode;SupervisorModeandKernelMode.

Forsimplicity,let'sjust

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 表格类模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1