# K.5 面向大型机的 IBM 360/370 体系结构
<!-- source: p1369 -->

## 引言

“计算机体系结构”一词由 IBM 于 1964 年为 IBM 360 创造。Amdahl、Blaauw 和 Brooks [1964] 用它指代程序员可见的指令集部分。他们认为，属于同一体系结构的计算机系列应能运行同样的软件。这在今天看似理所当然，当时却相当新颖。即使 IBM 已是产业领军企业，在 360 之前也拥有五种不同体系结构。因此，一家公司统一采用一种体系结构的想法十分大胆。360 的设计者希望通过定义共同体系结构，把 IBM 的六个不同部门整合起来。他们给出的定义是：

> ……机器语言程序员为了给一台计算机编写正确、与时序无关的程序而必须理解的计算机结构。

“机器语言程序员”意味着兼容性甚至在汇编语言层面也成立；“与时序无关”则允许不同的实现。

IBM 360 于 1964 年推出，包含六种型号，最高与最低性能之比为 25∶1。Amdahl、Blaauw 和 Brooks [1964] 讨论了 IBM 360 的体系结构，以及允许多个实现保持目标代码兼容的概念。按我们今天理解的含义，指令集体系结构这一观念是 360 最重要的贡献。它还引入了后来广泛采用的若干重要创新：

1. 32 位体系结构。
2. 采用 8 位字节、按字节寻址的存储器。
3. 8、16、32、64 位数据长度。
4. 32 位单精度和 64 位双精度浮点数据。

1971 年，IBM 开始交付第一批 System/370，即 155 和 165 型号，包含对 360 的若干重大扩展。Case 和 Padegs [1978] 对此进行了讨论，也回顾了 System/360 的早期历史。最重要的新增内容是虚拟存储器，不过带虚拟存储器的 370 直到 1972 年相应操作系统就绪才交付。到 1978 年，高端 370 的速度已是十年前交付的低端 360 的数百倍。1984 年，IBM 360 原有的 24 位寻址模型必须扩展，于是推出 370-XA（eXtended Architecture，扩展体系结构）。旧的 24 位程序可以不加修改地运行，但扩展到支持 31 位地址的 32 位寻址模型时，有些指令无法继续按原方式工作，因为它们不能生成 31 位地址。转换主要用汇编编写的操作系统，无疑是最大的任务。

<!-- source: p1370 -->

关于 IBM 360 及其指令测量，已有多项研究。Shustek 的学位论文 [1978] 是最知名、最完整的 360/370 体系结构研究。他对指令集复杂性提出若干观察，直到数年后才受到充分重视。另一项重要研究是 Alexander 和 Wortman [1975] 的 Toronto 研究，在 IBM 360 上测量了 19 个 XPL 程序。

## System/360 指令集

下面按指令类型和格式列出 360 指令集。System/370 另有 15 条用户指令。

### 整数／逻辑和浮点 R-R 指令

`*` 表示该指令为浮点指令，可替换为 `D`，即双精度，或 `E`，即单精度。

| 指令 | 说明 |
| --- | --- |
| `ALR` | 寄存器逻辑加法 |
| `AR` | 寄存器加法 |
| `A*R` | 浮点加法 |
| `CLR` | 寄存器逻辑比较 |
| `CR` | 寄存器比较 |
| `C*R` | 浮点比较 |
| `DR` | 寄存器除法 |
| `D*R` | 浮点除法 |
| `H*R` | 浮点数减半 |
| `LCR` | 寄存器取补后加载 |
| `LC*R` | 取补后加载 |
| `LNR` | 寄存器加载负值 |
| `LN*R` | 加载负值 |
| `LPR` | 寄存器加载正值 |
| `LP*R` | 加载正值 |
| `LR` | 加载寄存器 |
| `L*R` | 加载浮点寄存器 |
| `LTR` | 加载并测试寄存器 |
| `LT*R` | 加载并测试浮点寄存器 |
| `MR` | 寄存器乘法 |
| `M*R` | 浮点乘法 |
| `NR` | 寄存器 AND |
| `OR` | 寄存器 OR |
| `SLR` | 寄存器逻辑减法 |
| `SR` | 寄存器减法 |
| `S*R` | 浮点减法 |
| `XR` | 寄存器异或 |

