68000

架构

[编辑] 地址总线

68000地址总线为24位,故支持16MB最大物理内存。在使用32位长字对地址进行存储和计算时,高位的一个字节会被自动忽略。这种设计使得其具备相当的向前兼容性,可以直接运行为后续的纯32位CPU编写的软件。也因此,根据现今的定义,68000应称得上是一款32位CPU。摩托罗拉使用32位内部总线的目的在于希望能够在68000上编写可以被将来的后续产品直接使用的软件,而相关指令不必作位数上的调整。

然而,编程人员还是有可能编写出无法与后续产品兼容的软件。倘若这种24位软件丢弃高位字节,或将该字节用作寻址以外的目的,它就有可能在32位68K系列CPU上运行失败。这就是说,对于希望支持向前兼容的软件,必须始终使用32位长字寻址,并且将最高位字节置零。

[编辑] 内部寄存器

68000包含8个32位通用寄存器(D0-D7),及8个32位地址寄存器(A0-A7)。最后一个地址寄存器,即A7,也作为标准指针使用,在编程中可以使用SP作为同义词。这组寄存器在规模上恰到好处:既可以对中断快速反应(只有十多个寄存器要保存),也有足够的寄存器来进行快速计算。

尽管两种寄存器并存有时会比较麻烦,但在实践中并非难于掌握。据称,这还使得CPU的设计者们可以通过对地址寄存器组使用辅助计算单元,从而实现较高程度的并行机制。

存储内容高位字节在前(Big Endian模式),与x86相反。

[编辑] 状态寄存器

68000比较、算术和逻辑操作会在状态寄存器SR的低端字节(又称CCR)中设置一些标志位,以供之后的条件跳转使用。这些标志位是:得零(Z)、进位(C)、溢出(V)、扩展(X)、负数(N)。尽管许多时候值是相同的,X与C依然是两个不同的标志位。这就允许算术、逻辑和移位操作的多余位与逻辑控制/连接造成的进位区别开。

[编辑] 指令集

68000的指令集基本上是正交的。大部分指令被划分成操作和地址模式两部分,并且大部分地址模式都对几乎全部指令可用。这种近似正交性在编程人员当中毁誉参半。

编程者会清楚地发现,他/她所书写的指令可能被汇编成几种不同的二进制操作码。这实际上是一种不错的妥协:一方面,在便利性上与纯粹的正交指令系统相仿;一方面,CPU设计者可以有更多的自由来设计操作码表。

对于一台16位时代的机器而言,由56条指令构成的最小指令集仍显巨大。此外,许多指令和寻址模式会在指令后边加入地址/寻址模式码。

许多设计者确信MC68000体系结构应基于成本考量使用较精简的指令码,特别是使用编译器自动生成时。这种认识为对其设计上的成功加分不少,并且使之成为一种经久不衰的体系结构。这一信条持续地保证了整个系列指令集的设计优势,直到ARM体系结构引入同样精简的Thumb指令集。

[编辑] 特权级

68K系列CPU包含两个特权级。超级用户(supervisor)模式和用户(user)模式。后者相比于前者只是禁用了中断级控制。中断总会使CPU进入超级用户态。超级用户标志位存储于状态寄存器SR中,并对用户可见。

超级用户态下会有一个分离的栈指针用于中断处理。

[编辑] 中断

68000可以识别7级中断,从级别1到级别7。7级中断严格按优先级排列,一个高级中断总是能嵌套于一个低级中断。可以使用专门的特权指令在SR内设置最小中断级别,从而屏蔽所有小于此级别的中断。但如果设置为0,表示不接受中断。级别7不可被屏蔽,即NMI。级别1总是可以被高级中断打断。

硬件中断源将中断信号以编码方式通过三条输入线传送给CPU。一般会使用专门的中断控制器来汇总各外部设备,并将中断信号按级编码与CPU硬连。中断控制器可以使用简单如74LS148优先级编码器,复杂如MC68901多功能外设(支持可编程中断控制、通用异步收发装置、定时器及并行输入输出等)等各种电路模块。

