I am in the middle of a problem that I can't seem to figure out. It involves testing the instruction set using c++ and inline assembly for the arm64. My current problems are with BL, BLR and the BR instructions. My current code looks as follows:
#include <stdio.h>
#define LDRARRAYLENGTH (4)
__asm __volatile
(
".global myFunction \n\t"
".p2align 4 \n\t"
".type myFunction,%function \n\t"
"myFunction: \n\t"
"mov x0, #10 \n\t"
"ret x30 \n\t"
);
/*
*
*/
bool BranchingModes(void)
{
bool BranchingModesFlag = false;
//local registers
int regw0 = 0x00;
int regw1 = 0x00;
int regw2 = 0x00;
int regw3 = 0x00;
/*
* Branch with Link branches to a PC-relative offset, setting
* the register X30 to PC+4. It provides a hint that this is a
* subroutine call.
*/
//Clear variables
regw0 = 0x00;
regw1 = 0x00;
regw2 = 0x00;
regw3 = 0x00;
__asm __volatile
(
"mov x0, #0 \n\t" /* setting up initial variable a */
"bl myFunction \n\t"
"mov %[reg1], x0 \n\t"
"nop \n\t"
:[reg0] "=r"(regw0), [reg1] "=r"(regw1)
:/* This is an empty input operand list */
);
/*
* The BL instruction calls a subroutine called myFunction within the subroutine
* a variable/register gets a value of 10. When the subroutine returns the
* the variable/register that got populated in the subroutine gets copied
* to another variable/register to acknowledge that the subroutine got called
* and returned using the BL instruction
*/
if((regw0 == 10) && (regw1 == 10))
{
BranchingModesFlag = true;
}
else
{
BranchingModesFlag = false;
}
return BranchingModesFlag;
}
int main()
{
unsigned int i0 = 0x00;
unsigned int counter = 0x00;
BranchingModes();
for(i0=0x00; i0<=10000; i0++)
{
counter = counter + 1;
}
return 0;
}
Issue is the code doesn't seem to make to the for loop after BranchingModes function. I know it's the asm section of the BranchingModes function which utilizes the BL instruction. I am not sure what I am doing wrong with that instruction. Am I returning correctly out of the "myFunction" using "ret x30"? I have attempted to use "BR x30" with no success. As BL updates "PC+4" and gets sorted to x30. Similar issue with the BLR instruction, I would appreciate any insight with my issues.
You need to tell the compiler about all registers you clobber, but you don't. The compiler doesn't see your changes to x0
and x30
, the latter of which is presumably the reason why your program never returns from BranchingModes
.
Haven't tested it, but this should work:
__asm __volatile
(
"mov x0, #0 \n\t" /* setting up initial variable a */
"bl myFunction \n\t"
"mov %[reg1], x0 \n\t"
"nop \n\t"
:[reg0] "=r"(regw0), [reg1] "=r"(regw1)
:/* This is an empty input operand list */
:"x0", "x30"
);
Note that this is for calling your specific function. For arbitrary ABI-compliant functions, you'll need to list everything the ABI specifies to be caller-saved as clobber. This will usually be x0
through x18
plus x30
, d8
through d15
, as well as cc
and memory
.