### 分支与状态设置 R-R 指令

<!-- source: p1371 -->

这些 R-R 格式指令执行分支或设置某种系统状态。其中若干是特权指令，只能在管理模式（supervisor mode）下合法执行。

| 指令 | 说明 |
| --- | --- |
| `BALR` | 分支并链接 |
| `BCTR` | 按计数分支 |
| `BCR` | 条件分支 |
| `ISK` | 插入存储键（key） |
| `SPM` | 设置程序掩码 |
| `SSK` | 设置存储键 |
| `SVC` | 管理程序调用 |

### 分支／逻辑和浮点指令：RX 格式

以下均为 RX 格式。符号 `+` 表示字操作，此时不添加字符，或者替换为 `H` 表示半字操作；例如 `A+` 代表 `A` 和 `AH` 两个操作码。`*` 代表 `D` 或 `E`，即双精度或单精度浮点。

| 指令 | 说明 |
| --- | --- |
| `A+` | 加法 |
| `A*` | 浮点加法 |
| `AL` | 逻辑加法 |
| `C+` | 比较 |
| `C*` | 浮点比较 |
| `CL` | 逻辑比较 |
| `D` | 除法 |
| `D*` | 浮点除法 |
| `L+` | 加载 |
| `L*` | 加载浮点寄存器 |
| `M+` | 乘法 |
| `M*` | 浮点乘法 |
| `N` | AND |
| `O` | OR |
| `S+` | 减法 |
| `S*` | 浮点减法 |
| `SL` | 逻辑减法 |
| `ST+` | 存储 |
| `ST*` | 存储浮点寄存器 |
| `X` | 异或 |

### 分支与特殊加载、存储：RX 格式

<!-- source: p1372 -->

| 指令 | 说明 |
| --- | --- |
| `BAL` | 分支并链接 |
| `BC` | 条件分支 |
| `BCT` | 按计数分支 |
| `CVB` | 转换为二进制 |
| `CVD` | 转换为十进制 |
| `EX` | 执行 |
| `IC` | 插入字符 |
| `LA` | 加载地址 |
| `STC` | 存储字符 |

### RS 和 SI 格式指令

以下是 RS 与 SI 格式指令。`*` 可以是 `A`，表示算术，或 `L`，表示逻辑。

| 指令 | 说明 |
| --- | --- |
| `BXH` | 变址后若高于则分支 |
| `BXLE` | 变址后若低于或等于则分支 |
| `CLI` | 逻辑比较立即数 |
| `HIO` | 停止 I/O |
| `LPSW` | 加载程序状态字 PSW |
| `LM` | 加载多个寄存器 |
| `MVI` | 传送立即数 |
| `NI` | 与立即数作 AND |
| `OI` | 与立即数作 OR |
| `RDD` | 直接读 |
| `SIO` | 启动 I/O |
| `SL*` | 算术／逻辑左移 |
| `SLD*` | 双字算术／逻辑左移 |
| `SR*` | 算术／逻辑右移 |
| `SRD*` | 双字算术／逻辑右移 |
| `SSM` | 设置系统掩码 |
| `STM` | 存储多个寄存器 |
| `TCH` | 测试通道 |
| `TIO` | 测试 I/O |
| `TM` | 按掩码测试 |
| `TS` | 测试并置位 |
| `WRD` | 直接写 |
| `XI` | 与立即数作异或 |

### SS 格式指令

<!-- source: p1373 -->

这些是十进制或字符串指令。[^ss-wording]

| 指令 | 说明 |
| --- | --- |
| `AP` | 打包十进制加法 |
| `CLC` | 字符逻辑比较 |
| `CP` | 打包十进制比较 |
| `DP` | 打包十进制除法 |
| `ED` | 编辑 |
| `EDMK` | 编辑并标记 |
| `MP` | 打包十进制乘法 |
| `MVC` | 传送字符 |
| `MVN` | 传送数字部分 |
| `MVO` | 带偏移量传送 |
| `MVZ` | 传送区码（zone）部分 |
| `NC` | 字符 AND |
| `OC` | 字符 OR |
| `PACK` | 打包，从字符转换为十进制 |
| `SP` | 打包十进制减法 |
| `TR` | 转换 |
| `TRT` | 转换并测试 |
| `UNPK` | 解包 |
| `XC` | 字符异或 |
| `ZAP` | 清零后作打包十进制加法 |

## 360 的详细测量

图 K.59 给出四个 IBM 360 程序的指令使用频率。

<!-- source: p1374 -->

| 指令／类别 | PLIC | FORTGO | PLIGO | COBOLGO | 平均 |
| --- | --- | --- | --- | --- | --- |
| **控制** | **32%** | **13%** | **5%** | **16%** | **16%** |
| `BC, BCR` | 28% | 13% | 5% | 14% | 15% |
| `BAL, BALR` | 3% | | | 2% | 1% |
| **算术／逻辑** | **29%** | **35%** | **29%** | **9%** | **26%** |
| `A, AR` | 3% | 17% | 21% | | 10% |
| `SR` | 3% | 7% | | | 3% |
| `SLL` | | 6% | 3% | | 2% |
| `LA` | 8% | 1% | 1% | | 2% |
| `CLI` | 7% | | | | 2% |
| `NI` | | | | 7% | 2% |
| `C` | 5% | 4% | 4% | 0% | 3% |
| `TM` | 3% | 1% | | 3% | 2% |
| `MH` | | | 2% | | 1% |
| **数据传送** | **17%** | **40%** | **56%** | **20%** | **33%** |
| `L, LR` | 7% | 23% | 28% | 19% | 19% |
| `MVI` | 2% | | 16% | 1% | 5% |
| `ST` | 3% | | 7% | | 3% |
| `LD` | | 7% | 2% | | 2% |
| `STD` | | 7% | 2% | | 2% |
| `LPDR` | | 3% | | | 1% |
| `LH` | 3% | | | | 1% |
| `IC` | 2% | | | | 1% |
| `LTR` | | 1% | | | 0% |
| **浮点** | | **7%** | | | **2%** |
| `AD` | | 3% | | | 1% |
| `MDR` | | 3% | | | 1% |
| **十进制、字符串** | **4%** | | | **40%** | **11%** |
| `MVC` | 4% | | | 7% | 3% |
| `AP` | | | | 11% | 3% |
| `ZAP` | | | | 9% | 2% |
| `CVD` | | | | 5% | 1% |
| `MP` | | | | 3% | 1% |
| `CLC` | | | | 3% | 1% |
| `CP` | | | | 2% | 1% |
| `ED` | | | | 1% | 0% |
| **合计** | **82%** | **95%** | **90%** | **85%** | **88%** |
{#fig-K.59 .wide .expand num="K.59" caption="四个 360 程序的指令执行频率分布。纳入执行频率大于 1.5% 的全部指令。只操作单字节的立即数指令归入体现其操作性质的类别，不与同种操作的长字符串版本合并。作为对照，VAX 主要类别的平均频率为：控制 23%、算术 28%、数据传送 29%、浮点 7%、十进制 9%。由于各分项列的数值，平均列仍可能出现 1% 项。这些程序分别是 PL-I 语言编译器，以及 FORTRAN、PL/I、Cobol 的运行时系统。"}

[^ss-wording]: 原文句子为 “These are add decimal or string instructions”，其中 `add` 与后面的多种十进制操作不协调。译文按该表实际类别表述为“十进制或字符串指令”，并保留这一源书文字疑点。
