目录
1. BEQZ (Branch if Equal to Zero)
2. BNEZ (Branch if Not Equal to Zero)
3. BGEZ (Branch if Greater or Equal to Zero)
4. BLTZ (Branch if Less Than Zero)
5. BEQI (Branch if Equal to Immediate)
6. BNEI (Branch if Not Equal to Immediate)
7. BGEI (Branch if Greater or Equal to Immediate)
8. BLTI (Branch if Less Than Immediate)
1. BLTUI (Branch if Less than Unsigned Immediate)
2. BBCI (Branch if Bit Clear Immediate)
3. BBSI (Branch if Bit Set Immediate)
6. BGE (Branch if Greater or Equal)
8. BGEU (Branch if Greater or Equal Unsigned)
2 ADDX2 (Add register shifted by 1)
3 ADDX4 (Add register shifted by 2)
4 ADDX8 (Add register shifted by 3)
5 SUB (Subtract two registers)
6 SUBX2 (Subtract register from register shifted by 1)
7 SUBX4 (Subtract register from register shifted by 2)
8 SUBX8 (Subtract register from register shifted by 3)
12 ADDMI (Add signed constant shifted by 8)
14 SALTU (Set AR if Less Than Unsigned)
1. EXTUI (Extract Unsigned Immediate Field)
2. SLLI (Shift Left Logical Immediate)
3. SRRLI (Shift Right Logical Immediate)
4. SRAI (Shift Right Arithmetic Immediate)
6. SRA (Shift Right Arithmetic)
9. SSA8B (Set Shift Amount for Big Endian)
10. SSA8L (Set Shift Amount for Little Endian)
11. SSR (Set Shift Right Register)
12. SSL (Set Shift Left Register)
13. SSAI (Set Shift Amount Immediate)
一 xtensa架构指令汇总
表1汇总了Xtensa架构所有版本中包含的核心指令。
表1. 核心指令总结
指令类别 | 指令 |
---|---|
加载 | L8UI, L16SI, L16UI, L32I, L32R |
存储 | S8I, S16I, S32I |
内存顺序 | MEMW, EXTW |
跳转,调用 | CALL0, CALLX0, RET J, JX |
条件分支 | BALL, BNALL, BANY, BNONE BBC, BBCI, BBS, BBSI BEQ, BEQI, BEQZ BNE, BNEI, BNEZ BGE, BGEI, BGEU, BGEUI, BGEZ BLT, BLTI, BLTU, BLTUI, BLTZ |
移动 | MOVNI, MOVEQZ, MOVGEZ, MOVLTZ, MOVNZE |
算术 | ADDI, ADDMI, ADD, ADDX2, ADDX4, ADDX8, SUB, SUBX2, SUBX4, SUBX8, NEG, ABS, SALT, SALTU |
位逻辑运算 | AND, OR, XOR |
移位 | EXTUI, SRLI, SRAI, SLLI SRC, SLL, SRL, SRA SSL, SSR, SSAI, SSA8B, SSA8L |
处理器控制 | RSR, WSR, XSR, RUR, WUR, ISYNC, RSYNC, ESYNC, DSYNC, FSYNC, NOP |
二 加载指令
在 Xtensa 汇编中,加载指令用于从内存中读取数据并将其加载到寄存器中。这些指令通常用于读取数组元素、结构体成员等。以下是几种常见的加载指令及其用途:
1. l32i
指令
- 用途:
- 用于从内存中加载一个 32 位的值到寄存器中。
- 格式:
l32i.n at, bt, imm
at
: 目标寄存器,用于存储读取的值。bt
: 基址寄存器,用于提供内存地址的基础值。imm
: 立即数偏移量,用于计算最终的内存地址。
示例
假设您需要从寄存器 a2
指向的内存地址加上偏移量 4
的位置加载一个 32 位的值到寄存器 a1
中。下面是使用 l32i
指令实现这一操作的示例:
asm
深色版本
1l32i.n a1, a2, 4
l32i.n a1, a2, 4
:- 从寄存器
a2
指向的内存地址加上偏移量4
的位置加载一个 32 位的值到寄存器a1
中。
- 从寄存器
2. l8i
指令
- 用途:
- 用于从内存中加载一个 8 位的值到寄存器中。
- 格式:
l8i.n at, bt, imm
at
: 目标寄存器,用于存储读取的值。bt
: 基址寄存器,用于提供内存地址的基础值。imm
: 立即数偏移量,用于计算最终的内存地址。
示例
假设您需要从寄存器 a2
指向的内存地址加载一个 8 位的值到寄存器 a1
中。下面是使用 l8i
指令实现这一操作的示例:
asm
深色版本
1l8i.n a1, a2, 0
l8i.n a1, a2, 0
:- 从寄存器
a2
指向的内存地址加载一个 8 位的值到寄存器a1
中。
- 从寄存器
3. l16i
指令
- 用途:
- 用于从内存中加载一个 16 位的值到寄存器中。
- 格式:
l16i.n at, bt, imm
at
: 目标寄存器,用于存储读取的值。bt
: 基址寄存器,用于提供内存地址的基础值。imm
: 立即数偏移量,用于计算最终的内存地址。
示例
假设您需要从寄存器 a2
指向的内存地址加载一个 16 位的值到寄存器 a1
中。下面是使用 l16i
指令实现这一操作的示例:
asm
深色版本
1l16i.n a1, a2, 0
l16i.n a1, a2, 0
:- 从寄存器
a2
指向的内存地址加载一个 16 位的值到寄存器a1
中。
- 从寄存器
4. ld
指令
- 用途:
- 用于从内存中加载一个双字(64 位)的值到两个寄存器中。
- 格式:
ld at, bt, imm
at
: 第一个目标寄存器,用于存储读取的值的高位部分。bt
: 第二个目标寄存器,用于存储读取的值的低位部分。imm
: 立即数偏移量,用于计算最终的内存地址。
示例
假设您需要从寄存器 a2
指向的内存地址加载一个 64 位的值到寄存器 a1
和 a0
中。下面是使用 ld
指令实现这一操作的示例:
asm
深色版本
1ld a1, a0, a2, 0
ld a1, a0, a2, 0
:- 从寄存器
a2
指向的内存地址加载一个 64 位的值,高位部分存储到寄存器a1
中,低位部分存储到寄存器a0
中。
- 从寄存器
5 总结
- 在 Xtensa 汇编中,提供了多种加载指令用于从内存中读取不同大小的数据到寄存器中。
- 这些指令包括
l32i
、l8i
、l16i
和ld
。 - 通过这些指令,您可以实现从内存中读取各种大小的数据,并将其加载到寄存器中以供进一步处理
三 存储指令
3.1 存储指令概述
存储指令 存储指令在地址形成方面类似于加载指令。存储内存错误不是同步异常;预计内存系统将使用中断来指示存储错误。
只有S32I和S32I.N可以访问InstRAM。
表1 显示了核心架构中的加载指令。
指令 | 格式 | 定义 |
---|---|---|
S8I | RR8 | 8位存储(8位偏移) |
S16I | RR8 | 16位存储(8位移位偏移) |
S32I | RR8 | 32位存储(8位移位偏移) |
3.2 存储指令详述
存储指令与加载指令类似,在地址生成方面。存储内存错误不是同步异常;预期内存系统将使用中断来指示存储错误。只有S32I和S32I.N可以访问InstRAM。
以下是每种存储指令的格式、使用示例和注意事项:
-
S8I (RR8): 8位存储(8位偏移)
- 格式: S8I Rd, Rs, [Rt]
- 示例:
assembly
这条指令将寄存器a1的低8位存储到地址a2+4处。1S8I a0, a1, [a2 + 4]
- 注意事项: 偏移量必须是8位的倍数。
-
S16I (RR8): 16位存储(8位移位偏移)
- 格式: S16I Rd, Rs, [Rt]
- 示例:
assembly
这条指令将寄存器a1的低16位存储到地址a2+8处。1S16I a0, a1, [a2 + 8]
- 注意事项: 偏移量必须是8位的倍数。
-
S32I (RR8): 32位存储(8位移位偏移)
- 格式: S32I Rd, Rs, [Rt]
- 示例:
assembly
这条指令将寄存器a1存储到地址a2+12处。1S32I a0, a1, [a2 + 12]
- 注意事项: 偏移量必须是8位的倍数。
这些指令用于将数据从寄存器存储到内存中。偏移量是一个8位的移位,这意味着它可以是0到255之间的任意值。在使用这些指令时,确保偏移量满足要求
四 内存顺序指令
4.1 内存顺序指令概述
Xtensa实现可以在任何顺序执行普通加载和存储操作,只要加载返回最后(如程序执行顺序所定义)单个处理器和简单内存中每个负载地址字节的最后一个值。这种灵活性是适当的,因为大多数内存访问只需要这些语义,并且一些实现可能能够通过利用非程序顺序内存访问来显著更快地执行程序。尽管许多实现采用更严格的排序,但Xtensa ISA仅要求实现遵循一种简化版本的发布一致性模型[的内存访问顺序。
然而,有些加载和存储指令不仅用于读取和写入存储,还会影响系统其他部分(例如,另一个处理器或I/O设备)的一些副作用。必须在程序顺序中执行此类位置的加载和存储。因此,Xtensa ISA提供了一个指令,可以用来给定程序顺序中的加载和存储内存访问顺序。
MEMW指令导致所有内存和缓存访问(加载、存储、获取、释放、预取和缓存操作,但不包括指令获取)在其自身之前,在程序顺序中访问内存的所有内存和缓存访问(但不包括指令获取)之后。应在每次加载或存储到volatile变量之间至少执行一次MEMW。多处理器同步选项提供了一些额外的指令,也以更集中的方式影响内存顺序。MEMW的应用范围比这些其他指令更广(例如,在读取和写入设备寄存器时),但它也可能比同步指令影响性能更大。
EXTW指令类似于MEMW,但在程序顺序中将所有外部效果与EXTW之前的指令分开,与EXTW之后的所有外部效果。EXTW是MEMW的超集,它包含程序顺序中的内存访问。
表1显示了核心体系结构中的内存顺序指令。
表1. 内存顺序指令
指令 | 格式 | 定义 |
---|---|---|
MEMW | RRR | 在内存访问前排序 |
EXTW | RRR | 在所有外部效果前排序 |
4.2 内存顺序指令详述
指令格式
MEMW
: 这是一个三操作数指令,格式为 RRR。EXTW
: 同样也是一个三操作数指令,格式也为 RRR。
指令实例
MEMW
指令的例子可能是:MEMW r0, r1, r2
这条指令表示将r1寄存器的内容作为内存地址,将r2寄存器的内容写入该地址,然后确保在此之后的所有内存访问(包括其他处理器的访问)都能看到这次写入。
EXTW
指令的例子可能是:EXTW r0, r1, r2
这条指令表示将r1寄存器的内容作为内存地址,将r2寄存器的内容写入该地址,然后确保在此之后的所有外部效应(包括I/O设备交互)能看到这次写入。
注意事项
- 使用
MEMW
和EXTW
指令时,应确保它们只应用于需要严格内存访问顺序的地方,否则可能会降低性能。 - 对于
MEMW
,它主要用于涉及volatile
变量的内存访问,因为它确保了在volatile
变量的加载或存储操作前后,内存访问都是有序的。 - 对于
EXTW
,它除了确保内存访问的顺序外,还确保所有外部效应(如I/O设备交互)也是有序的,因此更适合用于复杂的多处理器环境和I/O操作。 - 在编写多处理器程序或涉及I/O设备交互的程序时,应该仔细考虑何时使用这些指令,以确保程序的正确性和效率。
总之,MEMW
和EXTW
指令是Xtensa架构中用于确保内存访问顺序的重要工具,它们能帮助开发者在复杂环境中保持程序的一致性和正确性
五 跳转和调用指令
5.1 跳转和调用指令概述
跳转和调用指令 无条件分支指令J具有比条件分支更长的范围(与PC相关)。调用具有稍长的范围,因为它们针对32位对齐的地址。此外,跳转和间接调用指令提供了对案例分派、函数变量和动态链接的支持。 表3-15显示了跳转和调用指令。
指令 | 格式 | 定义 |
---|---|---|
CALL0 | CALL | 调用子例程,与PC相关 |
CALLX0 | CALLX | 调用子例程,地址在寄存器中 |
J | CALL | 无条件跳转,与PC相关 |
JX | CALLX | 无条件跳转,地址在寄存器中 |
RET | CALLX | 子例程返回——跳转到返回地址。用于从由CALL0/CALLX0调用的例程返回。 |
5.2 跳转和调用指令详述
以下是关于Xtensa汇编中的跳转和调用指令的一些信息:
1 CALL0:
- CALL0: 这是一种与PC相关的调用子例程的指令。它将当前PC值保存到返回地址寄存器,并跳转到目标地址执行子例程。格式如下:
assembly
深色版本
1CALL0 target_label
这里的target_label
是子例程的标签。注意,CALL0
只适用于短距离跳转,适合于在同一函数或附近函数之间跳转。
2 CALLX0
- CALLX0: 这是一种调用子例程的指令,地址在寄存器中。它将当前PC值保存到返回地址寄存器,并跳转到寄存器中的地址执行子例程。格式如下:
assembly
深色版本
1CALLX0 reg
这里的reg
是要跳转的地址所在的寄存器。
3 J
- J: 这是一种无条件跳转指令,与PC相关。它跳转到目标地址继续执行。格式如下:
assembly
深色版本
1J target_label
这里的target_label
是跳转的目标标签。J
指令的跳转范围比CALL0
更大,适合于较远距离的跳转。
4 JX:
- JX: 这是一种无条件跳转指令,地址在寄存器中。它跳转到寄存器中的地址继续执行。格式如下:
assembly
深色版本
1JX reg
这里的reg
是要跳转的地址所在的寄存器。JX
指令允许更大的跳转范围,适合于非常远的距离。
5 RET:
- RET: 这是一种子例程返回指令。它从返回地址寄存器中取出地址,跳转到那里继续执行。格式如下:
assembly
深色版本
1RET
RET
指令用于从子例程返回到调用者。它通常用于CALL0
或CALLX0
后的返回。
注意事项:
- 所有这些指令都涉及跳转或调用另一个子例程,所以在使用它们之前,确保已经正确设置了所需的参数和保存了必要的状态。
- 当使用
CALL0
和CALLX0
时,目标地址必须在一定范围内,否则会导致错误。J
和JX
的范围更广,但仍然有限制。 CALL0
和CALLX0
会保存当前PC值到返回地址寄存器,以便在子例程结束后能够返回。J
和JX
不会保存返回地址,因此不能直接用来调用子例程。RET
指令用于从子例程返回,它期望返回地址寄存器中有正确的地址。如果没有调用CALL0
或CALLX0
,使用RET
可能会导致未定义的行为。
模板:
assembly
深色版本
1; 使用CALL0调用子例程
2call_subroutine:
3 ; 子例程代码...
4 RET
5
6main:
7 ; ...
8 CALL0 call_subroutine
9 ; 继续执行主程序...
assembly
深色版本
1; 使用CALLX0调用子例程
2call_subroutine:
3 ; 子例程代码...
4 RET
5
6main:
7 ; ...
8 MOVI a0, &call_subroutine
9 CALLX0 a0
10 ; 继续执行主程序...
assembly
深色版本
1; 使用J跳转
2label:
3 ; 目标代码...
4
5main:
6 ; ...
7 J label
8 ; 不会到达这里...
assembly
深色版本
1; 使用JX跳转
2label:
3 ; 目标代码...
4
5main:
6 ; ...
7 MOVI a0, &label
8 JX a0
9 ; 不会到达这里...
assembly
深色版本
1; 使用RET返回
2call_subroutine:
3 ; 子例程代码...
4 RET
5
6main:
7 ; ...
8 CALL0 call_subroutine
9 ; 继续执行主程序...
六 条件分支指令
6.1 条件分支指令概述
条件分支指令(一)
表 3-16 列出了 Xtensa 汇编中的条件分支指令。这些指令用于比较一个寄存器操作数与零、立即数或者另一个寄存器值,并基于比较的结果进行条件分支。相比于其他 ISA,这些分支指令可以提高代码密度和性能。所有分支都是 PC 相对的;立即字段包含了 PC 相对的偏移量,范围从负三到零,这个区域被保留给未来的使用。
指令 | 格式 | 定义 |
---|---|---|
BEQZ | BR12 | 如果等于零则分支 |
BNEZ | BR12 | 如果不等于零则分支 |
BGEZ | BR12 | 如果大于或等于零则分支 |
BLTZ | BR12 | 如果小于零则分支 |
BEQI | BR8 | 如果等于立即数则分支 |
BNEI | BR8 | 如果不等于立即数则分支 |
BGEI | BR8 | 如果大于或等于立即数则分支 |
BLTI | BR8 | 如果小于立即数则分支 |
BGEUI | BR8 | 如果大于或等于无符号立即数则分支 |
解释
- BEQZ: 如果寄存器操作数等于零,则分支。
- BNEZ: 如果寄存器操作数不等于零,则分支。
- BGEZ: 如果寄存器操作数大于或等于零,则分支。
- BLTZ: 如果寄存器操作数小于零,则分支。
- BEQI: 如果寄存器操作数等于立即数,则分支。
- BNEI: 如果寄存器操作数不等于立即数,则分支。
- BGEI: 如果寄存器操作数大于或等于立即数,则分支。
- BLTI: 如果寄存器操作数小于立即数,则分支。
- BGEUI: 如果寄存器操作数大于或等于无符号立即数,则分支。
注意:表格中的脚注表示了编码有符号和无符号立即数的详细信息可以在表 3-17 和表 3-18 找到。
条件分支指令(二)
指令 | 格式 | 定义 |
---|---|---|
BLTUI | RR8 | 如果小于无符号立即数则分支 |
BBCI | RR8 | 如果位清零则分支 |
BBSI | RR8 | 如果位设置则分支 |
BEQ | RR8 | 如果等于则分支 |
BNE | RR8 | 如果不等于则分支 |
BGE | RR8 | 如果大于或等于则分支 |
BLT | RR8 | 如果小于则分支 |
BGEU | RR8 | 如果大于或等于无符号则分支 |
BLTU | RR8 | 如果小于无符号则分支 |
BANY | RR8 | 如果任意掩码位设置则分支 |
BNONE | RR8 | 如果没有掩码位设置(全清零)则分支 |
BALL | RR8 | 如果所有掩码位设置则分支 |
BNALL | RR8 | 如果并非所有掩码位设置则分支 |
BBC | RR8 | 如果位清零则分支 |
BBS | RR8 | 如果位设置则分支 |
注意:表格中的脚注表示了编码有符号和无符号立即数的详细信息可以在表 3-17 和表 3-18 找到。
解释
- BLTUI: 如果寄存器操作数小于无符号立即数则分支。
- BBCI: 如果寄存器操作数的某个位清零则分支。
- BBSI: 如果寄存器操作数的某个位设置则分支。
- BEQ: 如果寄存器操作数等于则分支。
- BNE: 如果寄存器操作数不等于则分支。
- BGE: 如果寄存器操作数大于或等于则分支。
- BLT: 如果寄存器操作数小于则分支。
- BGEU: 如果寄存器操作数大于或等于无符号则分支。
- BLTU: 如果寄存器操作数小于无符号则分支。
- BANY: 如果寄存器操作数的任意掩码位设置则分支。
- BNONE: 如果寄存器操作数的所有掩码位未设置(全清零)则分支。
- BALL: 如果寄存器操作数的所有掩码位设置则分支。
- BNALL: 如果寄存器操作数的并非所有掩码位设置则分支。
- BBC: 如果寄存器操作数的某个位清零则分支。
- BBS: 如果寄存器操作数的某个位设置则分支。
注意事项
- 这些指令提供了额外的条件分支选项,比如针对位测试和掩码操作。
- 在编写汇编代码时,应根据实际需要选择合适的指令。
总结
- 表格 续列出了 Xtensa 汇编中的条件分支指令。
- 这些指令包括
bltui
、bbci
、bbsi
、beq
、bne
、bge
、blt
、bgeu
、bltu
、bany
、bnone
、ball
、bnall
、bbc
和bbs
。 - 这些指令提供了丰富的条件判断和流程控制功能。
6.2 条件指令(一)概述
1. BEQZ
(Branch if Equal to Zero)
- 格式:
beqz reg, label
reg
: 寄存器。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
是否等于零,如果是,则跳转到标签 .zero
。下面是使用 beqz
指令实现这一操作的示例:
asm
深色版本
1beqz a1, .zero
beqz a1, .zero
:- 如果寄存器
a1
的值等于零,则跳转到标签.zero
。
- 如果寄存器
2. BNEZ
(Branch if Not Equal to Zero)
- 格式:
bnez reg, label
reg
: 寄存器。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
是否不等于零,如果不是,则跳转到标签 .non_zero
。下面是使用 bnez
指令实现这一操作的示例:
asm
深色版本
1bnez a1, .non_zero
bnez a1, .non_zero
:- 如果寄存器
a1
的值不等于零,则跳转到标签.non_zero
。
- 如果寄存器
3. BGEZ
(Branch if Greater or Equal to Zero)
- 格式:
bgez reg, label
reg
: 寄存器。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
是否大于或等于零,如果是,则跳转到标签 .greater_or_equal_zero
。下面是使用 bgez
指令实现这一操作的示例:
asm
深色版本
1bgez a1, .greater_or_equal_zero
bgez a1, .greater_or_equal_zero
:- 如果寄存器
a1
的值大于或等于零,则跳转到标签.greater_or_equal_zero
。
- 如果寄存器
4. BLTZ
(Branch if Less Than Zero)
- 格式:
bltz reg, label
reg
: 寄存器。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
是否小于零,如果是,则跳转到标签 .less_than_zero
。下面是使用 bltz
指令实现这一操作的示例:
asm
深色版本
1bltz a1, .less_than_zero
bltz a1, .less_than_zero
:- 如果寄存器
a1
的值小于零,则跳转到标签.less_than_zero
。
- 如果寄存器
5. BEQI
(Branch if Equal to Immediate)
- 格式:
beqi reg, imm, label
reg
: 寄存器。imm
: 立即数。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和立即数 10
,如果它们相等,则跳转到标签 .equal_to_10
。下面是使用 beqi
指令实现这一操作的示例:
asm
深色版本
1beqi a1, 10, .equal_to_10
逐行解释
beqi a1, 10, .equal_to_10
:- 如果寄存器
a1
的值等于立即数10
,则跳转到标签.equal_to_10
。
- 如果寄存器
6. BNEI
(Branch if Not Equal to Immediate)
- 格式:
bnei reg, imm, label
reg
: 寄存器。imm
: 立即数。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和立即数 10
,如果它们不相等,则跳转到标签 .not_equal_to_10
。下面是使用 bnei
指令实现这一操作的示例:
asm
深色版本
1bnei a1, 10, .not_equal_to_10
逐行解释
bnei a1, 10, .not_equal_to_10
:- 如果寄存器
a1
的值不等于立即数10
,则跳转到标签.not_equal_to_10
。
- 如果寄存器
7. BGEI
(Branch if Greater or Equal to Immediate)
- 格式:
bgei reg, imm, label
reg
: 寄存器。imm
: 立即数。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和立即数 10
,如果 a1
大于或等于 10
,则跳转到标签 .greater_or_equal_to_10
。下面是使用 bgei
指令实现这一操作的示例:
asm
深色版本
1bgei a1, 10, .greater_or_equal_to_10
逐行解释
bgei a1, 10, .greater_or_equal_to_10
:- 如果寄存器
a1
的值大于或等于立即数10
,则跳转到标签.greater_or_equal_to_10
。
- 如果寄存器
8. BLTI
(Branch if Less Than Immediate)
- 格式:
blti reg, imm, label
reg
: 寄存器。imm
: 立即数。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和立即数 10
,如果 a1
小于 10
,则跳转到标签 .less_than_10
。下面是使用 blti
指令实现这一操作的示例:
asm
深色版本
1blti a1, 10, .less_than_10
逐行解释
blti a1, 10, .less_than_10
:- 如果寄存器
a1
的值小于立即数10
,则跳转到标签 `.less_than_10
- 如果寄存器
6.3 条件指令(二)概述
1. BLTUI
(Branch if Less than Unsigned Immediate)
- 格式:
bltui at, imm, label
at
: 寄存器。imm
: 立即数。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和立即数 10
,如果 a1
小于 10
,则跳转到标签 .less_than_10
。下面是使用 bltui
指令实现这一操作的示例:
asm
深色版本
1bltui a1, 10, .less_than_10
bltui a1, 10, .less_than_10
:- 如果寄存器
a1
的值小于立即数10
,则跳转到标签.less_than_10
。
- 如果寄存器
2. BBCI
(Branch if Bit Clear Immediate)
- 格式:
bbci at, bitnum, label
at
: 寄存器。bitnum
: 位编号。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
的第 3 位是否清零,如果是,则跳转到标签 .bit_clear_3
。下面是使用 bbci
指令实现这一操作的示例:
asm
深色版本
1bbci a1, 3, .bit_clear_3
bbci a1, 3, .bit_clear_3
:- 如果寄存器
a1
的第 3 位清零,则跳转到标签.bit_clear_3
。
- 如果寄存器
3. BBSI
(Branch if Bit Set Immediate)
- 格式:
bbsi at, bitnum, label
at
: 寄存器。bitnum
: 位编号。label
: 跳转的目标标签。
示例
假设您需要检查寄存器 a1
的第 4 位是否设置,如果是,则跳转到标签 .bit_set_4
。下面是使用 bbsi
指令实现这一操作的示例:
asm
深色版本
1bbsi a1, 4, .bit_set_4
bbsi a1, 4, .bit_set_4
:- 如果寄存器
a1
的第 4 位设置,则跳转到标签.bit_set_4
。
- 如果寄存器
4. BEQ
(Branch if Equal)
- 格式:
beq at, bt, label
at
: 第一个寄存器。bt
: 第二个寄存器。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和 a2
的值,如果它们相等,则跳转到标签 .equal
。下面是使用 beq
指令实现这一操作的示例:
asm
深色版本
1beq a1, a2, .equal
beq a1, a2, .equal
:- 如果寄存器
a1
和a2
的值相等,则跳转到标签.equal
。
- 如果寄存器
5. BNE
(Branch if Not Equal)
- 格式:
bne at, bt, label
at
: 第一个寄存器。bt
: 第二个寄存器。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和 a2
的值,如果它们不相等,则跳转到标签 .not_equal
。下面是使用 bne
指令实现这一操作的示例:
asm
深色版本
1bne a1, a2, .not_equal
bne a1, a2, .not_equal
:- 如果寄存器
a1
和a2
的值不相等,则跳转到标签.not_equal
。
- 如果寄存器
6. BGE
(Branch if Greater or Equal)
- 格式:
bge at, bt, label
at
: 第一个寄存器。bt
: 第二个寄存器。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和 a2
的值,如果 a1
大于或等于 a2
,则跳转到标签 .greater_or_equal
。下面是使用 bge
指令实现这一操作的示例:
asm
深色版本
1bge a1, a2, .greater_or_equal
bge a1, a2, .greater_or_equal
:- 如果寄存器
a1
的值大于或等于寄存器a2
的值,则跳转到标签.greater_or_equal
。
- 如果寄存器
7. BLT
(Branch if Less Than)
- 格式:
blt at, bt, label
at
: 第一个寄存器。bt
: 第二个寄存器。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和 a2
的值,如果 a1
小于 a2
,则跳转到标签 .less_than
。下面是使用 blt
指令实现这一操作的示例:
asm
深色版本
1blt a1, a2, .less_than
blt a1, a2, .less_than
:- 如果寄存器
a1
的值小于寄存器a2
的值,则跳转到标签.less_than
。
- 如果寄存器
8. BGEU
(Branch if Greater or Equal Unsigned)
- 格式:
bgeu at, bt, label
at
: 第一个寄存器。bt
: 第二个寄存器。label
: 跳转的目标标签。
示例
假设您需要比较寄存器 a1
和 a2
的无符号值,如果 a1
大于或等于 a2
,则跳转到标签 .greater_or_equal_unsigned
七 移动指令
6.1 移动指令概述
移动指令
MOVI
设置寄存器为指令编码的常数。表 3-19 中列出的条件移动指令用于分支避免。
表 3-19. 移动指令
指令 | 格式 | 定义 |
---|---|---|
MOVI | RRI8 | 加载寄存器为 12 位带符号常数 |
MOVEQZ | RRR | 非零条件移动 |
MOVNEZ | RRR | 不等于零条件移动 |
MOVTZ | RRR | 小于零条件移动 |
MOVGEZ | RRR | 大于或等于零条件移动 |
解释
MOVI
指令设置寄存器为 12 位带符号常数。MOVEQZ
在非零条件下移动。MOVNEZ
在不等于零条件下移动。MOVTZ
在小于零条件下移动。MOVGEZ
在大于或等于零条件下移动。
示例
假设您希望在寄存器 a0
的值不为零时将 1
加载到寄存器 a1
,可以使用以下指令:
asm
深色版本
1moveqz a0, a1, 1
moveqz a0, a1, 1
:- 如果
a0
的值不为零,则将1
加载到a1
。
- 如果
注意事项
- 条件移动指令用于避免不必要的分支。
- 条件移动指令依赖于寄存器的值。
6.2 指令详解
1 MOVI
指令格式
MOVI
指令用于将 12 位带符号常数加载到寄存器。
asm
深色版本
1moVi rd, imm
示例
假设您希望将 -128
加载到寄存器 a0
,可以使用以下指令:
asm
深色版本
1moVi a0, -128
逐行解释
moVi a0, -128
:- 将
-128
加载到寄存器a0
。
- 将
注意事项
MOVI
指令支持 12 位带符号常数。- 常数范围为
-2^11
至2^11 - 1
。
2 MOVEQZ
指令格式
MOVEQZ
指令用于在非零条件下移动。
asm
深色版本
1moveqz rs, rt, imm
示例
假设您希望在寄存器 a0
的值不为零时将 1
加载到寄存器 a1
,可以使用以下指令:
asm
深色版本
1moveqz a0, a1, 1
逐行解释
moveqz a0, a1, 1
:- 如果
a0
的值不为零,则将1
加载到a1
。
- 如果
注意事项
MOVEQZ
指令仅在非零条件下执行。
3 MOVNEZ
指令格式
MOVNEZ
指令用于在不等于零条件下移动。
asm
深色版本
1movnez rs, rt, imm
示例
假设您希望在寄存器 a0
的值不等于零时将 2
加载到寄存器 a1
,可以使用以下指令:
asm
深色版本
1movnez a0, a1, 2
movnez a0, a1, 2
:- 如果
a0
的值不等于零,则将2
加载到a1
。
- 如果
注意事项
MOVNEZ
指令仅在不等于零条件下执行。
4 MOVTZ
指令格式
MOVTZ
指令用于在小于零条件下移动。
asm
深色版本
1movtz rs, rt, imm
示例
假设您希望在寄存器 a0
的值小于零时将 3
加载到寄存器 a1
,可以使用以下指令:
asm
深色版本
1movtz a0, a1, 3
movtz a0, a1, 3
:- 如果
a0
的值小于零,则将3
加载到a1
。
- 如果
注意事项
MOVTZ
指令仅在小于零条件下执行。
5 MOVGEZ
指令格式
MOVGEZ
指令用于在大于或等于零条件下移动。
asm
深色版本
1movgez rs, rt, imm
示例
假设您希望在寄存器 a0
的值大于或等于零时将 4
加载到寄存器 a1
,可以使用以下指令:
asm
深色版本
1movgez a0, a1, 4
movgez a0, a1, 4
:- 如果
a0
的值大于或等于零,则将4
加载到a1
。
- 如果
八 算术指令
8.1 算术指令概述
算术指令,包括带有少量移位的加法和减法,用于地址计算和合成常数乘法。ADDMI指令用于扩展加载和存储指令的范围。
表3.20. 算术指令
指令 | 格式 | 定义 |
---|---|---|
ADD | RRR | 两个寄存器相加 |
ADDX2 | RRR | 寄存器加上寄存器右移一位 |
ADDX4 | RRR | 寄存器加上寄存器右移两位 |
ADDX8 | RRR | 寄存器加上寄存器右移三位 |
SUB | RRR | 两个寄存器相减 |
SUBX2 | RRR | 寄存器减去寄存器右移一位 |
SUBX4 | RRR | 寄存器减去寄存器右移两位 |
SUBX8 | RRR | 寄存器减去寄存器右移三位 |
NEG | RRR | 取反 |
ABS | RRR | 绝对值 |
ADDI | RR8i | 加上带符号的立即数 |
ADDMI | RR8i | 加上带符号的立即数右移八位 |
SALT | RRR | 设置AR,如果小于则置零 |
SALTU | RRR | 设置AR,如果无符号小于则置零 |
Chapter 3. Core Architecture
Table 3.20. Arithmetic Instructions (continued)
指令 | 格式 | 定义 |
---|---|---|
ADDI | RR8i | 加上带符号的立即数 |
ADDMI | RR8i | 加上带符号的立即数右移八位 |
SALT | RRR | 如果小于则设置AR为0 |
SALTU | RRR | 如果无符号小于则设置AR为0 |
8.2 算术指令详述
1 ADD (Add two registers)
格式: ADD Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: ADD R0, R1, R2
- 将R1和R2的内容相加并将结果存储到R0。
注意事项:
- 注意溢出情况。
2 ADDX2 (Add register shifted by 1)
格式: ADDX2 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: ADDX2 R0, R1, R2
- 将R1的内容右移1位并与R2相加,结果存储到R0。
注意事项:
- 注意溢出情况。
3 ADDX4 (Add register shifted by 2)
格式: ADDX4 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: ADDX4 R0, R1, R2
- 将R1的内容右移2位并与R2相加,结果存储到R0。
注意事项:
- 注意溢出情况。
4 ADDX8 (Add register shifted by 3)
格式: ADDX8 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: ADDX8 R0, R1, R2
- 将R1的内容右移3位并与R2相加,结果存储到R0。
注意事项:
- 注意溢出情况。
5 SUB (Subtract two registers)
格式: SUB Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SUB R0, R1, R2
- 计算R1和R2之差并将结果存储到R0。
注意事项:
- 注意溢出情况。
6 SUBX2 (Subtract register from register shifted by 1)
格式: SUBX2 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SUBX2 R0, R1, R2
- 计算R1减去R2右移1位的结果,结果存储到R0。
注意事项:
- 注意溢出情况。
7 SUBX4 (Subtract register from register shifted by 2)
格式: SUBX4 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SUBX4 R0, R1, R2
- 计算R1减去R2右移2位的结果,结果存储到R0。
注意事项:
- 注意溢出情况。
8 SUBX8 (Subtract register from register shifted by 3)
格式: SUBX8 Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SUBX8 R0, R1, R2
- 计算R1减去R2右移3位的结果,结果存储到R0。
注意事项:
- 注意溢出情况。
9 NEG (Negate)
格式: NEG Rd, Rs
- Rd: 目标寄存器
- Rs: 源寄存器
实例: NEG R0, R1
- 将R1的内容取反并存储到R0。
注意事项:
- 注意溢出情况。
10 ABS (Absolute value)
格式: ABS Rd, Rs
- Rd: 目标寄存器
- Rs: 源寄存器
实例: ABS R0, R1
- 将R1的内容取绝对值并存储到R0。
注意事项:
- 注意溢出情况。
11 ADDI (Add signed constant)
格式: ADDI Rd, Rs, #imm
- Rd: 目标寄存器
- Rs: 源寄存器
- #imm: 带符号的立即数
实例: ADDI R0, R1, #10
- 将R1的内容加上10并存储到R0。
注意事项:
- 立即数必须在-128至+127之间。
12 ADDMI (Add signed constant shifted by 8)
格式: ADDMI Rd, Rs, #imm
- Rd: 目标寄存器
- Rs: 源寄存器
- #imm: 带符号的立即数右移8位
实例: ADDMI R0, R1, #10
- 将R1的内容加上10右移8位并存储到R0。
注意事项:
- 立即数必须在-128至+127之间。
13 SALT (Set AR if Less Than)
格式: SALT Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SALT R0, R1, R2
- 如果R1小于R2,则将R0设为全零;否则不变。
注意事项:
- 此指令仅考虑带符号比较。
14 SALTU (Set AR if Less Than Unsigned)
格式: SALTU Rd, Rs, Rt
- Rd: 目标寄存器
- Rs: 第一个源寄存器
- Rt: 第二个源寄存器
实例: SALTU R0, R1, R2
- 如果R1无符号小于R2,则将R0设为全零;否则不变
九 位逻辑指令
9.1 位逻辑指令概述
表1中的位逻辑指令提供了一个核心集,可以从中合成其他逻辑门电路。这些指令的立即形式不提供,因为立即值只能有四位。
表1. 位逻辑指令
指令 | 格式 | 定义 |
---|---|---|
RRR | 位逻辑与 | AND |
RRR | 位逻辑或 | OR |
RRR | 位逻辑异或 | XOR |
说明:
- "RRR" 指的是寄存器-寄存器-寄存器(Register-Register-Register)格式,表示操作涉及三个寄存器。
- "and" 表示逻辑与操作。
- "or" 表示逻辑或操作。
- "xor" 表示逻辑异或操作。
- "AR[r] ← AR[s] and AR[t]" 表示将寄存器 AR[s] 和 AR[t] 进行逻辑与操作的结果存回寄存器 AR[r]。
- 类似地,"AR[r] ← AR[s] or AR[t]" 和 "AR[r] ← AR[s] xor AR[t]" 分别表示逻辑或和逻辑异或操作。
9.2 位逻辑指令详述
位逻辑指令在表格中均标记为“RRR”格式,这表示它们是寄存器-寄存器-寄存器(Register-Register-Register)类型的指令。在这种格式中,指令操作涉及三个寄存器:两个源寄存器(通常标记为s和t)和一个目标寄存器(通常标记为r)。指令从两个源寄存器中读取值,执行指定的逻辑操作,然后将结果存储到目标寄存器中。
指令使用实例
-
AND(逻辑与)
- 格式:
AND r, s, t
- 指令使用实例:
AND a1, a2, a3
- 这将执行
a1 ← a2 and a3
操作,即将寄存器a2和a3中的值进行逻辑与操作,结果存储在寄存器a1中。
- 这将执行
- 格式:
-
OR(逻辑或)
- 格式:
OR r, s, t
- 指令使用实例:
OR b1, b2, b3
- 这将执行
b1 ← b2 or b3
操作,即将寄存器b2和b3中的值进行逻辑或操作,结果存储在寄存器b1中。
- 这将执行
- 格式:
-
XOR(逻辑异或)
- 格式:
XOR r, s, t
- 指令使用实例:
XOR c1, c2, c3
- 这将执行
c1 ← c2 xor c3
操作,即将寄存器c2和c3中的值进行逻辑异或操作,结果存储在寄存器c1中。
- 这将执行
- 格式:
9.3 注意事项
-
寄存器选择:确保在指令中使用的寄存器是有效的,并且符合处理器架构的要求。
-
操作结果:逻辑操作的结果将存储在目标寄存器中,确保该寄存器在后续操作前不会被意外修改。
-
性能考虑:虽然位逻辑操作通常很快,但在设计算法时仍应考虑其对整体性能的影响。
-
立即值不可用:表格中特别提到,这些位逻辑指令没有立即值形式,因为立即值通常只提供有限的位数(例如四位)。如果需要与立即值进行逻辑操作,可能需要先将立即值加载到寄存器中。
-
依赖关系:在执行依赖于先前位逻辑操作结果的指令时,请确保前面的操作已经完成并更新了目标寄存器的值。
-
应用场景:位逻辑指令在处理位掩码、位字段、位标志和进行条件测试时非常有用。了解它们的应用场景可以帮助更有效地使用这些指令
十 移位指令
10.1 移位指令概述
表1中的移位指令提供了一组丰富的操作,同时避免了关键的定时路径。参阅第25页的第3.3.2节以获得更多信息。
表1. 移位指令
指令 | 格式 | 定义 |
---|---|---|
EXTUI | RRR | 提取无符号字段立即数(右移0...31位,AND掩码为1...16个1) |
SLLI | RRR | 左移逻辑立即数1...31位(参阅第744页的立即数编码)。 |
SRRLI | RRR | 右移逻辑立即数0...15位位置 |
SRAI | RRR | 右移算术立即数0...31位位置 |
SRC | RRR | 右移组合(从SAR提取的通道移位) |
SRA | RRR | 右移算术(从SAR移位数量) |
SLL | RRR | 左移逻辑(从SAR移位数量的通道移位) |
SRL | RRR | 右移逻辑(从SAR移位数量的通道移位) |
SSA8B | RRR | 设置大端字节对齐的移位量寄存器(SAR) |
SSA8L | RRR | 设置小端字节对齐的移位量寄存器(SAR) |
SSR | RRR | 设置右移逻辑的移位量寄存器(SAR),该指令不同于WSSRtoSAR,只使用寄存器的五位最不重要位 |
SSL | RRR | 设置左移逻辑的移位量寄存器(SAR) |
SSAI | RRR | 设置移位量寄存器(SAR)的立即数 |
10.2 指令详述
这些指令是用于处理器中数据操作的一些基本命令,主要用于位移操作。下面我将根据指令的格式、使用实例和注意事项来逐一介绍这些指令。
1. EXTUI (Extract Unsigned Immediate Field)
格式: EXTUI Rd, Rn, #imm, #mask
- Rd: 目标寄存器
- Rn: 源寄存器
- #imm: 右移的位数(0-31)
- #mask: AND掩码(1-16个连续的1)
实例: EXTUI R0, R1, #4, #0x0F
- 将R1的内容右移4位后与0x0F进行AND操作,结果存储到R0。
注意事项:
- 确保掩码的长度与右移后的位宽匹配。
- 移位后的结果会被截断到指定的位宽。
2. SLLI (Shift Left Logical Immediate)
格式: SLLI Rd, Rn, #imm
- Rd: 目标寄存器
- Rn: 源寄存器
- #imm: 左移位数(1-31)
实例: SLLI R0, R1, #2
- 将R1的内容左移2位,结果存储到R0。
注意事项:
- 确保移位不会导致溢出。
3. SRRLI (Shift Right Logical Immediate)
格式: SRRLI Rd, Rn, #imm
- Rd: 目标寄存器
- Rn: 源寄存器
- #imm: 右移位数(0-15)
实例: SRRLI R0, R1, #3
- 将R1的内容右移3位(逻辑),结果存储到R0。
注意事项:
- 移位位数不能超过15位。
4. SRAI (Shift Right Arithmetic Immediate)
格式: SRAI Rd, Rn, #imm
- Rd: 目标寄存器
- Rn: 源寄存器
- #imm: 右移位数(0-31)
实例: SRAI R0, R1, #2
- 将R1的内容右移2位(算术),结果存储到R0。
注意事项:
- 算术移位会保持符号位。
5. SRC (Shift Right Combined)
格式: SRC Rd, Rn, SAR
- Rd: 目标寄存器
- Rn: 源寄存器
- SAR: 移位量寄存器
实例: SRC R0, R1, SAR
- 将R1的内容根据SAR寄存器中的值进行右移(逻辑/算术,取决于实现),结果存储到R0。
注意事项:
- 确保SAR寄存器的值符合预期。
6. SRA (Shift Right Arithmetic)
格式: SRA Rd, Rn, SAR
- Rd: 目标寄存器
- Rn: 源寄存器
- SAR: 移位量寄存器
实例: SRA R0, R1, SAR
- 将R1的内容根据SAR寄存器中的值进行算术右移,结果存储到R0。
注意事项:
- 确保SAR寄存器的值不超过最大移位位数。
7. SLL (Shift Left Logical)
格式: SLL Rd, Rn, SAR
- Rd: 目标寄存器
- Rn: 源寄存器
- SAR: 移位量寄存器
实例: SLL R0, R1, SAR
- 将R1的内容根据SAR寄存器中的值进行逻辑左移,结果存储到R0。
注意事项:
- 确保SAR寄存器的值不超过最大移位位数。
8. SRL (Shift Right Logical)
格式: SRL Rd, Rn, SAR
- Rd: 目标寄存器
- Rn: 源寄存器
- SAR: 移位量寄存器
实例: SRL R0, R1, SAR
- 将R1的内容根据SAR寄存器中的值进行逻辑右移,结果存储到R0。
注意事项:
- 确保SAR寄存器的值不超过最大移位位数。
9. SSA8B (Set Shift Amount for Big Endian)
格式: SSA8B SAR, Rn
- SAR: 移位量寄存器
- Rn: 源寄存器
实例: SSA8B SAR, R1
- 将R1的内容的大端字节对齐值写入SAR寄存器。
注意事项:
- 适用于大端模式。
10. SSA8L (Set Shift Amount for Little Endian)
格式: SSA8L SAR, Rn
- SAR: 移位量寄存器
- Rn: 源寄存器
实例: SSA8L SAR, R1
- 将R1的内容的小端字节对齐值写入SAR寄存器。
注意事项:
- 适用于小端模式。
11. SSR (Set Shift Right Register)
格式: SSR SAR, Rn
- SAR: 移位量寄存器
- Rn: 源寄存器
实例: SSR SAR, R1
- 将R1的低五位写入SAR寄存器作为移位量。
注意事项:
- 只使用源寄存器的最低五位。
12. SSL (Set Shift Left Register)
格式: SSL SAR, Rn
- SAR: 移位量寄存器
- Rn: 源寄存器
实例: SSL SAR, R1
- 将R1的内容写入SAR寄存器作为移位量。
注意事项:
- 通常用于设置左移的移位量。
13. SSAI (Set Shift Amount Immediate)
格式: SSAI SAR, #imm
- SAR: 移位量寄存器
- #imm: 立即数移位量
实例: SSAI SAR, #4
- 将4写入SAR寄存器作为移位量。
10.3 注意事项:
- 确保立即数符合指令要求的范围
十一 处理器控制指令
11.1 处理器控制指令概述
表1. 处理器控制指令
指令 | 格式 | 定义 |
---|---|---|
RSR | RSR | 读取特殊寄存器 |
WSR | RSR | 写入特殊寄存器 |
RSR | - | 交换特殊寄存器(此行为合并项,应为XSR,且在T1030及早期处理器中不存在) |
XSR | (组合的RSR和wSR) | 不存在于T1030及早期处理器中 |
RRR | - | 指令获取同步:等待所有之前获取的、影响指令获取的加载、存储、缓存和ISYNC特殊寄存器写入指令完成后再获取下一条指令。 |
RRR | RSYNC | 指令寄存器同步:等待所有之前获取的wSR和XSR指令完成后再解释下一条指令的寄存器字段。此操作也是ISYNC的一部分。 |
RRR | ESYNC | 寄存器值同步:等待所有之前获取的wSR和xSR指令完成后再在下一条指令中使用任何寄存器值。此操作也是ISYNC、RSYNC和ESYNC的一部分。 |
RRR | DSYNC | 加载/存储同步:等待所有之前获取的wSR和xSR指令完成后再解释下一条加载或存储指令的虚拟地址。此操作也是ISYNC、RSYNC和ESYNC的一部分。 |
FSYNC | RRR | 获取同步:实现定义。 |
NOP | RRR | 无操作 |
11.2 处理器控制指令详述
1 指令格式
对于处理器控制指令,指令格式通常取决于具体的处理器架构和指令集。不过,我们可以根据常见的RISC(精简指令集计算机)架构风格来概括这些指令的格式。在Xtensa处理器中,指令格式可能包括操作码(opcode)字段,以及一个或多个寄存器字段(用于指定源操作数、目标操作数或特殊寄存器)。
- RSR(读取特殊寄存器)
- 格式:
RSR <目标寄存器>, <特殊寄存器号>
- 示例:
RSR a2, SCOMPARE1
(假设SCOMPARE1
是特殊寄存器号,且a2
是目标寄存器)
- 格式:
- WSR(写入特殊寄存器)
- 格式:
WSR <源寄存器>, <特殊寄存器号>
- 示例:
WSR a1, SCOMPARE1
(假设a1
包含要写入的值,SCOMPARE1
是特殊寄存器号)
- 格式:
- XSR(交换特殊寄存器与AR[t])
- 格式:
XSR <源寄存器>, <特殊寄存器号>, <AR[t]寄存器号>
(假设格式,具体取决于实现) - 示例:无直接示例,因为此指令在T1030及早期处理器中不存在,且格式可能因实现而异。
- 格式:
- ISYNC、RSYNC、ESYNC、DSYNC
- 格式:
指令名
(这些指令通常不直接操作寄存器,因此没有标准的“寄存器, 寄存器”格式) - 示例:
ISYNC
、RSYNC
、ESYNC
、DSYNC
(直接作为指令使用)
- 格式:
- NOP(无操作)
- 格式:
NOP
(无操作数) - 示例:
NOP
- 格式:
2 指令使用实例
- 读取特殊寄存器
- 示例:读取性能计数器到寄存器
a2
assembly
RSR a2, PERFCOUNT1
- 示例:读取性能计数器到寄存器
- 写入特殊寄存器
- 示例:将寄存器
a1
的值写入到中断使能寄存器assembly
WSR a1, INTENABLE
- 示例:将寄存器
- 同步指令
- 示例:在执行了一系列写入特殊寄存器的操作后,确保所有写入完成
assembly
WSR a1, SCOMPARE1
WSR a2, SAR
ESYNC
- 示例:在执行了一系列写入特殊寄存器的操作后,确保所有写入完成
11.3 注意事项
-
寄存器号:确保在RSR、WSR和XSR指令中使用的特殊寄存器号是有效的,并且符合处理器文档中的规定。
-
同步需求:在写入特殊寄存器后,如果需要确保这些写入对后续指令可见,应使用适当的同步指令(如ESYNC)。
-
指令顺序:注意指令的执行顺序,特别是在需要同步操作的场景中。
-
性能影响:某些同步指令(如ISYNC、RSYNC、ESYNC、DSYNC)可能会对性能产生影响,因为它们可能导致处理器暂停执行以等待内部操作的完成。
-
处理器版本:注意不同版本的Xtensa处理器可能支持不同的指令集和功能。例如,XSR指令在T1030及早期处理器中不存在。
-
上下文保存与恢复:在中断处理或任务切换时,可能需要使用RSR和WSR指令来保存和恢复特殊寄存器的值。
-
权限问题:在某些情况下,写入特殊寄存器可能需要特定的权限或处于特定的处理器模式(如特权模式)
十二 内存顺序指令
12.1 内存顺序指令概述
Xtensa实现可以在任何顺序执行普通加载和存储操作,只要加载返回最后(如程序执行顺序所定义)单个处理器和简单内存中每个负载地址字节的最后一个值。这种灵活性是适当的,因为大多数内存访问只需要这些语义,并且一些实现可能能够通过利用非程序顺序内存访问来显著更快地执行程序。尽管许多实现采用更严格的排序,但Xtensa ISA仅要求实现遵循一种简化版本的发布一致性模型[的内存访问顺序。
然而,有些加载和存储指令不仅用于读取和写入存储,还会影响系统其他部分(例如,另一个处理器或I/O设备)的一些副作用。必须在程序顺序中执行此类位置的加载和存储。因此,Xtensa ISA提供了一个指令,可以用来给定程序顺序中的加载和存储内存访问顺序。
MEMW指令导致所有内存和缓存访问(加载、存储、获取、释放、预取和缓存操作,但不包括指令获取)在其自身之前,在程序顺序中访问内存的所有内存和缓存访问(但不包括指令获取)之后。应在每次加载或存储到volatile变量之间至少执行一次MEMW。多处理器同步选项提供了一些额外的指令,也以更集中的方式影响内存顺序。MEMW的应用范围比这些其他指令更广(例如,在读取和写入设备寄存器时),但它也可能比同步指令影响性能更大。
EXTW指令类似于MEMW,但在程序顺序中将所有外部效果与EXTW之前的指令分开,与EXTW之后的所有外部效果。EXTW是MEMW的超集,它包含程序顺序中的内存访问。
表1显示了核心体系结构中的内存顺序指令。
表1. 内存顺序指令
指令 | 格式 | 定义 |
---|---|---|
MEMW | RRR | 在内存访问前排序 |
EXTW | RRR | 在所有外部效果前排序 |
12.2 内存顺序指令详述
指令格式
MEMW
: 这是一个三操作数指令,格式为 RRR。EXTW
: 同样也是一个三操作数指令,格式也为 RRR。
指令实例
MEMW
指令的例子可能是:MEMW r0, r1, r2
这条指令表示将r1寄存器的内容作为内存地址,将r2寄存器的内容写入该地址,然后确保在此之后的所有内存访问(包括其他处理器的访问)都能看到这次写入。
EXTW
指令的例子可能是:EXTW r0, r1, r2
这条指令表示将r1寄存器的内容作为内存地址,将r2寄存器的内容写入该地址,然后确保在此之后的所有外部效应(包括I/O设备交互)能看到这次写入。
12.3 注意事项
- 使用
MEMW
和EXTW
指令时,应确保它们只应用于需要严格内存访问顺序的地方,否则可能会降低性能。 - 对于
MEMW
,它主要用于涉及volatile
变量的内存访问,因为它确保了在volatile
变量的加载或存储操作前后,内存访问都是有序的。 - 对于
EXTW
,它除了确保内存访问的顺序外,还确保所有外部效应(如I/O设备交互)也是有序的,因此更适合用于复杂的多处理器环境和I/O操作。 - 在编写多处理器程序或涉及I/O设备交互的程序时,应该仔细考虑何时使用这些指令,以确保程序的正确性和效率。
总之,MEMW
和EXTW
指令是Xtensa架构中用于确保内存访问顺序的重要工具,它们能帮助开发者在复杂环境中保持程序的一致性和正确性