Assembly 是否有任何方法可以让GCC生成额外的NOP指令来将指令执行与特定的块大小对齐?

Assembly 是否有任何方法可以让GCC生成额外的NOP指令来将指令执行与特定的块大小对齐?,assembly,gcc,cpu,cpu-architecture,Assembly,Gcc,Cpu,Cpu Architecture,上下文:您好,我最近正在构建一个定制CPU,它有16、32和48位指令长度。CPU获取64位的数据块,在两个数据块之间捕获到一条指令之前,这一切都是正常的;这使得我的CPU获取两个数据块,这会影响其性能 问题: 我想知道是否有任何方法可以通过向编译过程中添加传统参数,使gcc将指令与NOP对齐到64位块。或者,让GCC将指令与NOP对齐的正确方法是什么 这就是一条指令如何夹在两个块之间 +---------------+ |Unaligned ins

上下文:您好,我最近正在构建一个定制CPU,它有16、32和48位指令长度。CPU获取64位的数据块,在两个数据块之间捕获到一条指令之前,这一切都是正常的;这使得我的CPU获取两个数据块,这会影响其性能

问题: 我想知道是否有任何方法可以通过向编译过程中添加传统参数,使gcc将指令与NOP对齐到64位块。或者,让GCC将指令与NOP对齐的正确方法是什么

这就是一条指令如何夹在两个块之间

          +---------------+ 
          |Unaligned ins  |
          +---------------+
 +---------------+ +---------------+
 |     64Bits    | |     64Bits    |
 +---------------+ +---------------+

这是我希望GCC实现的16位执行和48位执行的理想方式。每个空块表示一条16位指令,但最后一个大空块表示一条48位指令;这将使后面的指令不对齐。如果后面跟着另一条48位或32位指令,它将被夹在两个数据块之间。我希望GCC生成NOP指令以防止未对齐的指令执行。如最后一个空块所示


+---+---+---+---+ +-----------+---+
|   |   |   |   | |           |   |
+---+---+---+---+ +-----------+---+
+---------------+ +---------------+
|     64Bits    | |     64Bits    |
+---------------+ +---------------+

我已经尝试过的:
我尝试向GCC添加参数,例如
-falign loops=###-falign functions=###-falign jumps=##
,但它们没有达到我想要的效果。

你能让GCC在每48位指令之前打印
.p2align 3,4
,在每32位指令之前打印
.p2align 3,2
吗?我不知道在哪里修改GCC的源代码来实现这一点,但它避免了需要实际跟踪指令大小和当前对齐方式

这将填充到2^3字节(64位)的边界,但仅当它最多需要4字节(或2字节)的填充时

有了这些限制,如果块边界前面有6个字节,它就不会在6字节指令之前填充(因此可以适应)。对于4字节指令也是如此

更为优化的是指令调度,它知道边界,并尝试重新排序以打包成块,而不留下很大的空白来填充NOP


如果您的GAS本身不知道如何生成2或4字节的NOP,那么糟糕的简单方法是使用
.p2alignw 3,0x1234,4
告诉它填充
0x1234
的2字节序列。(其中,
0x1234
是用于编码2字节NOP指令的占位符。)


稍微好一点的方法是教GAS发出2字节或4字节的NOP指令,而不是2个2字节的NOP指令,但这只是一个不需要修改GAS就可以做的肮脏的黑客行为。

你能让GCC在每48位指令之前打印
.p2align 3,4
,在每32位指令之前打印
.p2align 3,2
?我不知道在哪里修改GCC的源代码来实现这一点,但它避免了需要实际跟踪指令大小和当前对齐方式

这将填充到2^3字节(64位)的边界,但仅当它最多需要4字节(或2字节)的填充时

有了这些限制,如果块边界前面有6个字节,它就不会在6字节指令之前填充(因此可以适应)。对于4字节指令也是如此

更为优化的是指令调度,它知道边界,并尝试重新排序以打包成块,而不留下很大的空白来填充NOP


如果您的GAS本身不知道如何生成2或4字节的NOP,那么糟糕的简单方法是使用
.p2alignw 3,0x1234,4
告诉它填充
0x1234
的2字节序列。(其中,
0x1234
是用于编码2字节NOP指令的占位符。)


稍微不那么糟糕的做法是教GAS发出2字节或4字节的NOP指令,而不是2个2字节的NOP指令,但这只是一个不需要修改GAS就可以做到的肮脏的黑客行为。

这不是对您问题的直接回答,但在googlenacl(原生客户端)中也做了类似的事情,以使x86机器代码的分析更容易。也许读一下他们为了达到这个效果而对工具链所做的修改?@fuz-Oh,谢谢。你能给我一个链接吗?很遗憾我没有链接。我必须以你需要的方式研究这个问题。我怀疑GCC中已经有任何东西可以为你做到这一点。您应该能够通过使用RTL INSN的指令大小注释RTL INSN,然后实现您自己的自定义过程来实现这一点。您也可以在汇编程序中实现它。您所做的与安腾(IA-64)体系结构的指令包类似,因此查看该实现可能会有所帮助,但除此之外,它与GCC一样,只是汇编程序已经知道指令大小。这不是对您问题的直接回答,但是在Googlenacl(原生客户端)中也做了类似的事情,以使x86机器代码的分析更容易。也许读一下他们为了达到这个效果而对工具链所做的修改?@fuz-Oh,谢谢。你能给我一个链接吗?很遗憾我没有链接。我必须以你需要的方式研究这个问题。我怀疑GCC中已经有任何东西可以为你做到这一点。您应该能够通过使用RTL INSN的指令大小注释RTL INSN,然后实现您自己的自定义过程来实现这一点。您也可以在汇编程序中实现它。您所做的与安腾(IA-64)体系结构的指令包类似,因此查看该实现可能会有所帮助,但除此之外,它与GCC一样,只是汇编程序已经知道指令大小。它可以工作。我删除了我以前的评论,我错了。现在的问题是,填充是作为一条指令执行的,
objdump-d
显示“bad”,就像填充是一条错误的指令一样。@Bybit360:因此,ISA的GAS不知道如何使用NOPs填充,只使用
00
字节或其他什么?你可能会