<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jack&#039;s Lab &#187; ISA</title>
	<atom:link href="http://www.jackslab.org/?feed=rss2&#038;tag=isa" rel="self" type="application/rss+xml" />
	<link>http://www.jackslab.org</link>
	<description>好奇之心，改变之力</description>
	<lastBuildDate>Sun, 02 Jul 2017 02:48:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>PowerPC 体系结构之存储管理</title>
		<link>http://www.jackslab.org/?p=239</link>
		<comments>http://www.jackslab.org/?p=239#comments</comments>
		<pubDate>Tue, 22 Feb 2011 03:32:44 +0000</pubDate>
		<dc:creator>Jack Tan</dc:creator>
				<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[基础设施]]></category>
		<category><![CDATA[ISA]]></category>
		<category><![CDATA[TLB]]></category>
		<category><![CDATA[存储管理]]></category>

		<guid isPermaLink="false">http://www.jackslab.org/?p=239</guid>
		<description><![CDATA[取 BOOKE 精要，兼顾 E500 规范。 E500 规范是 BOOKE 的 32-bit 实现，更详细些，大部与 BOOKE 兼容。 BOOKE 对存储管理的规范较抽象，没有非常多的细节（比如 TLB 每项的结构必须如此等等），涉及细节则多以 ...]]></description>
			<content:encoded><![CDATA[<p>取 BOOKE 精要，兼顾 E500 规范。 E500 规范是 BOOKE 的 32-bit 实现，更详细些，大部与 BOOKE 兼容。</p>
<p>BOOKE 对存储管理的规范较抽象，没有非常多的细节（比如 TLB 每项的结构必须如此等等），涉及细节则多以 E500 为例子。<br />
<strong><br />
<span style="color: #ff9900;"> 1. 概述</span></strong></p>
<p>E500 实现有两级 TLB，即：L1 TLB 和 L2 TLB。L1 TLB 可以理解为 L2 TLB 的部分缓存。访问 L1 TLB 的效率要比 L2 的效率高，相应的实现的花费也就高。L1 TLB 由硬件维护，不可编程精确控制。故下面的讨论皆针对 L2 TLB，为方便简称其为 TLB。</p>
<p>E500 没有对虚拟地址空间进行划分，即没有固定使用某段虚拟地址固定映射到某段物理地址 (MIPS，主要用于支持设备资源的固定映射以及方便内核对内存的管理)。而是引入了一个更灵活的设计：将 TLB 分为 TLB0 和 TLB1。</p>
<p>TLB0 即用于页映射的 TLB，可动态被替换，页大小固定为 4 KB。E500v1 实现为 2 路组相联，256 项；E500v2 实现为 4 路组相联，512 项。</p>
<p>TLB1 则设计用于映射大页（比如 16MB, 256MB &#8230;），支持可变页大小，E500v1 可支持 9 个页大小（最大 256MB），E500v2 则支持 11 个页大小（最大 4GB）。使用时可将某项设为永驻 TLB1 （通过置 Invalidation Protection 位，简写为 IPROT 位），不会被动态替换，实现为全相联，共 16 项，可将其理解为用于映射 16 个段的可编程固定映射机制。</p>
<p><span id="more-239"></span></p>
<p><span style="color: #3d85c6;"><strong>2. TLB 结构与工作方式</strong></span></p>
<p><strong>2.1 TLB 结构</strong></p>
<p>E500 之 TLB0 与 TLB1 每项的数据格式相似，皆由页区分域、翻译域、访问控制域和存储属性位组成。</p>
<p><strong>2.1.1  页区分域 </strong></p>
<p>页区分域 (Page Identificaion Fields) 即为查找 TLB 时的比对域。包括 EPN (Effective Page Number)，TS (Translation Address Space, 1 bit)，TID (Translation ID)，V (Valid, 1 bit)，SIZE (Page Size, 4 bits)。其中 EPN 即为虚页号。</p>
<p>PowerPC 习惯上将地址转换时需要比对的位 (IS/DS | PID | EPN) 的组合，叫做一个地址空间。<br />
其中 IS/DS 为 Instruction/Data Address Space，各 1 bit，位于 MSR，0 为地址空间 0，1 则为地址空间 1，转换时其于 TLB_Entry 之 TS 相比较，相等才会输出物理页号；</p>
<p>PID 为 Process ID，本意是用于区分不同进程的虚拟地址空间，存放于 PIDR 中，属上下文。转换时，比较 PIDR 与 TLB_Entry 之 TID 位，相等才会输出物理页号。BOOKE 规定需实现一个 PID 寄存器；E500 作了扩展，其实现有 3 个 PIDR (PID0 ~ 2)，则 E500 在转换时会形成 3 个虚拟地址。</p>
<p>将 TLB_Entry 之 TID 置 0，则硬件会忽略 PID0 ~ 2 与 TID 的比较，PowerPC Linux 设计时，就将 TID 置 0。</p>
<p><strong>2.1.2  翻译域 </strong></p>
<p>翻译域 (Translation Field) 即为经 TLB 翻译后输出的数据，其实即为物理页号，PowerPC 叫 RPN (Real Page Number)<br />
<strong> </strong></p>
<p><strong> </strong> <strong>2.1.3  访问控制域</strong></p>
<p>访问控制域 (Access Control Fields) 又称为 PERMIS，共 6 bits，分别指定该页可否被用户态读、写、可执行 (UR, UW, UX)；管理态（核心态）的读、写、可执行 (SR, SW, SX)</p>
<p><strong>2.1.4  存储属性位</strong></p>
<p>存储属性位 (Storage Attribute Bits) ，其重要的 5 bits 为： W (Write through), I (caching Inhibited), M (Memory coherence), G (Guarded), E (Endianness)，一般简写为 WIMGE；</p>
<p>E500 还实现有可用于系统软件的 X0~1，可用于用户软件的 U0 ~ U3</p>
<p>此外E500 之 TLB1 还有一位无效保护位 IPROT，置位则该项不会被置无效。</p>
<p><strong>2.1.5 完整的 E500 TLB Entry 结构</strong><br />
<a href="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.entry_.structure.png"><img class="aligncenter size-full wp-image-250" title="tlb.entry.structure" src="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.entry_.structure.png" alt="" width="571" height="390" /></a></p>
<p><strong>2.2 TLB 工作方式<br />
</strong></p>
<p><strong><a href="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.org_.e500v1.png"><img class="aligncenter size-full wp-image-252" title="tlb.org.e500v1" src="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.org_.e500v1.png" alt="" width="522" height="450" /></a></strong></p>
<p><strong><a href="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.addr_.translate.png"><img class="aligncenter size-full wp-image-249" title="tlb.addr.translate" src="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.addr_.translate.png" alt="" width="484" height="268" /></a></strong></p>
<p><strong><a href="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.match.process.png"><img class="aligncenter size-full wp-image-251" title="tlb.match.process" src="http://www.jackslab.org/wp-content/uploads/2011/02/tlb.match.process.png" alt="" width="518" height="252" /></a></strong></p>
<p><strong><a href="http://www.jackslab.org/wp-content/uploads/2011/02/access.control.process.png"><img class="aligncenter size-full wp-image-240" title="access.control.process" src="http://www.jackslab.org/wp-content/uploads/2011/02/access.control.process.png" alt="" width="495" height="224" /></a></strong></p>
<p><span style="color: #a64d79;"><strong>3. TLB 控制接口</strong></span></p>
<p><strong> 3.1  相关寄存器</strong></p>
<p><strong>3.1.1</strong> <strong>MAS0 ~ 4, MAS6, MAS7</strong></p>
<p>MMU Assist Registers, 用于与 TLB Entry 之间的数据交换</p>
<p>MAS0，32 bits，用于选择交换对象是 TLB0  还是 TLB1 (TLBSEL)，以及是TLB1 的哪个 Entry  或者 TLB0 的哪一路 (ESEL)：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas0.png"><img class="aligncenter size-full wp-image-242" title="mas0" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas0.png" alt="" width="539" height="99" /></a></p>
<p>MAS1，32 bits，用于存放 V, IPROT, TID, TS, TSIZE：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas1.png"><img class="aligncenter size-full wp-image-243" title="mas1" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas1.png" alt="" width="529" height="99" /></a></p>
<p>MAS2，32 bits，用于存放 EPN | X0 | X1 | W | I | M | G | E：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas2.png"><img class="aligncenter size-full wp-image-244" title="mas2" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas2.png" alt="" width="538" height="101" /></a></p>
<p>MAS3，32 bits，用于存放 RPN | U0 &#8211; U3 | UX | SX | UW | SW | UR |SR：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas3.png"><img class="aligncenter size-full wp-image-245" title="mas3" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas3.png" alt="" width="532" height="102" /></a></p>
<p>MAS4，32 bits，用于加上 TLB Miss 的处理，存放默认的 TLBSEL,  TIDSEL,  TSIZE,  X0, X1, WIMGE，当 I/D TLB Miss 出现时，硬件自动将 MAS4 中的值写到 MAS0 ~ 2 的相应域中：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas4.png"><img class="aligncenter size-full wp-image-246" title="mas4" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas4.png" alt="" width="536" height="100" /></a></p>
<p>MAS6，32 bits，用于 tlbsx 查找 TLB  时指定 PID0 (SPID0) 和 AS (SAS)</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas6.png"><img class="aligncenter size-full wp-image-247" title="mas6" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas6.png" alt="" width="540" height="96" /></a></p>
<p>MAS7，32 bits，E500v2 实现，用于支持 36 bits 物理地址，即其 MAS7[60:63] 用作 RPN 的高四位：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/mas7.png"><img class="aligncenter size-full wp-image-248" title="mas7" src="http://www.jackslab.org/wp-content/uploads/2011/02/mas7.png" alt="" width="539" height="99" /></a></p>
<p><strong>3.1.2</strong> <strong>MMUCSR0</strong></p>
<p>MMU Control and Status Register 0，用于控制 TLB 的批量无效。有 2 个有效位：位 61 和位 62，其余保留为 0。</p>
<p>MMUCSR0[61]，置 1 则将 TLB0 的所有项置无效</p>
<p>MMUCSR0[62]，置 1 则将 TLB1 的所有项置无效</p>
<p><strong>3.1.3 MMU 配置状态寄存器</strong></p>
<p>MMUCFG, TLB0CFG, TLB1CFG，皆为只读。</p>
<p>MMUCFG 存放当前实现的 PID Register 的数目，PID Register 中 PID 的有效位（e500 为 8），实现的 TLB 个数（e500 为 2，TLB0 和 TLB1）</p>
<p>TLB0CFG 指示 TLB0 的特性，如：几路组相联 （e500v1 为 2，e500v2 为4），最小页大小和最大页大小（TLB0 皆为 4KB），是否支持 IPROT 位（TLB0 不支持），是否支持可变页大小（TLB0 不支持，则 AVAL = 0），有多少 Entry</p>
<p>TLB1CFG 指示 TLB1 的特性，数据域与  TLB0CFG 同。</p>
<p><strong> 3.2 相关指令</strong></p>
<p>tlbsx RA, RB &#8212; TLB Search Indexed<br />
tlbre &#8212; TLB Read Entry<br />
tlbwe &#8212; TLB Write Entry<br />
tlbivax RA, RB &#8212; TLB Invalidate Virtual Address Indexed<br />
tlbsync &#8212; TLB Sync</p>
<p><strong>3.3 实例</strong></p>
<p><strong>3.3.1 查找 TLB</strong></p>
<p>输入： MAS6，指定 PID0 (SPID0) 和 AS (SAS)<br />
执行 tlbsx RA, RB，在 TLB 中查找有效地址 RA + RB</p>
<p>若命中，则将命中项之数据输出到：MAS0 ~ MAS3，MAS1[V] = 1，MAS0[TLBSEL] 指定命中的是 TLB0 还是 TLB1，MAS0[ESEL] 指定命中项是TLB1 的哪个 Entry  或者 TLB0 的哪一路。</p>
<p>若没找到，则 MAS1[V] = 0，MAS2[RPN] 为 0</p>
<p><strong>3.3.3 写 TLB </strong></p>
<p>输入：MAS0 ~ 3 (MAS7 for E500v2)<br />
执行  tlbwe</p>
<p>其据 MAS0[TLBSEL]  和  MAS0[ESEL]  选择将被写的 TLB 入口（若为 TLB0，还需借助 EPN[45:51] 用于索引组，ESEL 用于路选），然后将 MAS0 ~ 3 (MAS7 for E500v2) 中的数据写入 TLB。</p>
<p><strong>3.3.4 读 TLB</strong><br />
<strong><br />
</strong>输入：MAS0[TLBSEL], MAS0[ESEL], MAS2[EPN]<br />
执行  tlbre<br />
输出：MAS1 ~ MAS3，若为 E500v2 且 HID0[EN_MAS7_UPDATE] 则将 RPN 的高 4 位置入  MAS7<br />
<strong> </strong></p>
<p><strong>3.3.2  置无效某项</strong></p>
<p>输入：无需借助 MAS 寄存器<br />
执行 tlbivax RA + RB</p>
<p>EA = RA + RB，为虚拟地址<br />
EA[32:51] 用于匹配 TLB 项 （组选 ＋ EPN 匹配），其不进行 PID 和 AS 的比较，则若同一组内有相同的 EPN，皆会将其置无效。<br />
EA[60] 用于选择操作的对象是 TLB0 还是 TLB1，类似 MAS0[TLBSEL]<br />
EA[61] 为 1 则置无效 TLB0 或 TLB1 的所有项</p>
<p>若 HID1[ABE] = 1 则该无效操作亦广播给其它 Core，置无效相应的项。</p>
<p>注意： TLB1 之 IPROT 位为 1 可使匹配的项免于被置无效</p>
<p><span style="color: #6aa84f;"><strong>4. TLB 相关异常</strong></span></p>
<p>Instruction TLB Error  异常，由 Instruction  TLB Miss  引起，用于从页表填充 TLB<br />
Data TLB Error 异常，由 Data TLB Miss 引起<br />
Instruction Storage 异常，由不允许的访问引起，如用户态读一个 UR 为 0（用户态不可读）的页<br />
Data Storage 异常，亦由不允许的访问引起</p>
<p><strong><span style="color: #674ea7;">5. Reset 后 TLB 的状态</span></strong></p>
<p>E500 上电后， TLB0 和 TLB1 的所有项都会被硬件自动置无效，后将 TLB1 的第一项自动初始化为：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/tlb1.entry0_.png"><img class="aligncenter size-full wp-image-253" title="tlb1.entry0" src="http://www.jackslab.org/wp-content/uploads/2011/02/tlb1.entry0_.png" alt="" width="409" height="299" /></a></p>
<p>原因为： E500 在上电后，固定到虚拟地址 0xFFFF FFFC 处取指，但其既无实模式 (x86) 又无固定映射 (MIPS)，所以就要求 TLB 中至少有一项，映射到初始化代码处（位于 Flash 的 bootloader），故E500 规定，上电后 TLB1 的第一项始终映射 0xFFFF F000 到物理地址 0xFFFF F000 处，大小为 4KB。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jackslab.org/?feed=rss2&#038;p=239</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerPC 体系结构之中断异常</title>
		<link>http://www.jackslab.org/?p=230</link>
		<comments>http://www.jackslab.org/?p=230#comments</comments>
		<pubDate>Tue, 22 Feb 2011 03:14:53 +0000</pubDate>
		<dc:creator>Jack Tan</dc:creator>
				<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[ISA]]></category>
		<category><![CDATA[中断]]></category>
		<category><![CDATA[异常]]></category>

		<guid isPermaLink="false">http://www.jackslab.org/?p=230</guid>
		<description><![CDATA[取 BOOKE 之精要。 1. 异常类型 00 Critical Interrupt     来自于外部中断控制器，具有较高的优先级 01 Machine Check    严重的内部状态错误，如 Cache 数据的校验失败 02  Data ...]]></description>
			<content:encoded><![CDATA[<p>取 BOOKE 之精要。</p>
<p><strong>1. 异常类型</strong></p>
<p><span style="color: #ff0000;"> 00</span> Critical Interrupt     来自于外部中断控制器，具有较高的优先级<br />
<span style="color: #ff0000;"> 01</span> Machine Check     严重的内部状态错误，如 Cache 数据的校验失败<br />
02  Data Storage     数据读写异常，如：用户态读一个非用户态的页 (UR=0)<br />
03  Instruction Storage    读指令异常，如：用户态时取一个用户态不可执行的页 (UX=0)<br />
<span style="color: #0baa20;"> 04</span> External Interrupt     来自于外部中断控制器<br />
05  Alignment     非对齐访问异常<br />
<span style="color: #0baa20;"> 06</span> Program     程序异常，如：执行非法指令，用户态执行特权指令<br />
07  Floating-Point unavailable    在无浮点部件的 CPU 上执行浮点指令即会触发此异常<br />
<span style="color: #0baa20;"> 08</span> System call     系统调用<br />
09  Auxiliary Processor Unavailable    在无协处理器的 CPU 上执行协处理器指令即触发此异常<br />
10     Decrementer     DEC 寄存器归零异常，DEC 是一个内部时钟计数器，Linux 用之实现时钟中断<br />
11     Fixed-interval timer interrupt<br />
<span style="color: #ff0000;"> 12</span> Watchdog timer interrupt<br />
<span style="color: #0baa20;"> 13</span> Data TLB error     数据 TLB Miss 异常<br />
<span style="color: #0baa20;"> 14</span> Instruction TLB error     指令 TLB Miss 异常<br />
<span style="color: #ff0000;"> 15</span> Debug     调试异常，用于支持调试</p>
<p>16 &#8211; 31    Reserved for future use    保留给将来体系结构升级用<br />
32 &#8211; 63   Allocated for implementation-dependent use   具体实现相关</p>
<p>其中 0，1，12，15 为 Critical Exception，当其发生时，使用 CSRR0 &amp; CSRR1 保存当前 PC 或 (PC + 4) 和 MSR；其他异常发生时，则使用 SRR0 &amp; SRR1 保存当前 PC 或 (PC + 4) 和 MSR</p>
<p>可以看到 BOOKE 体系结构层面规定的异常即为前 16 个，这其中的有些异常是个笼统的抽象（比如 Data Storage 就需要区分是读还是写导致的），为了更细地描述发生异常的原因，PowerPC 引入了一个 ESR (Exception Syndrome Register)，让硬件在异常发生时，在其中指出更具体的原因。比如 若 ESR[40] 被置位，则说明异常是由写操作引起的。</p>
<p><span id="more-230"></span></p>
<p><strong>2. 异常入口（向量）<br />
</strong><br />
BOOKE 使用可读写的内部寄存器 IVPR 和 IVOR 来指定异常的入口。</p>
<p>其中 IVPR (Interrupt Vector Prefix Register) 为 64 bit，指定所有异常入口基地址的高 48 bit，即 IVPR[48:63] 始终为 0</p>
<p>IVOR (Interrupt Vector Offset Register) 为 32 bit，指定具体异常入口相对异常基地址的偏移，每个异常一个，只使用其低 16 位。则其 IVOR[32:40] 为 0；又因所有入口 16 字节对齐，实际上 IVOR[60:63] 亦始终 0：</p>
<p>IVOR00           Critical Interrupt<br />
IVOR01           Machine Check<br />
IVOR02           Data Storage<br />
IVOR03           Instruction Storage<br />
IVOR04           External Interrupt<br />
IVOR05           Alignment<br />
IVOR06           Program<br />
IVOR07           Floating-Point unavailable<br />
IVOR08           System call<br />
IVOR09           Auxiliary Processor Unavailable<br />
IVOR10           Decrementer<br />
IVOR11           Fixed-interval timer interrupt<br />
IVOR12           Watchdog timer interrupt<br />
<strong>IVOR13 </strong> Data TLB error<br />
IVOR14           Instruction TLB error<br />
IVOR15           Debug<br />
IVOR16 ~ IVOR31<br />
IVOR32 ~ IVOR63</p>
<p>则 Data TLB Miss 的异常入口即为： IVPR[0:47] || IVOR[48:59] || 0b0000</p>
<p><strong>注意：</strong>PowerPC 没有 RESET 异常这个概念，故没有 RESET 的入口，上电后处理器直接到固定地址去取指令(E500 上为 0xFFFF FFFC)。</p>
<p><strong>3. 相关寄存器</strong></p>
<p><strong> 3.0 MSR </strong>(Machine Status Register)</p>
<p>内含部分异常使能位，清位则屏蔽相应的异常：</p>
<p>MSR[46], CE (Critical Enable) &#8212; Critical Input and Watchdog Timer Interrupts Enable<br />
MSR[48], EE (External Enable) &#8212; External Input, Decrementer and Fixed-Interval Timer Interrupts Enable<br />
MSR[51], ME (Machine Check Enable) &#8212; Machine Check Enable<br />
MSR[54], DE (Debug Enable) &#8212; Debug Enable</p>
<p>MSR[49], PR (Proble State) &#8212; 置 1 表示处理器处于用户态，置 0 则为核心态</p>
<p>当 Critical Exception 发生时，硬件将 MSR 保存于 CSRR1 后，仅保持 ME 不变，自动将 MSR 之其它位清零（PR = 0，进入核心态）</p>
<p>当一般异常发生时，硬件将 MSR 保存于 SRR1 后，保持 CE，DE，ME 不变，自动将其它位清零</p>
<p><strong><br />
3.1 SRR0</strong> (Save/Restore Register 0)</p>
<p>64 bit，用于异常发生时保存引起异常指令的地址（异常）或其下一条指令的地址（中断）。<br />
保存过程硬件自动做<br />
执行 rfi 从异常返回时，处理器会跳转到 SRR0 保存的地址处继续执行。</p>
<p><strong> 3.2 SRR1 </strong>(Save/Restore Register 1)</p>
<p>32 bit，用于异常发生时硬件自动保存 MSR (Machine Status Register)<br />
执行 rfi 从异常返回时，处理器会将 SRR1 值恢复入 MSR</p>
<p><strong> 3.3 CSRR0</strong> (Critical Save/Restore Register 0)</p>
<p>64 bit，用于 Critical Exception (0, 1, 12, 15)<br />
其它与 SRR0 同，只是该类型异常使用指令 rfci 返回</p>
<p><strong> 3.4 CSRR1</strong> (Critical Save/Restore Register 1)</p>
<p>32 bit，用于 Critical Exception (0, 1, 12, 15)<br />
其它与 SRR1 同，只是该类型异常使用指令 rfci 返回</p>
<p><strong> 3.5 DEAR</strong> (Data Exception Address Register)</p>
<p>64 bit，用于记录访存失败的地址，类似 MIPS 之 BadVAddr 或 x86 之 CR2</p>
<p><strong> 3.6 IVPR &amp; IVORi</strong></p>
<p>64 bit &amp; 32 bit，异常入口寄存器</p>
<p><strong> 3.7 ESR</strong> (Exception Syndrome Register)</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/esr.def_.png"><img class="aligncenter size-full wp-image-231" title="esr.def" src="http://www.jackslab.org/wp-content/uploads/2011/02/esr.def_.png" alt="" width="418" height="371" /></a></p>
<p><strong><br />
4. 完整的例子<br />
</strong><br />
以外设中断为例：</p>
<p>a. 外部中断控制器通过中断引脚 (#int) 触发处理器进入 External Input 异常<br />
b. 保存当前 PC + 4 入 SRR0 （异步，无需重新执行之，故下一条指令即可）<br />
c. 保存当前 MSR 入 SRR1，保持 MSR 之 CE, DE, ME，其余清除<br />
d. 跳转到入口 IVPR + IVOR4 处 （interrupt handler 之所在）<br />
e. interrupt handler 使用指令 rfi 返回，处理器在执行该指令时自动把 SRR1 恢复入 MSR，SRR0 入 PC</p>
<p>最后给一个 BOOKE 之异常的全家福：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/esr.def_.png"><img class="aligncenter size-full wp-image-231" title="esr.def" src="http://www.jackslab.org/wp-content/uploads/2011/02/esr.def_.png" alt="" width="418" height="371" /></a></p>
<p><strong>参考文献：</strong></p>
<p>[1] Book E: Enhanced PowerPC Architecture, V1.0, 2002.5</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jackslab.org/?feed=rss2&#038;p=230</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerPC 体系结构之指令集 (II)</title>
		<link>http://www.jackslab.org/?p=221</link>
		<comments>http://www.jackslab.org/?p=221#comments</comments>
		<pubDate>Tue, 22 Feb 2011 02:53:13 +0000</pubDate>
		<dc:creator>Jack Tan</dc:creator>
				<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[ISA]]></category>
		<category><![CDATA[指令集]]></category>

		<guid isPermaLink="false">http://www.jackslab.org/?p=221</guid>
		<description><![CDATA[3.3 整数指令 这类指令大致分为如下几类： 整数访存指令 整数算术运算指令 整数逻辑运算指令 整数比较指令 整数陷阱指令 整数移位指令 XER 指令 其中以整数循环移位指令最为特别。 3.3.1 整数访存指令 3.3.1.1 Load Byte/Half-word/Word ...]]></description>
			<content:encoded><![CDATA[<p><span style="color: #3399ff;"><strong> 3.3 整数指令</strong></span></p>
<p>这类指令大致分为如下几类：</p>
<p>整数访存指令<br />
整数算术运算指令<br />
整数逻辑运算指令<br />
整数比较指令<br />
整数陷阱指令<br />
整数移位指令<br />
XER 指令</p>
<p>其中以整数循环移位指令最为特别。</p>
<p><strong> 3.3.1 整数访存指令</strong></p>
<p><strong>3.3.1.1</strong> Load Byte/Half-word/Word and Zero</p>
<p>该类指令从指定地址处读取 8 位、16 位、32 位数据，置入 RT，RT  高位置 0</p>
<p>lbz/lbzu                           RT, D(RA)<br />
lbzx/lbzux                  RT,  RA, RB</p>
<p>lhz/lhzu                           RT, D(RA)<br />
lhzx/lhzux                  RT,  RA, RB</p>
<p>lwz/lwzu                        RT, D(RA)<br />
lwzx/lwzux                  RT,  RA, RB</p>
<p>RT, RA, RB 皆为 GPR，D 为有符号立即数。则有效地址的计算分别为：RA[32:63] + D，RA[32:63] + RB[32:63]，有效地址高 32 位置 0。</p>
<p>后缀 u 表示 Update，即将有效地址更新到 RA 中<br />
后缀 x 表示 Indexed，即使用 RA + RB 的寻址方式</p>
<p>以上用于 32 位，对 64 位，上述指令皆加后缀 &#8216;e&#8217;。则有效地址的 0 ~ 31 位， 不再置 0，其计算方式如下：RA + D，RA + RB。</p>
<p>此外，用于 64 位的还有对双字操作的支持：</p>
<p>lde/ldue/ldxe/lduxe<br />
<em><span id="more-221"></span></p>
<p></em><strong>3.3.1.2</strong> Load Half-word Algebraic</p>
<p>lha/lhau                           RT, D(RA)<br />
lhax/lhaux                  RT,  RA, RB<em></p>
<p></em>与 lhz 不同的是，该指令将所读取的半字的最高位 (RT[48]) 填充到 RT[32:47]，实际上就是形成一个 16 位的补码有符号数。</p>
<p>有效地址计算与上同；后缀 u, x 与上同。</p>
<p>对 64 位情形，上述指令皆加后缀 &#8216;e&#8217;，有效地址计算与上小节同。<br />
<em></p>
<p></em><strong>3.3.1.3</strong> <span style="color: #808000;">Load Halfword/Word Byte-Reverse</span><strong></p>
<p></strong>从指定地址处读取 16 位/32 位数据，将字节反转后置入 RT，RT 高位置 0<br />
<strong><br />
</strong> lhbrx        RT, RA, RB<br />
lwbrx        RT, RA, RB</p>
<p>如： lwbrx        r3, r2, r1，若 r2 + r1 地址处的数据为 0x55aa66bb，则 r3 的结果为 0xbb66aa55</p>
<p>对 64 位情形，上述指令皆加后缀 &#8216;e&#8217;，有效地址计算与上小节同。</p>
<p><strong>3.3.1.4</strong> <span style="color: #99cc00;">Load Multiple Word</span></p>
<p>lmw        RT, D(RA)</p>
<p>该指令将 RA + D 开始处的数据，顺序置入 RT ~ R31 中，共读取 31 &#8211; T 个字</p>
<p>该指令无 64 位扩展。</p>
<p><strong>3.3.1.5</strong> <span style="color: #99cc00;">Load String Word</span></p>
<p>lswi         RT, RA, NB               （后缀 i，表示立即数 Immediate）<br />
lswx         RT, RA, RB          （后缀 x，表示 Indexed 寻址方式）</p>
<p>加载 n 个字节到 RT  开始的寄存器中；<br />
当 NB == 0 时 n = 32； NB != 0 时 n = NB，NB 取值范围为 0 ~ 31</p>
<p>如 r3 = 0&#215;1000 ：</p>
<p>lswi        r4, r3, 16</p>
<p>则将 0&#215;1000 处的 16 字节，依次写入 r4, r5, r6, r7</p>
<p>对于 lswx，要加载的字节数则位于 XER[57:63]</p>
<p>该指令无 64 位扩展。</p>
<p><strong>3.3.1.6</strong> <span style="color: #009900;">Load Word/Doubleword and Reserve</span></p>
<p>lwarx         RT, RA, RB</p>
<p>该指令与 lwzx 的差别在于，其还将处理器内部的 RESERVE 位置为 1，并将有效地址对应的物理地址放入 RESERVE_ADDR 中。</p>
<p>该指令的 64 位版本为： lwarxe        RT, RA, RB，差别还是在于有效地址的 0 ~ 31 不被置 0</p>
<p>此外还有一个 ldarxe        RT, RA, RB，与 lwarxe 的差别在于其加载 8 字节的数据。</p>
<p>这三条指令常分别与 stwcx./stwcxe./stdcxe. 联用，用于实现锁操作，类似 MIPS 之 ll/sc 指令。</p>
<p><strong>3.3.1.7 </strong>Store<strong> </strong></p>
<p>stb/stbu                           RS, D(RA)<br />
stbx/stbux                  RS,  RA, RB<br />
sth/sthu                           RS, D(RA)<br />
sthx/sthux                  RS,  RA, RB<br />
stw/stwu                           RS, D(RA)<br />
stwx/stwux                  RS,  RA, RB</p>
<p>该类指令将 RS 中的 8 位、16 位、32 位数据写入有效地址处。后缀 &#8216;u&#8217;, &#8216;x&#8217; 之含义与 3.3.1.1 同。</p>
<p>上述 12 条指令加后缀 &#8216;e&#8217; 则用于 64 位。有效地址计算与与 3.3.1.1 同。</p>
<p>另用于 64 位的还有对双字操作的支持：</p>
<p>stde/stdue/stdxe/stduxe</p>
<p><strong>3.3.1.8</strong> <span style="color: #ffcc00;">Store Halfword/Word Byte-Reverse</span></p>
<p>sthbrx    RS, RA, RB<br />
stwbrx    RS, RA, RB</p>
<p>将 RS 中的 16/32 bit 的数据字节反转后置入有效地址处。该指令用于支持在大端系统上以小端序存储数据，亦或在小端系统上以大端序存储数据。</p>
<p>对 64 位情形，上述指令皆加后缀 &#8216;e&#8217;，有效地址计算与上小节同。</p>
<p><strong>3.3.1.9</strong> <span style="color: #ff9900;">Store Multiple Word</span></p>
<p>smw       RS, D(RA)</p>
<p>该指令将 RS ~ R31 中的数据 （一个字），写入到 RA + D 处</p>
<p>该指令无 64 位扩展。</p>
<p><strong>3.3.1.10</strong> <span style="color: #ff9900;">Store  String Word</span></p>
<p>stswi              RS, RA, NB           （后缀 i，表示立即数 Immediate）<br />
stswx          RS, RA, RB           （后缀 x，表示 Indexed 寻址方式）</p>
<p>与 lswi/lswx 的操作相反，其将 RS 开始的寄存器组中的 n 个字节，写入到有效地址处（位于 RA）</p>
<p>当 NB == 0 时 n = 32； NB != 0 时 n = NB，NB 取值范围为 0 ~ 31</p>
<p>如 r3 = 0&#215;1000 ：</p>
<p>stswi        r4, r3, 16</p>
<p>则将 r4, r5, r6, r7  中的 16 字节数据依次写入 0&#215;1000 处</p>
<p>对于 stswx，要加载的字节数则位于 XER[57:63]</p>
<p>该指令无 64 位扩展。</p>
<p><strong>3.3.1.11</strong> <span style="color: #ff6600;">Store  Word/Doubleword Conditional</span></p>
<p>stwcx.                RS, RA, RB</p>
<p>如果 RESERVE 位为 1，且 RA + RB 对应的物理地址与 RESERVE_ADDR 一致，则将 RS[32:63] 的内容写入到 RA + RB 处，将 CR0[eq] 位置为 1 后，再将 RESERVE 位复位为 0。</p>
<p>若条件不满足，则仅将 CR0[eq] 位置为 0</p>
<p>可用该指令与 lwarx 联用，实现 spin_lock：</p>
<p>li       r0, 1<br />
loop:<br />
lwarx       r4, 0, r3<br />
cmpwi      r4, 0                     # r4[32:63] 与 0 比较<br />
bne loop<br />
stwcw.       r0, 0, r3<br />
bne       loop<br />
isync</p>
<p>解锁则为：</p>
<p>msync<br />
li       r0, 0<br />
stw       r0, 0(r3)</p>
<p>下面的指令用于 64 位：</p>
<p>stwcxe.            RS, RA, RB<br />
stdcxe.            RS, RA, RB</p>
<p>差别在于有效地址的高 32 位不再被置为 0。</p>
<p><strong> 3.3.2 整数算术运算指令</strong></p>
<p>加、减、乘、除、取负</p>
<p><strong> 3.3.3 整数逻辑运算指令</strong></p>
<p>与、或、非、异或<br />
<strong><br />
3.3.4 整数比较指令</strong></p>
<p>cmp                   BF, L, RA, RB<br />
cmpi                BF, L, RA, SI                     # RA 与有符号立即数 SI 比较<br />
cmpl                BF, L, RA, RB                     # RA, RB 逻辑比较。l &#8212;&gt; logical<br />
cmpli                BF, L, RA, UI                     # RA 与无符号立即数 UI 逻辑比较</p>
<p>BF 取值 0 ~ 7，用于指定使用的 CR 域<br />
L 为 0，则为 32 位比较；为 1，则为 64 位比较</p>
<p>如：</p>
<p>cmpi              0, 0, r3, 5</p>
<p>若 r3 &gt; 5，则 CR0[gt] = 1；若 r3 &lt; 5，则 CR0[lt] = 1</p>
<p><strong> 3.3.5 整数陷阱指令</strong></p>
<p>tw                    TO, RA, RB<br />
twi            TO, RA, SI</p>
<p>TO 为立即数，5 位，从左到右标号为 0 ~ 4，依次表示小于、大于、等于、无符号小于、无符号大于。用于指定 Trap 的条件。<br />
SI： Signed Immediate</p>
<p>如：</p>
<p>twi       0&#215;10, r3, 5</p>
<p>则如果 r3 &lt; 5，则陷入异常。</p>
<p>以上用于单字 (32 bit) 比较，双字比较则用：</p>
<p>td                    TO, RA, RB<br />
tdi            TO, RA, SI</p>
<p><strong><br />
3.3.6 整数移位指令</strong></p>
<p><strong> 3.3.6.1</strong> <span style="color: #99cc00;"><strong>Rotate</strong></span></p>
<p>rlwimi                RA, RS, SH, MB, ME                            # Rotate Left Word Immediate then Mask Insert<br />
rlwinm                RA, RS, SH, MB, ME                            # Rotate Left Word Immediate then AND with Mask<br />
rlwnm                 RA, RS, RB, MB, ME                            # Rotate Left Word then AND with Mask</p>
<p>以下是该指令的一些例子：</p>
<p>all r11 is: 0x55aa67bb</p>
<p>r0 = 0&#215;00000000<br />
rlwimi      r0, r11, 8, 0, 31<br />
r0 is: 0xaa67bb55</p>
<p>r0 = 0&#215;12345678<br />
rlwimi      r0, r11, 8, 0, 14<br />
r0 is: 0xaa665678</p>
<p>r0 = 0&#215;1<span style="color: #99cc00;">234567</span>8<br />
rlwimi      r0, r11, 8, 28, 3<br />
r0 is: 0xa<span style="color: #99cc00;">234567</span>5</p>
<p>即：取 RS 循环左移 SH 位后的 WB 到 WE 位，替换 RA 的 WB 到 WE 位。</p>
<p>r0 = 0&#215;00000000<br />
rlwinm      r0, r11, 8, 0, 31<br />
r0 is: 0xaa67bb55</p>
<p>r0 = 0&#215;12345678<br />
rlwinm      r0, r11, 8, 0, 14<br />
r0 is: 0xaa660000</p>
<p>即：取 RS 循环左移 SH 位后的 WB 到 WE 位，替换归零后的 RA</p>
<p>rldcl<br />
rldcr<br />
rldic<br />
rldicl<br />
rldicr<br />
rldimi</p>
<p><strong> 3.3.6.2</strong> Shift</p>
<p>slw<br />
srw<br />
sraw<br />
srawi</p>
<p>slw./srw./sraw./srawi.</p>
<p>sld<br />
srd<br />
srad<br />
sradi</p>
<p><strong> 3.3.7 XER 指令</strong></p>
<p>mcrxr              BF<br />
mcrxr64            BF</p>
<p><span style="color: #3399ff;"><strong> 3.4 浮点指令</strong></span></p>
<p>这类指令包括：</p>
<p>浮点数据加载与存储指令<br />
浮点运算指令<br />
浮点数近似和转化指令<br />
浮点比较指令<br />
浮点状态和控制寄存器指令</p>
<p>有关该指令的详情留待以后以《PowerPC 浮点结构》的形式讨论吧。</p>
<p><span style="color: #3399ff;"><strong> 3.5 处理器控制指令</strong></span></p>
<p>这类指令包括用于支持异常中断处理的：</p>
<p>sc                            System Call<br />
rfci                     Return From Critical Interrupt<br />
rfi                       Return From Interrup</p>
<p>用于处理器控制寄存器维护的：</p>
<p>mfspr              RT, SPRN                     Move From SPRN (Special Purpose Register) to RT<br />
mtspr              SPRN, RS                     Move RS To SPRN</p>
<p>mfdcr              RT, DCRN                     Move From DCRN (Device Control Register) to RT<br />
mtdcr              DCRN, RS                     Move RS To DCRN</p>
<p>mfmsr              RT                            Move From MSR to RT<br />
mtmsr              RS                            Move RS To MSR</p>
<p>wrtee              RA       Write MSR External Enable, MSR[EE] = RA[48]<br />
wrteei         E       Write MSR External Enable Immediate, MSR[EE] = E</p>
<p>以及用于指令同步的：</p>
<p>isync</p>
<p>其保证在其之前的所有指令皆提交，在其自己被提交前，其之后的指令不会进入流水线</p>
<p><span style="color: #3399ff;"><strong> 3.6 存储管理相关指令<br />
</strong></span><br />
这类指令包括用于 TLB 管理的：</p>
<p>tlbivax<br />
tlbre<br />
tlbwe<br />
tlbsx<br />
tlbsync</p>
<p>tlbivaxe<br />
tlbsxe</p>
<p>用于 Cache 管理的：</p>
<p>dcba/dcbf/dcbi/dcbst/dcbt/dcbtst/dctz/icbi/icbt<br />
dcbae/dcbfe/dcbie/dcbste/dcbte/dcbtste/dctze/icbie/icbte</p>
<p>用于存储同步的：</p>
<p>msync<br />
mbar</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jackslab.org/?feed=rss2&#038;p=221</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerPC 体系结构之指令集 (I)</title>
		<link>http://www.jackslab.org/?p=209</link>
		<comments>http://www.jackslab.org/?p=209#comments</comments>
		<pubDate>Mon, 21 Feb 2011 09:30:25 +0000</pubDate>
		<dc:creator>Jack Tan</dc:creator>
				<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[ISA]]></category>
		<category><![CDATA[指令集]]></category>

		<guid isPermaLink="false">http://www.jackslab.org/?p=209</guid>
		<description><![CDATA[1. 概述 Book E 定义的 PowerPC 指令集的指令可分为以下几类： 分支跳转指令 CR 指令 整数指令 浮点指令 处理器控制指令 存储管理相关指令 CR 指令主要是对 CR ...]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff6600;"><strong>1. 概述</strong></span></p>
<p>Book E 定义的 PowerPC 指令集的指令可分为以下几类：</p>
<p>	分支跳转指令<br />
	CR 指令 整数指令<br />
	浮点指令<br />
	处理器控制指令<br />
	存储管理相关指令</p>
<p>CR 指令主要是对 CR 内部位运算支持的一些指令，如 crand, cror, crxor 等等。</p>
<p><span style="color: #009900;"><strong>2. 常用指令</strong></span></p>
<p>先看一个测试程序：</p>
<pre class="brush:cpp">int test_call(int a, int b, int c)
{
	a = b + c;
	return a;
}

int test_if(int s)
{
	int i;
	if(s &gt; 0)
		i = s;
	else if(s &lt; 0)
		i = -s;
	else
		i = s * 8;
	return i;
}

int test_cyc1(int c)
{
	int sum = 0;
	do {
		sum += c;
		c--;
	} while(c &gt; 0);
	return c;
}

int test_cyc2(int c)
{
	int sum = 0;
	for(; c &gt; 0; c--)
		sum += c;
	return c;
}

int main()
{
	int a, b, c, d;
	a = test_if(5);
	b = test_cyc1(10);
	c = test_cyc2(10);
	d = test_call(1, 2, 3);
	return a + b + c + d;
}</pre>
<p>引入的目的在于查看判断、循环和过程调用这些基本结构在 PowerPC 里怎么被支持。</p>
<p>-O2 参数编译后，objdump -S -d 反汇编，则：</p>
<p><span id="more-209"></span></p>
<pre class="brush:cpp">1000040c &lt;test_call&gt;:
int test_call(int a, int b, int c)
{
	a = b + c;
	return a;
}
1000040c:    7c 64 2a 14     add     r3,r4,r5
--&gt; 对应 a, b, c 三个参数，同时 r3 又置返回值
10000410:    4e 80 00 20     blr
--&gt; 跳转到 LR 所存放的地址处，即函数返回

10000414 &lt;test_if&gt;:
int test_if(int s)
{
	int i;
	if(s &gt; 0)
10000414:    7c 60 1b 79     mr.     r0,r3
--&gt; r3 移到 r0，若 r0 小于、大于、等于 0，则置 CR0 的相应位。指令后多一点，则说明该指令会据执行结果，设置 CR 的相应位
10000418:    7c 03 03 78     mr      r3,r0
--&gt; 此条指令多余
1000041c:    4d a1 00 20     bgtlr+
--&gt; 若 CR0[gt] 位为 1，则跳转到 LR 所存放的地址处，即直接函数返回了。此条指令等价于 bclr  13, 1
		i = s;
	else if(s &lt; 0)
10000420:    38 60 00 00     li      r3,0
10000424:    4d 82 00 20     beqlr
--&gt; 若 CR0[eq] 位为 1，则跳转到 LR 所存放的地址处，也直接函数返回了。此条指令等价于 bclr      12, 2
		i = -s;
10000428:    7c 60 00 d0     neg     r3,r0
--&gt; r0 取反，入 r3
	else
		i = s * 8;
	return i;
}
1000042c:    4e 80 00 20     blr
--&gt; 跳转到 LR 所存放的地址处，函数返回

10000430 &lt;test_cyc1&gt;:
int test_cyc1(int c)
{
10000430:    34 03 ff ff     addic. r0,r3,-1
10000434:    7c 69 03 a6     mtctr   r3
10000438:    41 80 00 10     blt-    10000448 &lt;test_cyc1+0x18&gt;
	int sum = 0;
	do {
		sum += c;
		c--;
1000043c:    38 63 ff ff     addi    r3,r3,-1
	} while(c &gt; 0);
10000440:    42 00 ff fc     bdnz+   1000043c &lt;test_cyc1+0xc&gt;
	return c;
}
10000444:    4e 80 00 20     blr
10000448:    38 00 00 01     li      r0,1
1000044c:    7c 09 03 a6     mtctr   r0
10000450:    4b ff ff ec     b       1000043c &lt;test_cyc1+0xc&gt;

10000454 &lt;test_cyc2&gt;:
int test_cyc2(int c)
{
10000454:    2c 03 00 00     cmpwi   r3,0
10000458:    39 20 00 00     li      r9,0
1000045c:    7d 23 48 1e     .long 0x7d23481e
	int sum = 0;
	for(; c &gt; 0; c--)
		sum += c;
	return c;
}
10000460:    7d 23 4b 78     mr      r3,r9
10000464:    4e 80 00 20     blr

int main()
{
10000468:   94 21 ff e0     stwu    r1,-32(r1)
1000046c:   7c 08 02 a6     mflr    r0
	int a, b, c, d;
	a = test_if(5);
10000470:   38 60 00 05     li      r3,5
10000474:   90 01 00 24     stw     r0,36(r1)
10000478:   93 61 00 0c     stw     r27,12(r1)
1000047c:   93 81 00 10     stw     r28,16(r1)
10000480:   93 a1 00 14     stw     r29,20(r1)
10000484:   4b ff ff 91     bl      10000414 &lt;test_if&gt;
10000488:   7c 7d 1b 78     mr      r29,r3
	b = test_cyc1(10);
1000048c:   38 60 00 0a     li      r3,10
10000490:   4b ff ff a1     bl      10000430 &lt;test_cyc1&gt;
10000494:   7c 7b 1b 78     mr      r27,r3
	c = test_cyc2(10);
10000498:   38 60 00 0a     li      r3,10
	d = test_call(1, 2, 3);
1000049c:   7f bd da 14     add     r29,r29,r27
100004a0:   4b ff ff b5     bl      10000454 &lt;test_cyc2&gt;
100004a4:   38 80 00 02     li      r4,2
100004a8:   7c 7c 1b 78     mr      r28,r3
100004ac:   38 a0 00 03     li      r5,3
100004b0:   38 60 00 01     li      r3,1
100004b4:   4b ff ff 59     bl      1000040c &lt;test_call&gt;
	return a + b + c + d;
}
100004b8:   80 01 00 24     lwz     r0,36(r1)
100004bc:   7f 9c 1a 14     add     r28,r28,r3
100004c0:   83 61 00 0c     lwz     r27,12(r1)
100004c4:   7c 7d e2 14     add     r3,r29,r28
100004c8:   83 81 00 10     lwz     r28,16(r1)
100004cc:   83 a1 00 14     lwz     r29,20(r1)
100004d0:   7c 08 03 a6     mtlr    r0
100004d4:   38 21 00 20     addi    r1,r1,32
100004d8:   4e 80 00 20     blr</pre>
<p><span style="color: #3399ff;"><strong>3. 分类概述</strong></span></p>
<p><strong> 3.1 分支跳转指令</strong></p>
<p>这类指令算是 PowerPC 里比较有特色的，也是稍显复杂的。这类指令与 CR, LR 和 CTR 紧密相联，建构起判断、循环和过程调用这些程序的基本结构。其大致可分为四类：</p>
<p>Branch<br />
Branch Conditional<br />
Branch Conditional to Count Register<br />
Branch Conditional to Link Register<br />
<strong> </strong></p>
<p><strong> 3.1.1 Branch</strong></p>
<p>这类指令与 CR 没有联系，即为非条件跳转，助记符后直接跟立即数地址。指令内为立即数地址预留 26 位，即可跳转 2^26 大小的空间，如：(CIA, Current Instruction Address)</p>
<p>b                                             0&#215;20                       &#8212;&#8211;&gt; 以当前指令地址为基点，往后跳转 0&#215;20 字节，即 PC = CIA + 0&#215;20<br />
ba                               0&#215;20                                                            &#8212;&#8211;&gt; 直接跳转到地址 0&#215;20 处。<strong>后缀为 a，则表示使用 Absolute Address，PC = 0&#215;20</strong>。<br />
bl                   0&#215;20                                                            &#8212;&#8211;&gt; 在 b 0&#215;20 的基础上，将 LR 更新为 CIA + 4<br />
bla                 0&#215;20                                                            &#8212;&#8211;&gt; 使用绝对地址，且更新 LR。<strong>后缀带 l，则表示更新 LR 为 CIA + 4</strong></p>
<p>以上针对 32 位的情形，对 64 位则使用指令 be, bea, bel, bela 功能与上同。</p>
<p><strong>3.1.2 Branch Conditional</strong></p>
<p>此类为条件跳转指令。皆以 bc 开头，带 3 个操作数，如：</p>
<p>bc                        BO, BI, BD<br />
bca               BO, BI, BD<br />
bcl                  BO, BI, BD<br />
bcla              BO, BI, BD</p>
<p>后缀 a, l 的含义与 branch 类指令同。BO 指定跳转的条件，5 位；BI 指定关联的 CR 位，也是 5 位；BD 为跳转的立即数地址，16 位。</p>
<p>其中以 BO 的编码最为复杂（BO 从左到右编号为 0 ~ 4）：</p>
<p>BO[0]: 为 1，则直接跳转<br />
BO[1]: 为 1，则条件为真时，跳转。否则条件为假时，跳转<br />
BO[2]: 为 1，则 CTR 不自动减 1<br />
BO[3]: 为 1 时，则 CTR == 0 时跳转；为 0 时，则 CTR != 0 时跳转<br />
BO[4]: 静态预测位，1 表示 unlikely，0 表示 likely</p>
<p>则常见的 BO 值：<br />
20 (0b10100) 则表示无条件跳转<br />
12 (0b01100) 则表示 CR 的某个位为 1 时跳转<br />
4 (0b00100) 则表示 CR 的某个位为 0 时跳转</p>
<p>至于静态预测的策略位，默认被置为<strong> 0</strong>，则其行为为：</p>
<p>b1. 目标地址小于当前指令地址，预测为<span style="color: #ff9900;">跳转</span><br />
b2. 目标地址大于当前指令地址，预测为<span style="color: #ff9900;">不跳转</span><br />
b3. 对于目标地址在 CTR/LR 中的条件跳转指令，一律预测为<span style="color: #ff9900;">不跳转</span></p>
<p>若该位被置 <strong>1</strong>，则上述 b1, b2, b3 的静态预测行为分别为：<span style="color: #99cc00;">不跳转</span>，<span style="color: #99cc00;">跳转</span>，<span style="color: #99cc00;">跳转</span>。</p>
<p>可以给分支指令加一个 +/- 的后缀，来简化。加 &#8216;+&#8217; 的指令，一律预测为跳转。加 &#8216;-&#8217; 的分支指令，一律预测为不跳转。</p>
<p>则对于 b1，后缀 &#8216;+&#8217; 会将 y 位置 0，&#8217;-&#8217; 则将 y 位置 1。<br />
对于 b2，后缀 &#8216;+&#8217; 会将 y 位置 1，&#8217;-&#8217; 则将 y 位置 0。<br />
对于 b3，后缀 &#8216;+&#8217; 会将 y 位置 1，&#8217;-&#8217; 则将 y 位置 0。</p>
<p>BI 与关联 CR 位的关系为：</p>
<p>32 + BI</p>
<p>即，若 BI 为 2，则对应于 CR[34]，即为 CR0[gt] 位。</p>
<p>以上针对 32 位的情形，对 64 位则使用指令 bce, bcea, bcel, bcela 功能与上同。</p>
<p><strong>3.1.3 Branch Conditional to Count Register</strong></p>
<p>bcctr                BO, BI<br />
bcctrl               BO, BI</p>
<p>后缀 l 的含义与 branch 类指令同。<br />
BO，BI 的编码与 Branch Conditional 类指令同。<br />
跳转目标地址位于 CTR 中。</p>
<p>以上针对 32 位的情形，对 64 位则使用指令 bcctre, bcctrel 功能与上同。</p>
<p><strong>3.1.4 Branch Conditional to Link Register</strong></p>
<p>bclr                BO, BI<br />
bclrl               BO, BI</p>
<p>后缀 l 的含义与 branch 类指令同。<br />
BO，BI 的编码与 Branch Conditional 类指令同。<br />
跳转目标地址位于 LR 中。</p>
<p>以上针对 32 位的情形，对 64 位则使用指令 bclre, bclrel 功能与上同。</p>
<p><span style="color: #3399ff;"><strong>3.2 CR 指令</strong></span></p>
<p>这类指令包括用来支持 CR 内部位运算的指令和 CR 与 GPR 之间的数据交换指令。</p>
<p><strong>3.2.1 CR 内</strong><strong>位运算指令</strong></p>
<p>这类指令的格式皆为：           crxxx            BT, BA, BB</p>
<p>BT, BA, BB 是 CR 内的位编号，取值范围为 0 ~ 31，如 crand    0, 8, 12，则将 CR[32+8] (CR2[lt]) 与 CR[32+12] (CR3[lt]) 作与操作后，将结果置入 CR[32+0] (CR0[lt])，即 CR[32] = CR[40] &amp; CR[44]</p>
<p>crand:                                                CR[32+BA] &amp; CR[32+BB]<br />
crandc:                                      CR[32+BA] &amp; (~CR[32+BB])<br />
creqv:                                                ~(CR[32+BA] ^ CR[32+BB])，即位相等，则置 1；不等则置 0<br />
crnand:                        ~(CR[32+BA] &amp; CR[32+BB])<br />
crnor:                                       ~(CR[32+BA] | CR[32+BB])<br />
cror:                                       CR[32+BA] | CR[32+BB]<br />
crorc:                          CR[32+BA] | (~CR[32+BB])，先取反后再或<br />
crxor:                              CR[32+BA] ^ CR[32+BB]，位异或</p>
<p><strong>3.2.2  CR 与 GPR 间</strong><strong>数据交换指令</strong><br />
<strong><br />
3.2.2.1</strong> mcrf                                    BF, BFA          &#8212;          Move Condition Register Fields</p>
<p>将 CR 之 BFA 域复制到 BF 域。如 mcrf            0, 3 则将 CR3 拷入 CR0</p>
<p><strong><br />
3.2.2.2</strong> mtcrf                          FXM, RS          &#8212;          Move To Condition Register Fields</p>
<p>通用寄存器 RS 之 32 ~ 63 位以 4 位为单位，对应于 CR 的 8 个域，编号为 RS0 ~ RS7；<br />
FXM 为域掩码，8 位，从左到右编号为 0 ~ 7，对应于 RS、CR 的 8 个域。某位为 1，则将对应的 RS 域拷贝到对应的 CR 域中。<br />
若 FXM 为 0&#215;80，则只将 CR0 = RS0<br />
若 FXM 为 0xc8，则将 CR0 = RS0, CR1 = RS1, CR4 = RS4</p>
<p><strong> 3.2.2.3</strong> mfcr                          RT          &#8212;          Move From Condition Register</p>
<p>将 CR 的内容移入通用寄存器 RT 的 32 ~ 63 位。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jackslab.org/?feed=rss2&#038;p=209</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PowerPC 体系结构之 ULR 和 ABI</title>
		<link>http://www.jackslab.org/?p=203</link>
		<comments>http://www.jackslab.org/?p=203#comments</comments>
		<pubDate>Mon, 21 Feb 2011 09:21:54 +0000</pubDate>
		<dc:creator>Jack Tan</dc:creator>
				<category><![CDATA[PowerPC]]></category>
		<category><![CDATA[体系结构]]></category>
		<category><![CDATA[ISA]]></category>
		<category><![CDATA[ULR]]></category>

		<guid isPermaLink="false">http://www.jackslab.org/?p=203</guid>
		<description><![CDATA[A. 以下取 Book E 之 ULR 精要 ULR (User Level Register) 即用户态程序能用的寄存器，包括只读的和可读写的。 最常用的 ULR 包括以下寄存器： 1. GRP ...]]></description>
			<content:encoded><![CDATA[<p><span style="color: #99cc00;"><strong>A. 以下取 Book E 之 ULR 精要</strong></span></p>
<p>ULR (User Level Register)  即用户态程序能用的寄存器，包括只读的和可读写的。</p>
<p>最常用的 ULR 包括以下寄存器：</p>
<p><strong> 1.</strong> GRP (General Purpose Register)  通用寄存器，即用于定点运算的寄存器，共 32 个</p>
<p><strong> 2.</strong> <span style="color: #ff9900;">CR</span> (Condition Register) 指令状态寄存器，其格式如下所示：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/CR.png"><img class="aligncenter size-full wp-image-204" title="CR" src="http://www.jackslab.org/wp-content/uploads/2011/02/CR.png" alt="" width="336" height="63" /></a><br />
<span style="color: #ff0000;"><strong>注意：</strong></span>Book E 对寄存器的位编号与通常不同，因其支持 PowerPC 64，故其将 64 位寄存器从最高位 (MSB) 到最低位 (LSB) 编号为 0 ~ 63，32 位寄存器则编号为 32 ~ 63。</p>
<p>CR 以4位为单位分成 8 个域，每个域能描述 4 种状态。</p>
<p><strong> 2.1</strong> CR0 用于存放 RC 位为1 的整数指令执行后的状态。CR[32:35] 依次表示小于、大于、等于和溢出。当指令执行的结果小于、大于或等于 0 时则置相应的CR[32:34] 的位；CR[35] 的值则直接复制自XER 的 SO (Summary Overflow)位。</p>
<p><strong> 2.2</strong> CR1用于存放 RC 位为 1 的所有浮点指令执行后的浮点异常状态。其内容直接复制于浮点状态与控制寄存器 (FPSCR)，CR[36:39] 依次对应于浮点异常 (FX)、浮点使能异常 (FEX)、浮点非法操作异常 (VX) 和浮点溢出异常 (OX)。</p>
<p>RC 位为 1 的指令，其助记符的最后有一个 &#8216;<strong>.</strong>&#8216; ，如 addic./divw./mullw./neg./and./or./xor./nand./nor.</p>
<p><strong> 2.3</strong> 对于比较指令（整数和浮点），可以通过操作数 BF 指定比较结果所存储的 CR 域：</p>
<p>cmp      <span style="color: #99cc00;"><strong>3</strong></span>, 0, r3, r4         (cmp     BF, L, RA, RB)</p>
<p>操作数 L = 0，表示此为 32 位比较，即只比较 r3, r4 的 32 ~ 63 位。若 r3 &gt; r4，则将 CR<span style="color: #99cc00;"><strong>3</strong></span>[gt] (CR[45]) 置位。浮点比较类似，但域内第 4 位含义与整数不同，整数依然表示溢出 (SO)，且其值拷贝自 XER[SO]；而对浮点比较，若该位被置，则表示某一浮点操作数不是数值。</p>
<p><strong> 2.4</strong> 此外 RC 位为 1 的条件存储指令 (stwcx<strong>.</strong>/stwcxe<strong>.</strong>/stdcxe<strong>.</strong>)，在存储操作成功时置 CR0[2] (EQ 位) 为 1。</p>
<p><span id="more-203"></span></p>
<p><strong>3. </strong>LR (Link Register) 链接寄存器，用于存放返回地址<br />
Branch and Link 类指令（如 bl，指令内 LK 位为 1）会将下条指令的地址自动写入 LR。bl 用于调用子过程，则置入 LR 的即为返回地址<br />
Branch Conditional to Link Register 类指令（如 bclr）则使用 LR 作为跳转的目标地址，该类指令通常用于子过程返回</p>
<p><strong> 4. </strong>CTR (Count Register) 计数寄存器，常用于存放跳转目标地址，与 Branch Conditional to Count Register 类指令配合使用；亦可存放循环变量与条件分支指令 (Branch Conditional) 配合，实现循环</p>
<p>CR，LR 和 CTR 是与分支指令紧密联系的，在实现基本程序结构之判断、循环以及过程调用方面作用巨大。</p>
<p><strong> 5. </strong>XER (Integer eXception Register) 整数异常寄存器，用于置整数运算的溢出 (Overflow)、进位 (Carry Out) 以及批量加载和存储指令要操作的字节数</p>
<p><strong>6. E500 ULR</strong></p>
<p>下图为 e500 之 ULR 概览：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/e500-ulr.png"><img class="aligncenter size-full wp-image-205" title="e500-ulr" src="http://www.jackslab.org/wp-content/uploads/2011/02/e500-ulr.png" alt="" width="689" height="278" /></a></p>
<p>可以看到 e500 没有浮点寄存器，其没有浮点部件。</p>
<p><strong>7. E600 ULR</strong></p>
<p>下图为 e600 之 ULR 概览：</p>
<p><a href="http://www.jackslab.org/wp-content/uploads/2011/02/e600-ulr.png"><img class="aligncenter size-full wp-image-206" title="e600-ulr" src="http://www.jackslab.org/wp-content/uploads/2011/02/e600-ulr.png" alt="" width="258" height="541" /></a></p>
<p>e600 则含32个浮点寄存器，且含 32 个向量寄存器 (VR0 ~ VR31) 用于支持向量计算。</p>
<p><strong><span style="color: #ff6600;"><br />
B. ABI</span></strong></p>
<p>ABI 即 Application Binary Interface。其主要规定通用寄存器的使用约定，以及过程调用的栈的组织。一般最常用的就是通用寄存器的使用约定。Linux 下常用SYS V ABI。</p>
<p>以下是比较诸多 PowerPC ABI 版本后的一个交集：</p>
<p>GPR1: Stack Pointer<br />
GPR3 ~ GPR4: 参数1 ~ 2，同时复用之，置 2 个返回值<br />
GPR5 ~ GPR10: 参数 3 ~ 8</p>
<p>e500 ABI 继承于 System V ABI PowerPC Processor Supplement</p>
<p>以较为常用的 System V ABI 为准，其他寄存器的约定如下：</p>
<p>GPR0: volatile, may be used by function linkage<br />
GPR2: reserved for system<br />
GPR11 ~ 12: volatile, may be used by function linkage<br />
GPR13: small data area pointer<br />
GPR14 ~ 31: saved</p>
<p><span style="color: #3366ff;"><strong>C. Reference</strong></span></p>
<p>[1] Book E: Enhanced PowerPC Architecture, v1.0, 2002.7<br />
[2] PowerPC e500 Core Family Reference Manual, Rev. 1, 2005.4<br />
[3] e600 PowerPC Core Reference Manual, Rev. 0, 2006.3<br />
[4] SYSTEM V APPLICATION BINARY INTERFACE PowerPC Processor Supplement (SYS V ABI), Rev. A, 1995.9<br />
[5] PowerPC Embedded Application Binary Interface (EABI), v1.0, 1995.1<br />
[6] PowerPC e500 Application Binary Interface User’s Guide, Rev. 1.0, 2003.3</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jackslab.org/?feed=rss2&#038;p=203</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
