JUC-3教学模型计算机概述
本章介绍一个教学模型计算机的设计,命名为JUC-3,是在JUC-II模型机基础上的改进和优化。为便于教学实施,JUC-3分为基本模块和扩展模块;扩展模块又分为指令增强模块和外设接口模块两类,指令增强模块增加了指令数量以及相应的硬件支持,外设接口模块扩充了输入输出接口和中断支持。
指令系统设计
JUC-3指令系统包含38条指令,涵盖了数据传送类指令、算术逻辑运算指令、移位指令、转移指令、子程序调用返回指令等。在寻址方式上采用最典型的寻址方式,有立即寻址、直接寻址、间接寻址、寄存器寻址、寄存器间接寻址、寄存器自增间接寻址、变址寻址、相对寻址等8种寻址方式。指令操作的数据宽度是字,不能按字节操作。
JUC-3的编程模型
图 1为面向汇编语言程序员的JUC-3的编程模型,包含CPU和主存两个功能模块,它们之间通过一组系统总线连接。
1. JUC-3微处理器的寄存器
JUC-3 CPU字长为16位。CPU内设置有一个通用寄存器组(Genenal Register Set,GRS),包含8个16位的通用寄存器R0~R7,用于存放参加运算的操作数和操作结果。还有2个专用寄存器:
程序计数器PC,16位,存放下一条将要执行的指令的地址。复位后PC的值为30H,即JUC-3程序中第一条指令的地址必须为30H;
程序状态字PSW,4位,存放当前指令执行后机器的状态标志信息,其中标志位包括借/进位标志CF,溢出标志OF,符号标志SF和零标志ZF;
堆栈指示器SP,存放堆栈栈顶的地址,复位后SP的值为30H。
指令格式及寻址方式
模型机的指令格式规整,所有的指令都可使用各种寻址方式(个别有限制的除外),所有的寄存器和存储单元都可同等对待。按照操作数个数的不同有三种指令格式:双操作数指令、单操作数指令和无操作数指令,如图 2所示。
指令系统采用操作码扩展技术,当双操作数指令的操作码部分(IR15-12)全为0时,表示扩展为单操作数指令,将双操作数指令的源操作数部分(IR11-6)用作单操作数指令的操作码。扩展无操作数指令时,将IR15-6全为0作为无操作数指令的标志,最低6位用作指令操作码。
指令格式中的Ms代表源操作数的寻址方式,Md代表目的操作数的寻址方式;Rs和Rd分别表示的是源操作数和目的操作数的寄存器号。寻址方式的编码见表 1。除了立即寻址不应作为目的寻址方式外,目的操作数和源操作数具有相同的寻址方式。
| 寻址方式 | 助记符 | 编码M |
|---|---|---|
寄存器寻址 |
Rn |
000 |
寄存器间接寻址 |
(Rn) |
001 |
寄存器自增间接寻址 |
(Rn)+ |
010 |
立即寻址 |
#imm |
011 |
直接寻址 |
addr |
100 |
间接寻址 |
(addr) |
101 |
变址寻址 |
disp(Rn) |
110 |
相对寻址 |
disp(PC) |
111 |
当寻址方式为表 1中的后面5种时,即M=011~111时,指令中还必须包含表示立即数、地址或偏移量的常数。常数的宽度均为一个字。因此根据目的操作数与源操作数寻址方式的不同,指令的总长度可能为单字、双字或三字。如果源和目的地址码均不包含常数,指令字长为一个字;如果源和目的地址码中有一个包含常数;指令字长为二个字;如果源和目的地址码中都包含常数;指令字长为三个字;如图 3所示。
指令类型
所有指令的指令编码见表 2,其中标有*号的是扩充的指令,标有**号的是和中断相关的指令。从指令功能上可分为以下几类。
指令助记符 |
指 令 编 码 |
影响PSW注 |
||||||||||||||||||
F |
E |
D |
C |
B |
A |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
S |
Z |
O |
C |
|
MOV src, dst |
0 |
0 |
0 |
1 |
源地址码 |
目的地址码 |
– |
– |
– |
– |
||||||||||
ADD src, dst |
0 |
0 |
1 |
0 |
源地址码 |
目的地址码 |
√ |
√ |
√ |
√ |
||||||||||
ADDC src, dst |
0 |
0 |
1 |
1 |
源地址码 |
目的地址码 |
√ |
√ |
√ |
√ |
||||||||||
SUB src, dst |
0 |
1 |
0 |
0 |
源地址码 |
目的地址码 |
√ |
√ |
√ |
√ |
||||||||||
SUBB src, dst |
0 |
1 |
0 |
1 |
源地址码 |
目的地址码 |
√ |
√ |
√ |
√ |
||||||||||
AND src, dst |
0 |
1 |
1 |
0 |
源地址码 |
目的地址码 |
√ |
√ |
× |
× |
||||||||||
OR src, dst |
0 |
1 |
1 |
1 |
源地址码 |
目的地址码 |
√ |
√ |
× |
× |
||||||||||
XOR src, dst |
1 |
0 |
0 |
0 |
源地址码 |
目的地址码 |
√ |
√ |
× |
× |
||||||||||
CMP src, dst |
1 |
0 |
0 |
1 |
源地址码 |
目的地址码 |
√ |
√ |
√ |
√ |
||||||||||
TEST src, dst |
1 |
0 |
1 |
0 |
源地址码 |
目的地址码 |
√ |
√ |
× |
× |
||||||||||
SAR dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
目的地址码 |
× |
× |
× |
√ |
|||||
SHL dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
目的地址码 |
× |
× |
× |
√ |
|||||
*SHR dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
目的地址码 |
× |
× |
× |
√ |
|||||
*ROL dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
目的地址码 |
× |
× |
× |
√ |
|||||
*ROR dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
目的地址码 |
× |
× |
× |
√ |
|||||
*RCL dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
目的地址码 |
× |
× |
× |
√ |
|||||
*RCR dst |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
目的地址码 |
× |
× |
× |
√ |
|||||
*JC dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
*JNC dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
目的地址码 |
– |
– |
– |
– |
|||||
*JO dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
*JNO dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
目的地址码 |
– |
– |
– |
– |
|||||
JZ dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
JNZ dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
目的地址码 |
– |
– |
– |
– |
|||||
*JS dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
*JNS dst |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
目的地址码 |
– |
– |
– |
– |
|||||
JMP dst |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
INC dst |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
目的地址码 |
√ |
√ |
√ |
√ |
|||||
DEC dst |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
目的地址码 |
√ |
√ |
√ |
√ |
|||||
NOT dst |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
目的地址码 |
√ |
√ |
× |
× |
|||||
*PUSH dst |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
*POP dst |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
目的地址码 |
– |
– |
– |
– |
|||||
*CALL dst |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
目的地址码 |
– |
– |
– |
– |
|||||
HALT |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
– |
– |
– |
– |
NOP |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
– |
– |
– |
– |
*RET |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
– |
– |
– |
– |
**RETI |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
– |
– |
– |
– |
**EI |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
– |
– |
– |
– |
**DI |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
– |
– |
– |
– |
2. 算术逻辑运算指令
双操作数运算指令有加法指令ADD、带进位的加法指令ADDC、减法指令SUB、带借位的减法指令SUBB、比较指令CMP,逻辑与指令AND、逻辑或OR、逻辑异或指令XOR,逻辑测试指令TEST。CMP指令执行减法运算并将运算产生的状态标志位保存到PSW,但不保存差。TEST指令执行逻辑与运算并将运算产生的状态标志位保存到PSW,但不保存两操作数按位进行与操作的结果。
单操作数运算指令有加1指令INC、减1指令DEC、逻辑反指令 NOT。
主存储器
主存储器的字长是16位,CPU地址总线也是16位,并且按字编址,不能按字节访问。因此主存空间为64K×16位。实验使用FPGA的片内存储器作为主存储器,容量可以根据片内RAM资源的多少而定,满足教学实验的需要即可。
复位时,PC的初始值为0030H,即主程序的第一条指令放在0030H单元。SP的初始值也为0030H,堆栈的存储空间为002FH~0008H。中断向量表的入口地址为0000H,一共预留了8个中断向量的存储空间;IO接口与主存统一编址,占用FF00H~FFFFH的地址空间。整个64K地址空间分配见表 3。
地址范围 |
分配用途 |
0000H~0007H |
中断向量表 |
0008H~002FH |
堆栈 |
0030H~FEFFH |
程序及数据 |
FF00H~FFFFH |
IO接口 |
微程序控制器
微指令寄存器µIR和微指令译码
微指令寄存器µIR保存从控存取出的微指令,可以分为微操作控制部分和顺序控制部分。微指令的顺序控制部分包括下址字段NA和转移方式字段BM。下址字段的位数由控存容量决定,模型机的微程序占用了256个地址空间,考虑到给扩充留下余量,下址字段设计为9位。转移方式BM字段设计为3位,具体在后面微地址形成一节介绍。
微操作控制部分采用字段直接编码方法对微命令组合。根据微命令的相容、相斥性以及并行操作的需要,将微操作控制部分分为8个字段,见表 4。
| 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 |
0:MOV |
0:NOP |
0:DST |
0:NOP |
0:NOP |
0:NOP |
||
1:PCoe |
1:PCce |
1:ADD |
1:PSWce |
1:SRC |
1:ARce |
1: PCinc |
1:RD |
||
2:DRoe |
2:IRce |
2:SUB |
2:DRces |
2:WR |
|||||
3:GRSoe |
3:GRSce |
3:AND |
3:DRce |
||||||
4:RYoe |
4:RYce |
4:OR |
|||||||
5:ARoe |
5:RXce |
5:XOR |
|||||||
6:RFoe |
6:RFce |
6:SR |
|||||||
7:SL |
|||||||||
8:NOT |
|||||||||
9:INC |
|||||||||
A:DEC |
|||||||||
B:ADDC |
|||||||||
C:SUBB |
微地址寄存器和微地址的形成
机器复位时微地址寄存器μAR的初始值决定了第一条微指令的地址,即取指令微程序的入口地址。JUC-3模型机取指令微程序的起始地址为0,故μAR复位时的初始值为0。
如图 6所示,后继微指令地址的形成和当前微指令、机器指令以及PSW状态条件有关。JUC-3模型机的微地址形成采用下址字段与断定测试相结合的方法。固定转移时,微地址直接由下址字段NA给出;根据测试结果转移时,微地址高位部分由下址字段NA的相应高位部分给出,微地址低位部分由测试结果给出。断定测试逻辑由硬件完成,测试条件主要来源于指令的操作码、寻址方式编码以及PSW中的标志位;在不同的场合有不同的测试条件,表 5给出了转移方式字段的编码及微转移地址的形成方法。各种转移方式的设计原理在后面随着设计深入再具体介绍。
| BM | 操作 | 意义 |
|---|---|---|
0 |
µAR = NA |
固定转移 |
1 |
µAR8,6-0 = NA8,6-0,µAR7 = INTR·IE |
根据是否有中断请求且是否允许中断产生两分支 |
2 |
µAR8-2 = NA8-2,
|
依据操作数个数的三分支微转移。如果是双操作数指令,则µAR1=0;如果是单操作数指令,则µAR1=1、µAR0=0;如果是无操作数指令,则µAR1=1、µAR0=1。 |
3 |
µAR8-1 = NA8-1, μAR0 = ƒ{OP, PSW(Z,O,S, C)} |
根据条件转移指令操作码和 PSW的ZF、OF、SF、CF 状态标志决定微地址,若满足条件μAR0=1,否则μAR0=0。 |
4 |
按操作码OP多路转移 |
按操作码OP形成多路微转移地址 |
5 |
µAR8-3 =NA8-3, µAR2-0 =M |
按寻址方式M形成多路微转移地址 |
6 |
保留 |
|
7 |
µAR8-1 = NA8-1, µAR0 = IR5 + IR4 + IR3 |
根据目的操作数寻址方式产生两分支:若Md=000(寄存器寻址),则μAR0=0;否则μAR0=1。 |
根据上面微转移地址的形成方法,表 6给出了一种微地址分配方案,读者也可以设计自己的微地址分配方案。
| 微程序 | 微地址 |
|---|---|
取指令 |
000H~003H |
取源操作数的入口 |
004H和005H |
取目标操作数的入口 |
006H |
指令执行阶段的入口 |
007H |
保留 |
008H~00BH |
执行结果存入目的操作数的微程序 |
00CH~00EH |
取源操作数微程序 |
00FH~027H |
取目标操作数微程序 |
028H~03FH |
单操作数指令的入口 |
041H~04FH |
无操作数指令的入口 |
060H~06FH |
双操作数指令的入口 |
071H~07FH |
中断响应隐指令的入口 |
080H |
微程序控制时序
如图 7,时序系统有两个周期相等的信号CP1和CP2;CP1将µAG形成的微指令地址打入µAR,启动了从控存读出微指令的操作;CP2将控存输出的微指令打入微指令寄存器µIR,开始执行这条微指令。下一条微指令的读出,表示当前微指令执行结束,也就是在每个CP1出现时还应该保存上一条微指令的执行结果,因此CP1还作为CPU内部各个寄存器的时钟脉冲。
模型机的时钟源由实验板的外部晶振提供,经过FPGA内部的锁相环调整为10MHz的系统时钟,每个微指令需要2个系统时钟周期,即微指令周期为0.2µS。复位时CP1为高、CP2为低,µAR清零;开始运行后第一个系统时钟首先使CP2上升沿到来,将000H控存单元的微指令打入微指令寄存器µIR,开始执行这条微指令;下一个系统时钟产生CP1上升沿,将该微指令的执行结果保存到相关寄存器,同时将µAG产生的下一条微指令地址打入µAR。也就是说,每个微指令周期CP2在先、CP1随后,循环往复。