在内存低1K位置存储中断向量表,共支持256条中断向量。部分中断向量有特殊用途:向量1为初始栈地址;向量2为初始代码地址;向量3到15用于错误报告,包括总线错误、寻址错误、非法指令、除零异常、优先权违反等。从向量24起处理真正的中断,包括伪中断、针对级别1到级别7的默认处理向量,多达15个自陷向量,以及用户定义向量。

由于必须在重启时保证向量1和2的内容有效,所以68000系统通常包含在地址底部使用非易失性存储器(如ROM)来存储一些例程向量和启动代码。但是,一个通用计算机的操作系统会期望在运行时改变向量内容。解决办法是将ROM内的向量指向RAM的分支表,或使用早期在8位CPU中广泛使用的换页技术(Bank switching)。

由于包含一条非特权指令MOVE from SR,允许一般用户只读地访问某些特权状态,68000并未完全满足波佩克与戈德堡虚拟化需求。该需求指出了为构建某一CPU之等价虚拟机而对CPU提出的若干要求。

MC68000对虚拟内存缺乏方便的支持。一款支持虚拟内存的CPU应能在内存访问失败后自陷并恢复。不过,68000确实提供了一个总线错误异常来使CPU自陷,尽管还不能保存足够的状态信息以便于异常处理之后的恢复。为此,一些Unix工作站通过使用两块68000来解决虚拟内存问题。两块CPU的运行时钟存在相位差。当第一块遇到寻址异常后,特殊的硬件会设法向第二块发出中断,以防止其也访问错误地址。中断例程在第二块CPU上处理完内存换页后,会按之前的状态重启第一块CPU,从而再次使两CPU同步。

不过,以上这些问题在MC68010被彻底解决。在MC68010中,总线异常和地址错误均会使大量状态信息压入系统栈,以便于之后的恢复。MOVE from SR也被修正为特权指令。原本用于访问SR低端字节的代码可由新指令MOVE from CCR取代。

[编辑] 指令集细节

[编辑] 标准寻址模式

68000提供多种寻址模式,并统称为有效寻址(EA)。在CPU参考手册中,经常会有诸如MOVE <ea>,<ea>这样的表记方式。这表示在目的操作数和源操作数上可分别使用一种(但通常不是全部)有效寻址。

  • 寄存器直接寻址
    • 数据寄存器直接寻址,如D0。
    • 地址寄存器直接寻址,如A0。通常不使用A7。
  • 寄存器间接寻址
    • 简单间址,如(A0)。先取得A0所存储的地址,再在内存中该地址处取出数据。
    • 自增间址,如(A0)+。只能用于源操作数域。先取得A0所存储的地址,再在内存中该地址处取出数据,然后A0的内容(地址)自增一定长度(因指令后缀而定)。这个操作其实相当于x86中的出栈指令POP(注意栈的方向和内存方向相反)。在这里,A0被用作一个用户自定义的栈指针,与系统使用的A7/A7'不同。
    • 自减间址,如-(A0)。可用于源或目的操作数域。先将A0的内容(地址)自减一定长度(因指令后缀而定);然后取得A0所存储的地址,再在内存中该地址处存入数据,然后这个操作其实相当于x86中的入栈指令PUSH。[1]
    • 偏移间址,如2AFF(A0)。前边的偏移量为16位。实际取得的地址为(A0)+2AFF。
    • 加索引的偏移间址,如E3(A0, D0)。前边的偏移量为8位。实际取得的地址为(A0)+(D0)+E3。
  • 程序计数器位移
    • 长位移,如2AFF(PC)。前边的偏移量为16位。PC变为(PC)+2AFF。
    • 短位移,如E3(PC, D0)。前边的偏移量为8位。PC变为(PC)+(D0)+E3。
  • 绝对内存寻址
    • 直接使用内存地址值,如$4000,表示目标地址在内存地址为4000处。注意$表示后边所跟数字为16进制,%表示2进制。
    • 在实际编程中,可以使用代码中的标号来充当内存地址值。汇编器会自动翻译为数字地址。
    • 注意不应与立即数混淆。使用立即数时应在值前再加一个#。$4000表示16进制地址4000;#$4000表示16进制立即数4000;4000表示10进制地址4000;#4000表示10进制立即数4000。

