Arm Community
Arm Community
  • Site
  • User
  • Site
  • Search
  • User
  • Groups
    • Arm Research
    • DesignStart
    • Education Hub
    • Graphics and Gaming
    • High Performance Computing
    • Innovation
    • Multimedia
    • Open Source Software and Platforms
    • Physical
    • Processors
    • Security
    • System
    • Software Tools
    • TrustZone for Armv8-M
    • 中文社区
  • Blog
    • Artificial Intelligence
    • Automotive
    • Healthcare
    • HPC
    • Infrastructure
    • Innovation
    • Internet of Things
    • Machine Learning
    • Mobile
    • Smart Homes
    • Wearables
  • Forums
    • All developer forums
    • IP Product forums
    • Tool & Software forums
    • Pelion IoT Platform
  • Activity
  • Support
    • Open a support case
    • Documentation
    • Downloads
    • Training
    • Arm Approved program
    • Arm Design Reviews
  • More
  • Cancel
中文社区
中文社区
中文社区博客 VIXL 入门
  • Blogs
  • Forum
  • 视频和文件
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • Jump...
  • Cancel
  • New
中文社区 requires membership for participation - click to join
More blogs in 中文社区
  • ARM中国大学计划博客

  • Arm新闻

  • 中文mbed博客

  • 中文社区博客

  • 恩智浦汽车电子MCU讨论区博客

 

Tags
  • Processor
  • chinese
  • Armv8
  • 中文
  • 处理器
Actions
  • RSS
  • More
  • Cancel
Related blog posts
Related forum threads

VIXL 入门

Song Bin 宋斌
Song Bin 宋斌
October 24, 2013

原文: Getting Started with VIXL

投稿人:baptisteasfa,2013 年 7 月 16 日

在上一篇博客文章中,我们介绍了 VIXL - 一个 ARMv8 动态代码生成工具包。本博客文章将告诉您如何使用 VIXL 框架。我们将会看到如何设置 VIXL 汇编程序并生成某些代码。我们还将详细阐述由 VIXL 提供的某些有用功能,并了解如何在 VIXL 模拟器中运行生成的代码。

本指南中开发的示例的源代码可以在示例目录中找到 (examples/getting-started.cc)。

创建宏汇编程序和模拟器

首先,您需要确保包括汇编程序和模拟器的标头文件。您的源文件的开头应该具有以下几行:

#include "a64/simulator-a64.h"

#include "a64/macro-assembler-a64.h"

VIXL 的汇编程序将在运行时生成一些代码,该代码需要存储在缓冲区中。它必须足够大,以包含将要生成的所有指令和数据。在本指南中,我们将使用默认值 4096,但您可以随意将其更改为适合您需求的值。

#define BUF_SIZE (4096)

所有 VIXL 组件在 vixl 命名空间内进行声明,因此,为方便起见,让我们将其加入到该文件的开头:

using namespace vixl;

现在,我们已准备好创建并初始化不同的组件。

首先,我们需要分配代码缓冲区并创建使用该缓冲区的宏汇编程序对象。

byte assm_buf[BUF_SIZE];

MacroAssembler masm(assm_buf, BUF_SIZE);

我们还需要设置模拟器。该模拟器使用解码器对象来从代码缓冲区读取指令并对其进行解码。我们需要创建解码器,并将我们的模拟器绑定到该解码器。

Decoder decoder;

Simulator simulator(&decoder);

生成某些代码

现在,我们可以生成某些代码。宏汇编程序为您可以使用的所有指令提供方法。由于它是宏汇编程序,因此您让它生成的指令可能不会直接映射到单个硬件指令。相反,它可以产生具有相同效果的短指令序列。

例如,硬件添加指令只能采用可以选择移位 12 的 12 位立即数,但宏汇编程序可生成处理任何 64 位立即数的一个或多个指令。例如,Add(x0, x0, -1) 将变成 Sub(x0, x0, 1)。

在了解如何生成某些代码之前,让我们介绍一个简单而方便的宏:

#define __ masm->

它使我们能够写入 __ Mov(x0, 42) 而非 masm->Mov(x0, 42); 来生成代码。

现在,我们将写入 C++ 函数来生成我们的第一个汇编代码片段。

void GenerateDemoFunction(MacroAssembler *masm) {

__ Ldr(x1, 0x1122334455667788);

__ And(x0, x0, x1);

__ Ret();

}

生成的代码对应于具有以下 C 原型的函数:

uint64_t demo_function(uint64_t x);

该函数不执行任何有用操作。其将值 0x1122334455667788 加载到 x1 中,并使用该函数的参数(存储在 x0 中)执行按位与运算。该与运算的结果由 x0 中的函数返回。

现在,在我们的程序主要功能中,我们只需创建一个标签来表示汇编函数的入口点,并调用 GenerateDemoFunction 来生成代码。


Label demo_function;

masm.Bind(&demo_function);

GenerateDemoFunction(&masm);

masm.Finalize();

现在,我们将了解有关该示例中使用的几个有趣 VIXL 功能的更多信息。

标签

VIXL 的汇编程序提供了表示具有标签对象的标签的机制。它们简单易用:只需创建 C++ 对象并将其绑定到生成的指令流中的某个位置。

创建标签非常简单,因为您只需定义该变量并将其绑定到使用该宏汇编程序的某个位置。

