简体   繁体   中英

Is there a LOAD or STORE in Legv8 that uses another register instead of a immediate offset?

Is there a load or store instruction in Legv8 that does not use a immediate offset? i do not have a value for i in the bottom question and i cant offset for data[i] when i use LDUR or STUR. I used STR and LDR from ARMv8. Is there another way i could have answered this question?

Convert the following C program into LEGv8 assembly program. Assume variables k, x, y and i are associated with registers X19, X20, X21, and X22 respectively. The base address of array data[] is in register X25. Each element of array data[] occupies 8 bytes.

if ( x > y )  
     k = x – y;  
else  
    k = y – x;  
while (data[i] < k) {  
    data[i] = data[i] + k;  
    i = i + 1;  

This is what i wrote.

IF:  
    SUBS X23, X20, X21 // CHECK IF X> Y  
B.LT ELSE // IF LESS THAN, BRANCH TO ELSE  
    SUB X19, X20, X21 // STORE K = X-Y  
B.LOOP  
ELSE:   
    SUB X19, X21, X20 // STORE K= Y-X;  
LOOP:  
    LDR X24, [X25, X22] // load into X24, base address from X24 with offset from X22  
    SUBS X18, X24, X19 // CHECK IF data[i] < k  
    B.GT EXIT  
    ADD X24, X24, X19 // data[i] += k  
STR X24, [X25, X22] // store into X25 with offset from X22, the value from X24  
    ADDI X22, X22, #1 // I += 1  
    B.LOOP  
EXIT:  

str / ldr are the normal instructions that can use a variety of addressing modes.

ldur / stur are only useful with register + constant offset when the immediate constant isn't a multiple of 4 or 8.

The normal form of ldr with that addressing mode encodes it as a scaled value so it can use a wider range of offsets. The U means "unscaled". (But that's an encoding detail: the asm source code still always has a byte offset like ldr w0, [x0, 4] to load the next int after the one pointed to by x0 . Godbolt ). But as I said, ldr / str can use any addressing mode.

You're correct that ldur is useless for data[i] with runtime-variable i .

Is there another way i could have answered this question?

Yes, of course there are many ways to arrange your loop. eg use a pointer increment instead of a 2-register addressing mode, calculating data+i outside the loop.

Or incrementing your counter by 8 as a byte offset instead of an array index you need to scale every time you use it. (I think you forgot this unless LEGv8 is different from AArch64).

Or optimize away i and just calculate an end-pointer to compare against.

Or even vectorizing with AdvSIMD (AArch64 version of NEON) SIMD instructions to do 2 adds at once.

Also you could structure the loop with the conditional branch at the bottom which is always good (fewer instructions inside the loop). Even if it means you need a compare/branch to maybe skip the loop if it should run zero times.

But all these ways just use ldr / str , not ldur / stur . You have no need for an offset as part of the addressing mode, just 2 registers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM