JUC-3指令增强

扩充条件转移指令

条件转移指令的硬件扩充

在JUC-3基本模块中已经支持JZ和JNZ指令,现在扩充依据其他3个标志位的条件转移指令JC、JNC、JO、JNO、JS、JNS。分析指令编码表,8条条件转移指令由IR的8、7、6位区分;其中IR8和IR7区分所测试的标志位类型,即区分N、Z、O、C,IR6区分所测试的标志位为1还是为0。因此修改基本版中BM=3依据标志位的微转移地址形成逻辑,在juc3-ch2.adoc#fig-20基础上增加一个4选1多路器,用IR8和IR7控制多路器选择标志位,IR6控制异或门决定是否取反,如图 1

图22
图 1. 依据PSW的微转移地址形成

实战:条件转移指令的微程序设计与调试

由上面的硬件设计可以知道,是否满足转移条件的判断是由硬件完成的,所以不同条件转移指令的微程序是一样的,只是微程序入口地址不同,所以只要在相应的微地址填入条件转移微指令。

(1)用以下程序验证JC指令

MOV #imm1, R1
CMP #imm2, R1
JC ADDR1
MOV #0001H, FF01H
HALT
ADDR1: MOV #0080H, FF01H
HALT

设计两组立即数使得转移和不转移两种情况均能出现,观察LED的变化和PC值的变化并分析原因。

(2)验证其他的条件转移指令。

增强移位指令

在JUC-3基本模块中移位指令只有算术右移SAR和逻辑左移SHL两条,并且移出的数据被丢弃。本节增强移位指令,一方面将移出的数据位放入PSW的CF标志位,以便后续指令使用;另一方面扩充移位指令的种类。

移位指令的硬件扩充

移位操作分逻辑移位、算术移位和循环移位三大类,其中循环移位根据进位位是否一起参加循环,可分为不带进位循环移位和带进位循环移位两种。移位操作如图 2

移位操作
图 2. 移位操作(注:JUC-3不包含算术左移指令)

图 2可以看出,除了左移和右移的不同,不同移位操作的区别主要是移入的数据来源不同。如果16位移位数据是d,左移时移入最低位d[0]的数据根据不同的的移位操作可取0、最高位d[15]或PSW中的CF;右移时移入最高位d[15]的数据根据不同的的移位操作可取d[15] 自身、0、最低位d[0]或CF。因此可以用两个多路器选择左移和右移时的移入数据,如图 3

图24
图 3. 左移和右移移入数据的选择

图中多路器的选择信号ShiftType连接指令寄存器IR的8、7两位,从指令编码表可以看出,当IR8-7分别为00、01、10、11时,对应的移位指令分别是:算术移位、逻辑移位、循环移位和带进位的循环移位。

移出位送入PSW的CF标志位

从运算器设计已经知道,PSW保存ALU的运算结果特征标志,其中CF是加法运算的进位,现在要使CF也可以来源于移位寄存器的移位输出,左移时将X的最高位送CF,右移时将X的最低位送CF。因此可以用一个多路器选择CF的来源,选择逻辑如图 4,SL有效时,选择输入数据的X[15]送入CF;SR有效时,选择输入数据的X[0]送入CF;SL和SR同时无效时(不移位),选择加法产生的进位送入CF;SL和SR不应该出现同时有效的情况,如果有这种情况出现,也选择加法产生的进位送入CF。

图25
图 4. CF选择逻辑

实战:移位指令的微程序设计与调试

从上面的硬件设计可以看出,不同移位指令移入数据来源的选择由硬件实现,移出数据位送到PSW的CF标志位也是由硬件实现。所以各个移位指令的微程序是相同的,但是微程序入口地址不同,所以只要在相应的微地址填入左移或右移的微程序。

(1)用以下调机程序验证右移指令的微程序。

MOV #0001H,R0
SHR R0
JC FFFDH(PC)
HALT

移位指令将移出的位保存在PSW的CF标志位中,所以可以用JC指令判断移出位的值。第3行指令中的“FFFDH(PC)”表示相对寻址,其中“FFFDH”是补码表示的偏移量,即十进制“-3”。

分析上述程序的功能,运行之后相关寄存器和PSW会有怎样的变化,第一次移位后JC指令是否转移,第二次呢?转移的目的地址是多少。

(2)用以下程序验证循环左移指令的微程序。

ORG 0030H
MOV #0505H,R1
TEST #0001H,R1
JZ 3(PC)
ROL R1
JMP 0032H
HALT