[编辑] 指令后缀

大部分指令都有表示操作长度的后缀:.B、.W或.L,分别表示这一操作在字节(8比特)上、字(16比特)上或长字(32比特)上进行。运算的过程和结果都会受到后缀的影响。在运算过程中,只有属于操作长度范围的部分才会参与运算。比方说,执行MOVE.B D2,D1会把D1的最低一字节复制到D2的最低一字节处,而两者的其余字节均不受影响。对于CCR,各标志位的值会由操作长度的最高有效位决定。如果某次ADD.B使得结果的第7Bit位为1,则CCR的N位会置1;如果某次ADD.L使得结果的第7Bit位为1,并且第15Bit不为1,则CCR的N位不会置1。在后一种情况下,CCR的N位只受第15Bit,即一个字的最高有效位影响。另一个例子是在自增/自减寻址中,自增/自减的长度因操作后缀而异。如果操作为MOVE.B,则自增/自减1;W为2;L为4。

[编辑] 常用指令

大部分68000的指令都是二元的。目的操作数在前,源操作数在后。

  • 移动指令
    • MOVE:标准移动指令。另有一些其它移动指令供选择:MOVEA(移动到地址寄存器An,不会影响CCR,但后缀不可为.B)、MOVEQ(移动一个8位数到目标寄存器,因为可将数值直接写入指令故称快速移动)、MOVEM(移动寄存器组到指定堆栈,多用于中断/子程序处理的第一步)等。
    • LEA:移动一个地址值到目标寄存器。LEA $2000,A0表示将A0的值设为16进制的2000。应注意此时不加立即数标志#。
    • LINK/ULNK:建立/取消堆栈帧。这个指令用于翻译高级语言的函数调用。LINK An, #-x可将An作为函数栈指针,并SP所指向的用户栈内取得x大小的空间存储局部变量,之后SP仍将指向栈顶,而An指向栈顶+x的位置。x的值在编译时由编译器自动算出。
  • 算数指令:ADD(加)、SUB(减)、MULU /MULS(无/有符号乘)、DIVU/DIVS(无/有符号除)、NEG (取补)、及CMP(类似于减但只会影响标志位而不改变操作数)。算数指令也多成组提供。对于ADD,还有ADDA(加地址,不会影响标志位)、ADDI(加立即数)、ADDQ(快速加,加数不大于8以便于直接放在操作码中,比x86的INC指令书写麻烦但功能更强)、ADDX(影响进位符,用于大数运算)等。
  • BCD码算数指令:ABCD(加)和SBCD(减)。
  • 移位指令
    • 逻辑移位(移位后用0补充):LSL(左移)、LSR(右移)
    • 算数移位(移位后用原来最高/最低有效位补充):ASL(左移)、ASR(右移)
    • 循环移位(移位后用所移动位补充):ROL(左移)、ROR(右移)
    • 循环扩展移位(移位至CCR的X位,同时用之前的X位补充):ROXL(左移)、ROXR(右移)
  • 位操作指令:BSET(置1)、BCLR (清0)和BTST (如果测试位在改变前为0则将CCR的Z设为1)。
  • 多任务处理:TAS(测试并置位)。这个指令用于实现信号灯等同步机制。
  • 流程控制:JMP(无责任跳转)、 JSR (跳转至子例程)、BSR (按相对地址跳转至子例程,多用于跳转至用户定义例程)、RTS (从子例程返回)、RTE (从异常/中断中返回)、 TRAP(自陷,即软中断)、CHK(检查地址是否越界,如是则触发异常)。
    • JMP指令只是纯粹跳转,不会将下一条指令地址压栈;JSR和BSR会将下一条指令压栈。
    • RTS将栈指针指向内容弹出给PC。
  • 条件测试并跳转:Bcc系列指令。cc定义了所测试的条件位。常用的如:
    • BNE:不等于时跳转。
    • BEQ:等于时跳转。
    • BRA:无条件跳转。
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值