Label my_label; // Create the label object.

__ Bind(&my_label); // Bind to the current location.

使用标签的分支的目标将会是其已经绑定的地址。例如,让我们考虑以下代码片段:

Label foo;

__ B(&foo); // Branch to foo.

__ Mov(x0, 42);

__ Bind(&foo); // Actual address of foo is here.

__ Mov(x1, 0xc001);

如果我们运行该代码片段,则 Mov(x0, 42) 将永远不会执行,因为该代码首先要跳转到 foo,其对应于 Mov(x1, 0xc001) 指令。

使用标签时,您需要知道它们仅用于本地分支,且应小心传送。这有两个原因:

  1. 1. 它们无法由值进行安全传送或返回,因为这可能触发多个构造函数和析构函数调用。析构函数具有断言,以确认我们不会尝试跳转到尚未绑定的标签。
  1. 2. B 指令不会跳转到分支范围外的标签。B 指令的范围在 2^28 个字节,但其他变量(如有条件或 CBZ 类分支)具有较小的范围。将它们限定在本地范围并不意味着我们不会达到这些限制,但它使标签的寿命短很多并简化了这类问题的调试。

文字池

ARMv8 指令长 32 位,因此在指令内进行编码的立即值的大小有限。如果您想加载大于该限制的常数,则您拥有两种可能方法:

  1. 1. 使用多个指令在多个步骤中加载该常数。该解决方案已经在 VIXL 中进行运用。例如,您可以这样写:

__ Mov(x0, 0x1122334455667788);

前面的指令不合法,因为立即值太大。然而,VIXL 的宏汇编程序会自动将这一行改写成多个指令,以高效生成该值。

  1. 2. 将该常量存储在内存中,并从该内存加载该值。该值需要在将对其进行加载的代码旁进行编写,因为我们使用 PC 相对偏移来指明该值的地址。该解决方案的优势是使该值可以在运行时轻松修改,因为它不驻留在指令流中,它不需要在更新时进行缓存维护。

VIXL 还提供了实现这一目标的方法:

__ Ldr(x0, 0x1122334455667788);

汇编程序将在“文字池”中存储立即值,这是一组嵌入在该代码中的常数。VIXL 将在控制流中的自然中断后发出文字池,如无条件分支或返回指令。

文字池定期发出,以便它们在引用它们的指令范围内。但是,您可以使用 masm.EmitLiteralPool() 强制发出文字池

在模拟器中运行代码

现在,我们将查看如何使用模拟器运行我们之前生成的代码。

使用模拟器将某个值指定到寄存器。我们前面的代码示例将寄存器 x0 用作输入,因此,让我们设置该寄存器的值。


simulator.set_xreg(0, 0x8899aabbccddeeff);

现在,我们可以跳转到条目标签来执行该代码:


simulator.RunFrom(entry.target());

完成执行并返回模拟器时,您可以在执行后检查寄存器的值。例如:


printf("x0 = %" PRIx64 "\n", simulator.xreg(0));

本教程中的示例非常简单,因为我们的目标是要展示 VIXL 框架的基础。VIXL 示例 目录中有更复杂的代码示例,显示了宏汇编程序和 ARMv8 架构两者的其他功能。

ARM 软件工程师 Baptiste Afsa 几乎对每一个有关嵌入式系统技术的主题以及与硬件密切相关的任何种类的代码都感兴趣。他加入 ARM 从事 JIT 编译器方面的工作,非常着迷于动态代码生成问题,试图生成针对 ARM 平台优化的代码。

Anonymous
中文社区博客
  • 中文社区博客: Streamline中基于统计的性能分析功能介绍

    章政
    章政
    原文参考 ARM性能分析器(Streamline) 7.0版开始支持基于SPE(统计性能分析扩展)的性能分析。SPE是Armv8.2-A架构中的一个可选扩展特性,它可以以很低的代价对处理器的流水线进行采样。Streamline可以从Arm Development Studio和Arm Mobile Stuido获取。 为什么需要SPE? Streamline前序版本只能通过硬件计数器和软中断中采样PC信息获取CPU的信息…
    • January 28, 2020
  • 中文社区博客: 让数值算法在Arm edge端跑的更快

    章政
    章政
    CMSIS DSP 库作为高度优化的嵌入式系统数字信号计算库一直以来深受广大开发者所喜爱,随着人工智能(Artificial Intelligence )逐步向Edge端扩展,Edge端的数字计算负载也越来越大,为了缓解计算的压力,各种框架也在Edge端采用CMSIS DSP库进行优化加速。科学计算环境和嵌入式开发环境有很大的区别,比如科学计算往往采用Python,SCIPy,Matlab,而这些环境一般是无法在低功耗嵌入式环境…
    • November 13, 2019
  • 中文社区博客: 使用Arm Mobile Studio加速Mali GPU分析

    章政
    章政
    Streamline性能分析器是一个基于采样的分析器,可以提供有关设备中存在的Arm CPU和Mali GPU的详细性能信息。最新版本的Streamline包含一组预定义模板,可用于方便选择要使用的数据源,并控制它们的显示方式。最新版本的Streamline包含在  Arm Mobile Studio  2019.0和  Arm Development Studio  2019.0中,它包含对Mali
    • May 31, 2019