这是我在 Stack Overflow 上的第一篇文章,所以我希望我做得正确。;-)
我正在尝试开发 TriCore 仿真器,但无法决定何时加载指令操作数的策略。TriCore 可能是一种相当不起眼的微控制器,所以让我稍微解释一下架构。
有两种类型的指令,16 位和 32 位。是16位还是32位,由最后一个字节的位0决定;由于字节顺序是小端,它始终是内存中的第一个字节。那里没问题。
这两种指令类型有几种操作码格式,14 种用于 16 位指令,25 种用于 32 位指令。操作码分为两个独立的操作码字段,尽管大多数 16 位的操作码只有一个操作码字段。第一个操作码字段在低 8 位;它直接描述了 16 位指令的指令,对于许多 32 位指令,它描述了操作数编码,而第二个字段描述了实际指令(当然也有例外)。
我的计划是始终提取所有操作码字段(这有点烦人,因为第二个字段的位置对于所有指令格式都不相同)并将它们放在一起成一个 16 位值,该值将用于函数指针表.
根据这个值,我想提取操作数。例如,当在 32 位指令中第一个操作码是0x8B
时,操作数是两个数据寄存器和一个 9 位常量。但是,也有一些非常乏味的例外情况:
ADD.A
andADDSC.A
指令都有操作码 1 0x01
== 。但是ADD.A
使用三个地址寄存器,而ADDSC.A
使用两个地址寄存器,一个数据寄存器和一个索引,编码到指令中。
最后我的问题是:在执行指令之前在这样的架构中加载操作数是否可行?还是先调用指令函数并在那里提取操作数会更好?
对于任何感兴趣的人,指令集手册在这里:http ://www.infineon.com/dgdl/tc_v131_instructionset_v138.pdf?folderId=db3a304412b407950112b409b6cd0351&fileId=db3a304412b407950112b409b6dd0352
感谢您的任何提示!
顺便说一句:选择的语言是 C 或 C++。
(应要求,我将我的想法插入到我原来的问题中。)
好吧,我广泛考虑了我拥有的不同选择,我想我会解决以下问题。
我将整个过程分为两个部分:
- 程序分析和操作数提取
- 执行
在第一步中,每条指令都被加载并对齐到 32 位。然后将加载的指令与一组位掩码进行比较,以确定正确的操作码,它不仅告诉我最终必须执行什么,还告诉我如何加载操作数。在特定于地址模式的函数中,操作数被加载到指针中;指令立即数根据需要存储。
这归结为类似于以下的结构:
struct instruction_t {
int32_t **operands;
int32_t *immediates;
};
这将基本上分配给每条指令(最大的缺点:内存消耗。我为这种最坏情况(使用 64 位指针)的结构计算了大约 40 个字节,这意味着通常只有 16 位指令的 4 MB 程序将最终占用大约 80 兆内存。另一方面,我认为执行速度可能相当快)。
使用这种方法,我可以只实现每条指令一次,因为我的操作数如何加载并不重要——另外,使用相同的操作数集执行相同的指令就像在真实机器上一样。代码的执行仅意味着通过选择正确的结构并相应地调用指令函数来加载正确的操作数集。
我知道还有其他方法——我特别喜欢动态重新编译。但是这个系统相当复杂,具有不同的片上组件和 I/O 映射寄存器,无论如何都会添加大量样板代码。
我非常感谢对我的方法的一些评论。也许您知道更好的方法?
谢谢!