Wiki

Clone wiki

LEGv8 / Home

LEGv8

This wiki explains how to run LEGv8 assembly code using the ARM DS-5 Community Edition and the Linaro toolchain and simulator. LEGv8 is a simple version of ARMv8 defined and used in the book Computer Organization and Design - The Hardware/Software Interface ARM Edition by David A. Patterson and John L. Hennessy.

Using ARM DS-5 and writing programs

You will use the free Community Edition of ARM's Integrated Development Environment called DS-5. Which can be downloaded from ARM https://developer.arm.com/tools-and-software/embedded/legacy-tools/ds-5-development-studio/editions/ds-5-community-edition or here. The installation does not need any further explanation.

You will also have to download a proper toolchain which includes an ARMv8 simulator. This toolchain can be downloaded from the Linaro website https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-elf/gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-elf.tar.xz. Download this file and extract it for example into C:\.

Installing Linaro aarch64-elf GCC as a toolchain in DS-5

You can add the toolchain in DS-5 as follows:

  • In DS-5, select Window → Preferences → DS-5 → Toolchains.
  • In the Toolchains dialog, click Add.
  • In the Select Toolchain Path dialog, enter the path to the toolchain binaries. In Windows this will normally be C:\gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-elf\bin. Then click Next.
  • In the Discovered Toolchain Information dialog, check the toolchain information is correct (as shown below), then click Finish.
  • The toolchain appears in the Toolchains dialog, click Apply, then click Restart Eclipse.

The Discovered Toolchain Information dialog.

Running a C program on the ARM-v8 simulator

Unzip the file Bare-metal_examples_Armv8.zip which under Windows can be found in C:\Program Files\DS-5 CE v5.29.1\examples\. For example into the directory C:\Bare-metal_examples_Armv8\.

You can run the calendar_Armv8-A_GCC example in DS-5 as follows:

  • In DS-5, select File → Import... → General → Existing Projects into WorkspaceWindow. Then click Next.
  • Select the directory C:\Bare-metal_examples_Armv8\.
  • Check the calendar_Armv8-A_GCC example and the Copy Projects into Workspace option, as shown below. Then click Finish.

The Import Projects dialog.

  • Right click on the project name calendar_Armv8-A_GCC in the Project Explorer and choose Properties.
  • Select C/C++ Build → Tool Chain Editor
  • Uncheck the Display compatible toolchains only option.
  • Select GCC 7.5.0 [aarch64-elf] as Current toolchain.
  • Click Yes and OK.
  • Click on the Build button The Build button. or right click on the project name in the Project Explorer and choose Build Project.
  • Right click on the project name in the Project Explorer and choose Debug As, Debug Configurations...
  • Open the option DS-5 Debugger, select calendar_Armv8-A_GCC-FM, as shown below and click Debug and Yes.

The Debug Configurations dialog.

  • You can now simulate the application. You can see the output and enter the input in the Target Console window, as shown here.

The Target Console window.

When you run the program it ends with a message that the source for svc.h can not be found. This is caused by the fact that the program returns with a return 0; statement but there is nothing (no operating system) to return to. We are running the program bare-metal, remember. If you don't like this, you can set a breakpoint on the return 0; statement in main or replace it with a while (1); instruction, so the program will not return. You have to stop the program yourself in this case.

Please note! This example deliberately contains an error so you can practice your debug skills, see the file readme.html which is included in the project directory.

Running a simple LEGv8 assembly program

You have installed ARM DS-5 and the Linaro toolchain and simulator now. Now you will use these to develop and test a very simple LEGv8 assembler program.

This project consists of a very simple assembler function and a C program which calls the assembler function.

The C program main.c contains the following code:

#!c
#include <stdio.h>

extern long long int test(long long int a, long long int b);

int main(void)
{
    long long int a = test(3, 5);
    printf("Result of test(3, 5) = %lld\n", a);
    return 0;
}

The main function calls the test function which is defined in the file test.S shown below. The first argument is passed in register X0 and the second argument is passed in register X1. The return value must be placed in register X0. The Procedure Call Standard for the ARM 64-bit Architecture (AArch64) can be found here: https://developer.arm.com/docs/ihi0055/latest/procedure-call-standard-for-the-arm-64-bit-architecture.

#!asm

    .globl test
test:
    add X0, X0, X1
    br  X30

This very simple assembly program will return the sum of the two arguments. You can test this program as follows:

  • Visit https://bitbucket.org/HarryBroeders/legv8/ and Fork this repository.
  • In DS-5, select File → Import... → Git → Projects from Git. Click Next.
  • Select Clone URI and click Next.
  • Fill in the URI to your own fork of the repository and click Next (twice).
  • Fill in the Destination Directory and click Next.
  • Select ass01 and click Finish.
  • Right click on the project name ass01 in the Project Explorer and choose Build Project.
  • Right click on the project name in the Project Explorer and choose Debug As, Debug Configurations...
  • Open the option DS-5 Debugger, select ass01 and click Debug and Yes.

When you run the program the output shown below should appear in the Target Console window.

The output of the ass01 project.

You are now ready to write your own LEGv8 assembler program. Happy LEGv8 coding!

Please note: you are not really using a LEGv8 assembler but you are actually using an ARMv8 assembler. So please review the remarks made by Patterson and Hennessy at the start of Paragraph 2.23, which are summarized below:

  • Immediate versions are not separate assembly language instructions in ARMv8. While LEGv8 has ADDI, SUBI, etc, ARMv8 does not. You simply use the non-immediate version and use an immediate operand. For example, to use the LEGv8 instruction: ADDI X0, X1, #4 you can just use ADD X0, X1, #4 (without the I).
  • Similarly, single and double-precision floating-point instructions do not have separate assembly language instructions in ARMv8. So instead of using FADDS or FADDD you can just use FADD and the assembler produces the right opcode depending on which register name you use: S for single and D for double.
  • In the ARMv8 instruction set, register X31 is XZR in most instructions but the stack pointer SP in others. In LEGv8 X28 is used as stack pointer. So you best use the symbolic names XZR and SP in your assembly code, to avoid confusion.
  • The immediate field for the logic instructions are not simple 12-bit constants in ARMv8. ARMv8 uses an algorithm to encode these immediate values. This means that some values are valid and others are not (e.g., 0 and 5).

There is another important difference between LEGv8 and ARMv8 to be considered, see Patterson and Hennessy, page 114:

  • ARMv8 software is required to keep the stack pointer aligned to quadword (16 byte) addresses. This means that the SP can only be in- or decreased by a multiple of 16!

Updated