1*f5c631daSSadaf EbrahimiGetting Started with VIXL for AArch32 2*f5c631daSSadaf Ebrahimi===================================== 3*f5c631daSSadaf Ebrahimi 4*f5c631daSSadaf Ebrahimi 5*f5c631daSSadaf EbrahimiThis guide will show you how to use the VIXL framework for AArch32. We will see 6*f5c631daSSadaf Ebrahimihow to set up the VIXL assembler and generate some code. We will also go into 7*f5c631daSSadaf Ebrahimidetails on a few useful features provided by VIXL and see how to run the 8*f5c631daSSadaf Ebrahimigenerated code. 9*f5c631daSSadaf Ebrahimi 10*f5c631daSSadaf EbrahimiThe source code of the example developed in this guide can be found in the 11*f5c631daSSadaf Ebrahimi`examples/aarch32` directory (`examples/aarch32/getting-started.cc`). 12*f5c631daSSadaf Ebrahimi 13*f5c631daSSadaf Ebrahimi 14*f5c631daSSadaf EbrahimiCreating the macro assembler. 15*f5c631daSSadaf Ebrahimi----------------------------- 16*f5c631daSSadaf Ebrahimi 17*f5c631daSSadaf EbrahimiFirst of all you need to make sure that the header files for the assembler are 18*f5c631daSSadaf Ebrahimiincluded. You should have the following lines at the beginning of your source 19*f5c631daSSadaf Ebrahimifile: 20*f5c631daSSadaf Ebrahimi 21*f5c631daSSadaf Ebrahimi // You may use <cstdint> if using C++11 or later. 22*f5c631daSSadaf Ebrahimi extern "C" { 23*f5c631daSSadaf Ebrahimi #include <stdint.h> 24*f5c631daSSadaf Ebrahimi } 25*f5c631daSSadaf Ebrahimi 26*f5c631daSSadaf Ebrahimi #include <cstdio> 27*f5c631daSSadaf Ebrahimi #include <string> 28*f5c631daSSadaf Ebrahimi #include "aarch32/constants-aarch32.h" 29*f5c631daSSadaf Ebrahimi #include "aarch32/instructions-aarch32.h" 30*f5c631daSSadaf Ebrahimi #include "aarch32/macro-assembler-aarch32.h" 31*f5c631daSSadaf Ebrahimi 32*f5c631daSSadaf EbrahimiIn our case, those files are included by "examples.h". 33*f5c631daSSadaf Ebrahimi 34*f5c631daSSadaf EbrahimiAll VIXL components are declared in the `vixl::aarch32` namespace, so let's add 35*f5c631daSSadaf Ebrahimithis to the beginning of the file for convenience (once again, done in 36*f5c631daSSadaf Ebrahimi"examples.h"): 37*f5c631daSSadaf Ebrahimi 38*f5c631daSSadaf Ebrahimi using namespace vixl::aarch32; 39*f5c631daSSadaf Ebrahimi 40*f5c631daSSadaf EbrahimiNow we are ready to create and initialise the different components. 41*f5c631daSSadaf Ebrahimi 42*f5c631daSSadaf EbrahimiFirst of all we need to create a macro assembler object. 43*f5c631daSSadaf Ebrahimi 44*f5c631daSSadaf Ebrahimi MacroAssembler masm; 45*f5c631daSSadaf Ebrahimi 46*f5c631daSSadaf Ebrahimi 47*f5c631daSSadaf EbrahimiGenerating some code. 48*f5c631daSSadaf Ebrahimi--------------------- 49*f5c631daSSadaf Ebrahimi 50*f5c631daSSadaf EbrahimiWe are now ready to generate some code. The macro assembler provides methods 51*f5c631daSSadaf Ebrahimifor all the instructions that you can use. As it's a macro assembler, 52*f5c631daSSadaf Ebrahimithe instructions that you tell it to generate may not directly map to a single 53*f5c631daSSadaf Ebrahimihardware instruction. Instead, it can produce a short sequence of instructions 54*f5c631daSSadaf Ebrahimithat has the same effect. 55*f5c631daSSadaf Ebrahimi 56*f5c631daSSadaf EbrahimiBefore looking at how to generate some code, let's introduce a simple but handy 57*f5c631daSSadaf Ebrahimimacro: 58*f5c631daSSadaf Ebrahimi 59*f5c631daSSadaf Ebrahimi #define __ masm-> 60*f5c631daSSadaf Ebrahimi 61*f5c631daSSadaf EbrahimiIt allows us to write `__ Mov(r0, 42);` instead of `masm->Mov(r0, 42);` to 62*f5c631daSSadaf Ebrahimigenerate code. 63*f5c631daSSadaf Ebrahimi 64*f5c631daSSadaf EbrahimiNow we are going to write a C++ function to generate our first assembly 65*f5c631daSSadaf Ebrahimicode fragment. 66*f5c631daSSadaf Ebrahimi 67*f5c631daSSadaf Ebrahimi void GenerateDemo(MacroAssembler *masm) { 68*f5c631daSSadaf Ebrahimi __ Ldr(r1, 0x12345678); 69*f5c631daSSadaf Ebrahimi __ And(r0, r0, r1); 70*f5c631daSSadaf Ebrahimi __ Bx(lr); 71*f5c631daSSadaf Ebrahimi } 72*f5c631daSSadaf Ebrahimi 73*f5c631daSSadaf EbrahimiThe generated code corresponds to a function with the following C prototype: 74*f5c631daSSadaf Ebrahimi 75*f5c631daSSadaf Ebrahimi uint32_t demo(uint32_t x); 76*f5c631daSSadaf Ebrahimi 77*f5c631daSSadaf EbrahimiThis function doesn't perform any useful operation. It loads the value 78*f5c631daSSadaf Ebrahimi0x12345678 into r1 and performs a bitwise `and` operation with 79*f5c631daSSadaf Ebrahimithe function's argument (stored in r0). The result of this `and` operation 80*f5c631daSSadaf Ebrahimiis returned by the function in r0. 81*f5c631daSSadaf Ebrahimi 82*f5c631daSSadaf EbrahimiNow in our program main function, we only need to create a label to represent 83*f5c631daSSadaf Ebrahimithe entry point of the assembly function and to call `GenerateDemo` to 84*f5c631daSSadaf Ebrahimigenerate the code. 85*f5c631daSSadaf Ebrahimi 86*f5c631daSSadaf Ebrahimi Label demo; 87*f5c631daSSadaf Ebrahimi masm.Bind(&demo); 88*f5c631daSSadaf Ebrahimi GenerateDemo(&masm); 89*f5c631daSSadaf Ebrahimi masm.Finalize(); 90*f5c631daSSadaf Ebrahimi 91*f5c631daSSadaf EbrahimiNow we are going to learn a bit more on a couple of interesting VIXL features 92*f5c631daSSadaf Ebrahimiwhich are used in this example. 93*f5c631daSSadaf Ebrahimi 94*f5c631daSSadaf Ebrahimi### Label 95*f5c631daSSadaf Ebrahimi 96*f5c631daSSadaf EbrahimiVIXL's assembler provides a mechanism to represent labels with `Label` objects. 97*f5c631daSSadaf EbrahimiThey are easy to use: simply create the C++ object and bind it to a location in 98*f5c631daSSadaf Ebrahimithe generated instruction stream. 99*f5c631daSSadaf Ebrahimi 100*f5c631daSSadaf EbrahimiCreating a label is easy, since you only need to define the variable and bind it 101*f5c631daSSadaf Ebrahimito a location using the macro assembler. 102*f5c631daSSadaf Ebrahimi 103*f5c631daSSadaf Ebrahimi Label my_label; // Create the label object. 104*f5c631daSSadaf Ebrahimi __ Bind(&my_label); // Bind it to the current location. 105*f5c631daSSadaf Ebrahimi 106*f5c631daSSadaf EbrahimiThe target of a branch using a label will be the address to which it has been 107*f5c631daSSadaf Ebrahimibound. For example, let's consider the following code fragment: 108*f5c631daSSadaf Ebrahimi 109*f5c631daSSadaf Ebrahimi Label foo; 110*f5c631daSSadaf Ebrahimi 111*f5c631daSSadaf Ebrahimi __ B(&foo); // Branch to foo. 112*f5c631daSSadaf Ebrahimi __ Mov(r0, 42); 113*f5c631daSSadaf Ebrahimi __ Bind(&foo); // Actual address of foo is here. 114*f5c631daSSadaf Ebrahimi __ Mov(r1, 0xc001); 115*f5c631daSSadaf Ebrahimi 116*f5c631daSSadaf EbrahimiIf we run this code fragment the `Mov(r0, 42)` will never be executed since 117*f5c631daSSadaf Ebrahimithe first thing this code does is to jump to `foo`, which correspond to the 118*f5c631daSSadaf Ebrahimi`Mov(r1, 0xc001)` instruction. 119*f5c631daSSadaf Ebrahimi 120*f5c631daSSadaf EbrahimiWhen working with labels you need to know that they are only to be used for 121*f5c631daSSadaf Ebrahimilocal branches, and should be passed around with care. The major reason is 122*f5c631daSSadaf Ebrahimithat they cannot safely be passed or returned by value because this can trigger 123*f5c631daSSadaf Ebrahimimultiple constructor and destructor calls. The destructor has assertions 124*f5c631daSSadaf Ebrahimito check that we don't try to branch to a label that hasn't been bound. 125*f5c631daSSadaf Ebrahimi 126*f5c631daSSadaf Ebrahimi 127*f5c631daSSadaf Ebrahimi### Literal Pool 128*f5c631daSSadaf Ebrahimi 129*f5c631daSSadaf EbrahimiOn AArch32 instructions are 16 or 32 bits long, thus immediate values encoded in 130*f5c631daSSadaf Ebrahimithe instructions have limited size. If you want to load a constant bigger than 131*f5c631daSSadaf Ebrahimithis limit you have two possibilities: 132*f5c631daSSadaf Ebrahimi 133*f5c631daSSadaf Ebrahimi1. Use multiple instructions to load the constant in multiple steps. This 134*f5c631daSSadaf Ebrahimi solution is already handled in VIXL. For instance you can write: 135*f5c631daSSadaf Ebrahimi 136*f5c631daSSadaf Ebrahimi `__ Mov(r0, 0x12345678);` 137*f5c631daSSadaf Ebrahimi 138*f5c631daSSadaf Ebrahimi The previous instruction would not be legal since the immediate value is too 139*f5c631daSSadaf Ebrahimi big. However, VIXL's macro assembler will automatically rewrite this line into 140*f5c631daSSadaf Ebrahimi multiple instructions efficiently generate the value, ultimately setting 'r0' 141*f5c631daSSadaf Ebrahimi with the correct value. 142*f5c631daSSadaf Ebrahimi 143*f5c631daSSadaf Ebrahimi 144*f5c631daSSadaf Ebrahimi2. Store the constant in memory and load this value from the memory. The value 145*f5c631daSSadaf Ebrahimi needs to be written near the code that will load it since we use a PC-relative 146*f5c631daSSadaf Ebrahimi offset to indicate the address of this value. This solution has the advantage 147*f5c631daSSadaf Ebrahimi of making the value easily modifiable at run-time; since it does not reside 148*f5c631daSSadaf Ebrahimi in the instruction stream, it doesn't require cache maintenance when updated. 149*f5c631daSSadaf Ebrahimi 150*f5c631daSSadaf Ebrahimi VIXL also provides a way to do this: 151*f5c631daSSadaf Ebrahimi 152*f5c631daSSadaf Ebrahimi `__ Ldr(r0, 0x12345678);` 153*f5c631daSSadaf Ebrahimi 154*f5c631daSSadaf Ebrahimi The assembler will store the immediate value in a "literal pool", a set of 155*f5c631daSSadaf Ebrahimi constants embedded in the code. VIXL will emit the literal pool when needed. 156*f5c631daSSadaf Ebrahimi 157*f5c631daSSadaf Ebrahimi The literal pool is emitted regularly, such that they are within range of the 158*f5c631daSSadaf Ebrahimi instructions that refer to it. However, you can force the literal pool to be 159*f5c631daSSadaf Ebrahimi emitted using `masm.EmitLiteralPool()`. It generates a branch to skip the 160*f5c631daSSadaf Ebrahimi pool. 161*f5c631daSSadaf Ebrahimi 162*f5c631daSSadaf Ebrahimi 163*f5c631daSSadaf EbrahimiRunning the code. 164*f5c631daSSadaf Ebrahimi----------------- 165*f5c631daSSadaf Ebrahimi 166*f5c631daSSadaf EbrahimiWe first need to run a few operations to get executable code. The 167*f5c631daSSadaf Ebrahimi`ExecutableMemory` helper takes care of it: 168*f5c631daSSadaf Ebrahimi 169*f5c631daSSadaf Ebrahimi byte* code = masm.GetBuffer().GetBuffer(); 170*f5c631daSSadaf Ebrahimi uint32_t code_size = masm.GetBuffer().GetSizeInBytes(); 171*f5c631daSSadaf Ebrahimi ExecutableMemory memory(code, code_size); 172*f5c631daSSadaf Ebrahimi 173*f5c631daSSadaf EbrahimiThen we compute a pointer to the function we just generated and copy: 174*f5c631daSSadaf Ebrahimi 175*f5c631daSSadaf Ebrahimi uint32_t (*demo_function)(uint32_t) = 176*f5c631daSSadaf Ebrahimi memory.GetOffsetAddress<uint32_t (*)(uint32_t)>(0); 177*f5c631daSSadaf Ebrahimi 178*f5c631daSSadaf EbrahimiNow, we can call this function pointer exactly as if it were a pointer on a C 179*f5c631daSSadaf Ebrahimifunction: 180*f5c631daSSadaf Ebrahimi 181*f5c631daSSadaf Ebrahimi uint32_t input_value = 0x89abcdef; 182*f5c631daSSadaf Ebrahimi uint32_t output_value = (*demo_function)(input_value); 183*f5c631daSSadaf Ebrahimi 184*f5c631daSSadaf EbrahimiA little trace: 185*f5c631daSSadaf Ebrahimi 186*f5c631daSSadaf Ebrahimi printf("native: abs(%08x) = %08x\n", input_value, output_value); 187*f5c631daSSadaf Ebrahimi 188*f5c631daSSadaf Ebrahimi 189*f5c631daSSadaf EbrahimiThe example shown in this tutorial is very simple, because the goal was to 190*f5c631daSSadaf Ebrahimidemonstrate the basics of the VIXL framework. There are more complex code 191*f5c631daSSadaf Ebrahimiexamples in the VIXL `examples/aarch32` directory showing more features of both the 192*f5c631daSSadaf Ebrahimimacro assembler and the AArch32 architecture. 193*f5c631daSSadaf Ebrahimi 194*f5c631daSSadaf EbrahimiDisassembling the generated code. 195*f5c631daSSadaf Ebrahimi--------------------------------- 196*f5c631daSSadaf Ebrahimi 197*f5c631daSSadaf EbrahimiOnce you have generated something with the macro-assembler, you may want to 198*f5c631daSSadaf Ebrahimidisassemble it. 199*f5c631daSSadaf Ebrahimi 200*f5c631daSSadaf EbrahimiFirst, you must include iostream. 201*f5c631daSSadaf Ebrahimi 202*f5c631daSSadaf Ebrahimi #include <iostream> 203*f5c631daSSadaf Ebrahimi 204*f5c631daSSadaf EbrahimiAnd the disassembler header file: 205*f5c631daSSadaf Ebrahimi 206*f5c631daSSadaf Ebrahimi #include "aarch32/disasm-aarch32.h" 207*f5c631daSSadaf Ebrahimi 208*f5c631daSSadaf EbrahimiThen you have to define the pc used to disassemble (the one which is used to 209*f5c631daSSadaf Ebrahimidisplay the addresses not the location of the instructions): 210*f5c631daSSadaf Ebrahimi 211*f5c631daSSadaf Ebrahimi uint32_t display_pc = 0x1000; 212*f5c631daSSadaf Ebrahimi 213*f5c631daSSadaf EbrahimiOr, if you running on a 32 bit host, you can use the real address: 214*f5c631daSSadaf Ebrahimi 215*f5c631daSSadaf Ebrahimi uint32_t display_pc = static_cast<uintptr_t>(masm.GetBuffer().GetBuffer()); 216*f5c631daSSadaf Ebrahimi 217*f5c631daSSadaf EbrahimiThen you can disassemble the macro assembler's buffer: 218*f5c631daSSadaf Ebrahimi 219*f5c631daSSadaf Ebrahimi PrintDisassembler disasm(std::cout, display_pc); 220*f5c631daSSadaf Ebrahimi disasm.DisassembleA32Buffer( 221*f5c631daSSadaf Ebrahimi masm.GetBuffer().GetOffsetAddress<uint32_t*>(0), masm.GetCursorOffset()); 222*f5c631daSSadaf Ebrahimi 223*f5c631daSSadaf EbrahimiIf you generated T32 code instead of A32 code, you must use 224*f5c631daSSadaf EbrahimiDisassembleT32Buffer. Warning: if your buffer contains some data or contains 225*f5c631daSSadaf Ebrahimimixed T32 and A32 code, the result won't be accurate (everything will be 226*f5c631daSSadaf Ebrahimidisassembled as T32 or A32 code). 227*f5c631daSSadaf Ebrahimi 228*f5c631daSSadaf EbrahimiExample of disassembly: 229*f5c631daSSadaf Ebrahimi 230*f5c631daSSadaf Ebrahimi 0x00001000 e30f0fff mov r0, #65535 231*f5c631daSSadaf Ebrahimi 0x00001004 e34f0fff movt r0, #65535 232*f5c631daSSadaf Ebrahimi 0x00001008 e3041567 mov r1, #17767 233*f5c631daSSadaf Ebrahimi 0x0000100c e3401123 movt r1, #291 234*f5c631daSSadaf Ebrahimi 0x00001010 e3a02000 mov r2, #0 235*f5c631daSSadaf Ebrahimi 0x00001014 e7c2001f bfc r0, #0, #3 236*f5c631daSSadaf Ebrahimi 0x00001018 e7d4081f bfc r0, #16, #5 237*f5c631daSSadaf Ebrahimi 0x0000101c e7c72011 bfi r2, r1, #0, #8 238*f5c631daSSadaf Ebrahimi 0x00001020 e7df2811 bfi r2, r1, #16, #16 239*f5c631daSSadaf Ebrahimi 0x00001024 e1000070 hlt 0 240