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.
CodePudding user response:
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
.