0x10c吧 关注:445贴子:4,053
  • 0回复贴,共1

DCPU16文档翻译

取消只看楼主收藏回复

DCPU-16 规范
Copyright 1985 Mojang
版本 1.7
摘要:
16 bit 一个词(具体指变量)
内存可以容纳0x10000个词
8个寄存器(A,B,C,X,Y,Z,I,J)
程序计数器(PC)
栈指针(SP)
溢出(EX)
中断地址(IA)
在这个文档中,任何在[括号]的东西在程序里都相当于“括号内内存指针的值”。例如,SP的意思是堆栈指针,但[SP]代表着堆栈中的位置指针指向的内存的值。
每当CPU需要读取一个词,都会读取[PC],然后将PC增加1,相当于[PC++],在某些情况下,CPU将读取修改前的值,在这种情况下,应改成[++PC]
为了稳定性和减少bug,强烈建议所有DCPU-16的程序的多词运行尽可能都使用小字节序
指令:
每个指令长1~3个字,由第一个字来定义命令含义。在基本指令中,指令第一个单词低五位是操作码,其余十一位分为5位的值称为B和6位的值称为A
b总是在处理器处理完a以后处理,并且低五位,在bits中(以LSB-0标准),一个普通的指令格式为:aaaaaabbbbbooooo
在下表中,C是查询数值或者执行操作码所需要的时间周期,VALUE是具体的数值,NAME是助记符,DESCRIPTION是用于表示操作码或值一串简短的描述
--- 数值: (5/6 bits) ---------------------------------------------------------
C | VALUE | DESCRIPTION
---+-----------+----------------------------------------------------------------
0 | 0x00-0x07 | register (A, B, C, X, Y, Z, I or J, in that order)
0 | 0x08-0x0f | [register]
1 | 0x10-0x17 | [register + next word]
0 | 0x18 | (PUSH / [--SP]) if in b, or (POP / [SP++]) if in a
0 | 0x19 | [SP] / PEEK
1 | 0x1a | [SP + next word] / PICK n
0 | 0x1b | SP
0 | 0x1c | PC
0 | 0x1d | EX
1 | 0x1e | [next word]
1 | 0x1f | next word (literal)
0 | 0x20-0x3f | literal value 0xffff-0x1e (-1..30) (literal) (only for a)
--+-----------+----------------------------------------------------------------
*“next word”意思是“[PC++]”,将指令单词长度增加1
*将0x18 0x19 0x1a使用到PEEK,POP/PUSH以及PICK,就会进行从0xffff开始的反向堆栈,例如:"SET PUSH,10","SET X,POP"
*试图写入一个字面意义的值会出错并静默
--- 基本操作码 (5 bits) ----------------------------------------------------
C | VAL | NAME | DESCRIPTION
---+------+----------+---------------------------------------------------------
- | 0x00 | n/a | 特别指示 - 见下文
1 | 0x01 | SET b, a | 将b设为a
2 | 0x02 | ADD b, a | 将b设置为b + a,如果有溢出,则将EX设置为0x0001
| | | 否则设为0x0
2 | 0x03 | SUB b, a | 将b设置为b-a,如果存在下溢,则将EX设置为0xffff,
| | | 否则为0x0
2 | 0x04 | MUL b, a | 设置b为b*a, 设置 EX 为 ((b*a)>>16)&0xffff (对于 b
| | | ,a是没有符号的)
2 | 0x05 | MLI b, a | 类似于MUL,但b和a有符号
3 | 0x06 | DIV b, a | 设置b为b/a, 设置 EX 为 ((b<<16)/a)&0xffff. 如果 a==0,
| | | 设置 b 和 EX 为 0. (对于 b, a 没有符号)
3 | 0x07 | DVI b, a | 类似于 DIV,但是b和a有符号.
3 | 0x08 | MOD b, a | 设置b为b%a. 如果 a==0, 设置 b 为 0.
3 | 0x09 | MDI b, a |类似于MOD, 但是b,a有符号. (MDI -7, 16 == -7)
1 | 0x0a | AND b, a | 设置b为b&&a
1 | 0x0b | BOR b, a | 设置b为 b|a
1 | 0x0c | XOR b, a | 设置b 为 b^a
1 | 0x0d | SHR b, a | 设置b为 b>>>a, 设置 EX 为 ((b<<16)>>a)&0xffff
| | | (logical shift)
1 | 0x0e | ASR b, a | 设置b为 b>>a, 设置 EX 为 ((b<<16)>>>a)&0xffff
| | | (arithmetic shift) (treats b as signed)
1 | 0x0f | SHL b, a | 设置b为 b<<a, 设置EX为 ((b<<a)>>16)&0xffff
2+| 0x10 | IFB b, a | 仅执行下一条指令 if (b&a)!=0
2+| 0x11 | IFC b, a | 仅执行下一条指令 if (b&a)==0
2+| 0x12 | IFE b, a | 仅执行下一条指令 if b==a
2+| 0x13 | IFN b, a | 仅执行下一条指令 if b!=a
2+| 0x14 | IFG b, a |仅执行下一条指令 if b>a
2+| 0x15 | IFA b, a | 仅执行下一条指令 if b>a (signed)
2+| 0x16 | IFL b, a |仅执行下一条指令 if b<a
2+| 0x17 | IFU b, a | 仅执行下一条指令 if b<a (signed)
- | 0x18 | - |
- | 0x19 | - |
3 | 0x1a | ADX b, a | 设置b为 b+a+EX, 设置EX为 0x0001 if there is an over-
| | | flow, 0x0 otherwise
3 | 0x1b | SBX b, a | 设置b为 b-a+EX, 设置EX为 0xFFFF if there is an under-
| | | flow, 0x0 otherwise
- | 0x1c | - |
- | 0x1d | - |
2 | 0x1e | STI b, a | 设置b为a,然后I和J增加1
2 | 0x1f | STD b, a | 设置b为a, 然后I和J减去1
---+------+----------+----------------------------------------------------------
*带符号的数字用二进制补码表示。
特别码总是有自己低五位设置,有一个值和一五位码。在二进制,他们有格式:aaaaaaooooo00000值(a)在同样的六位前面定义的格式。
--- 特别码: (5 bits) --------------------------------------------------
C | VAL | NAME | DESCRIPTION
---+------+-------+-------------------------------------------------------------
- | 0x00 | n/a | 预留扩展
3 | 0x01 | JSR a | 将下一条指令的地址压入堆栈,
| | | 然后设置PC为a
- | 0x02 | - |
- | 0x03 | - |
- | 0x04 | - |
- | 0x05 | - |
- | 0x06 | - |
- | 0x07 | - |
4 | 0x08 | INT a | 使用a触发软件中断
1 | 0x09 | IAG a | 设置a为IA
1 | 0x0a | IAS a | 设置IA为a
3 | 0x0b | RFI a | 禁用中断队列,从堆栈中弹出A,然后
| | | 从堆栈中弹出PC
2 | 0x0c | IAQ a | 如果a为非零值,则中断将添加到队列中
| | | 而不是触发。如果a为零,则中断为
| | | 再次正常触发
- | 0x0d | - |
- | 0x0e | - |
- | 0x0f | - |
2 | 0x10 | HWN a | 将a设为连接的硬件设备的数量
4 | 0x11 | HWQ a | 设置A,B,C,X,Y寄存器以获取有关硬件a的信息
| | | A +(B << 16)是一个32位字,用于标识硬件ID
| | | C是硬件版本
| | |X +(Y << 16)是一个32位字,用于标识制造商
4+| 0x12 | HWI a | 向硬件发送中断
- | 0x13 | - |
- | 0x14 | - |
- | 0x15 | - |
- | 0x16 | - |
- | 0x17 | - |
- | 0x18 | - |
- | 0x19 | - |
- | 0x1a | - |
- | 0x1b | - |
- | 0x1c | - |
- | 0x1d | - |
- | 0x1e | - |
- | 0x1f | - |
---+------+-------+-------------------------------------------------------------
中断:
DCPU-16在每条指令之间最多执行一次中断。如果
多个中断同时被触发,它们会被添加到一个队列中。
如果队列的长度超过256个中断,DCPU-16就会着火(原文为catch fire,有歧义)。
当IA设置为非0时,在DCPU-16上触发中断
将打开中断队列,将PC推入堆栈,然后将A推入
堆栈,然后将PC设置为IA,将A设置为中断消息。
如果IA设置为0,则触发的中断不执行任何操作。仍然软件中断
占用四个时钟周期,但立即返回,传入的硬件中断
被忽略。请注意,排队中断在离开时被视为已触发
队列,而不是进入队列时。
中断处理程序应以RFI结尾,这将禁用中断排队
然后将A和PC作为单个原子指令从堆栈中弹出。
IAQ通常在中断处理程序中是不需要的,但是对时间关键代码很有用

硬件:
DCPU-16最多支持65535个连接的硬件设备。这些设备可以是其他存储设备,传感器,监视器或扬声器中的任何东西。
每个硬件设备都指定了如何控制硬件,但是DCPU-16
支持通过以下方式检测连接的硬件的标准枚举方法
HWN,HWQ和HWI指令。
发送到硬件的中断不能包含消息,可以进行额外的循环,并且可以读取或修改 DCPU-16 上的任何寄存器或内存地址。此行为会更改每个硬件设备,并在硬件文档中描述。
在至少对硬件进行一次HWI调用之前,硬件不得开始修改DCPU-16的寄存器或RAM。
DPCU-16 不支持热交换硬件。DCPU-16 运行时连接或断开硬件的行为具有不确定性。


IP属地:广东1楼2021-05-02 15:44回复