分析程序的功能,运行之后相关寄存器和PSW会有怎样的变化,程序是否转移,转移的目的地址是多少。

支持堆栈及相关指令

数据通路和微命令的扩展

堆栈是主存储器中的一块连续的专用存储区域,它只能从一端存入或取出数据,遵循后进先出(LIFO)的规则。如果是从低地址一端操作,随着存入堆栈数据的增加,存放数据的单元地址减小,通常称作堆栈向上增长;如果是从高地址一端操作,随着存入堆栈数据的增加,存放数据的单元地址增大,通常称作堆栈向下增长。JUC-3的堆栈是向上增长的,堆栈的存储空间为002FH~0008H。

堆栈操作必须通过堆栈指示器SP,它是CPU中的一个专用寄存器,用来指向栈顶元素。将数据压入堆栈时,首先将SP的内容减1,使SP指向一个新的内存单元,然后将数据存入以SP内容为地址的内存单元;将数据从堆栈中取出时,首先以SP内容为地址取出该内存单元的数据,然后将SP的内容加1,使SP指向新的栈顶。总之,SP始终指向当前的栈顶元素。增加了SP寄存器的JUC-3E模型机结构如图 5。SP的初始值为0030H。增加了SPoe和SPce微命令的微指令编码见表 1

JUC3e模型机数据通路图 2020后
图 5. JUC-3E教学模型机的数据通路
表 1. JUC-3E的微指令格式及编码
F0:XXoe

(3位)
F1:XXce

(3位)
F2:ALU

(4位)
F3:PSW

(3位)
F4:S/D

(1位)
F5:SB

(2位)
F6:PC

(1位)
F7:Mem

(3位)
F8:BM

(3位)
F9: NA

(9位)

0:NOP

0:NOP

由ALU

0:NOP

0:DST

0:NOP

0:NOP

0:NOP

1:PCoe

1:PCce

的硬件设

1:PSWce

1:SRC

1:ARce

1: PCinc

1:RD

2:GRSoe

2:GRSce

计决定

2:DRces

2:WR

3:RFoe

3:IRce

3:DRce

4:RYoe

4:RYce

5:ARoe

5:RXce

6:DRoe

6:RFce

7:SPoe

7:SPce

堆栈相关指令的功能和操作

和堆栈操作有关的指令主要有压栈指令PUSH、出栈指令POP、子程序调用指令CALL、子程序返回指令RET。

“PUSH dst”是单操作数指令,但本质上是双操作数的传送,相当于“MOV dst, - (SP)”,其中由SP指向的堆栈单元是隐含操作数,dst的本质是源,但是作为单操作数指令,只有取目的操作数阶段。在取目的操作数的微程序结束时,dst已经存放到RX暂存器中,也就是要放入堆栈的数据。因此在PUSH指令的执行阶段,要将RX暂存器中的“目的操作数”送到堆栈中去。

出栈指令“POP dst” 相当于“MOV (SP)+, dst”,也就是将栈顶单元的内容送给dst。dst可能在主存或寄存器,如果在主存中,其地址已经在取操作数阶段存放在AR中。但是在从堆栈中取出数据时,需要将SP的内容送给AR,这就破坏了AR中的目的地址;所以需要在此之前先将AR的内容保存到RY寄存器。此外栈顶单元的内容取出后还要将SP加1,使SP始终指向栈顶单元。

子程序调用指令(CALL)的功能是使程序转向目的地址,这一点和JMP转移指令是一样的,只要将AR的内容送给PC就可以了;不同的是CALL指令还要为子程序返回指令(RET)做好准备,将下一条指令的地址也就是当前PC的内容压入堆栈。而RET指令所要做的就是将栈顶单元内容取出装入PC中,使程序返回调用处继续执行。

实战:堆栈相关指令的微程序设计与调试

(1)PUSH和POP指令的微程序设计与调试。

用下面的调机程序验证PUSH和POP的微程序。观察堆栈指针SP、堆栈存储单元以及相关寄存器和内存单元的变化,理解堆栈的用法。

ORG 0030H
MOV #0041H,R0
PUSH R0        ;将R0寄存器内容压入堆栈
PUSH 0040H     ;将R0寄存器内容压入堆栈
POP (R0)       ;将当前栈顶内容存入主存0041H单元
POP R1         ;将当前栈顶内容存入R1寄存器

(2)编写CALL指令的微程序,并设计调机程序验证。

(3)编写RET指令的微程序,并设计调机程序验证。

注意观察子程序返回是否返回到正确的地址,以及返回后堆栈指针的变化。