ARM instruction misc

ARM instruction misc

daifset/daifclr

msr daifset, #0xf  //对DAIF寄存器的值的bit0-3位置1

msr daifset, #2 //对DAIF的bit1置1,即对DAIF的I bit置1(disable irq)

DAIF bit,F bit是bit6,I是bit7,A是bit8,D是bit9,所以上述msr daifset, #2实际上是将bit7设置为1

从daif读值时,同样是一样的,即F bit是bit6,I是bit7,A是bit8,D是bit9,假如DAIF只有I bit置位,则mrs x2, daif后x2的值是0x80

tbnz

指令

使用范例

功能描述

CBZ

CBZ X1, label

如果x1 == 0,则跳转到label

CBNZ

CBNZ X1, label

如果x1 != 0,则跳转到label

TBZ

TBZ X1, #3, label

如果x1寄存器的第三位等于0,则跳转到label

TBNZ

TBNZ X1, #3, label

如果x1寄存器的第三位不等于0,则跳转到label

from: https://support.huaweicloud.com/pinsrcase-kunpengprocs/kunpengprocessor_18_0040.html

.align 7

经常会看到arm-linux汇编中有如下的指令: .align n 它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或 2^n ,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多。

PRFM

Prefetch from Memory (PRFM) provides a hint to the memory system that data from a particular address will be used by the program soon. The effect of this hint typically results in data or instructions being loaded into one of the caches.
The instruction syntax is:
PRFM <prfop>, <addr> | label

Where prfop is a concatenation of the following options:
Type    PLD or PST (prefetch for load or store).
Target   L1, L2, or L3 (which cache to target).
Policy    KEEP or STRM (keep in cache, or streaming data).


For example, PLDL1KEEP.

AArch64: PRFM PLDL1KEEP, [Xm, #imm] ; This indicates a Prefetch for a load from Xm +
offset into the L1 cache as a temporal prefetch, which means that the data might be used
more than once.

LDAXR

LDAXRB是byte;LDAXRH是half-word;LDAXR是register:

A register instruction operates on a doubleword if accessing an X register, or on a word if accessing a W register

 

stxr ws, <wt/xt>, [Xn]

arm64指令,STXR指令和普通的STR指令,不同的是,该指令有返回值,表示store exclusive是否成功。如果成功,ws为0,不成功,ws为1。

ldp x29, x30, [sp],#16

ldp x29, x30, [sp],#16:从sp的位置提取数据到x29、x30,x29在低地址、x30在高地址,执行完以后,sp加上0x10,隐藏着出栈的操作指令

ARM NZCV标志位

之前以为CMP指令执行后,不管是进位还是借位,C标志位都会置位,其实这是错的,所以我整理了一下四个ARM标志位的置位和清零的规则:

N 当用两个补码表示的带符号数进行运算时,N=1表示运算的结果为负数;N=0表示运算的结果为正数或零.
Z Z=1表示运算的结果为零,Z=0表示运算的结果非零。
C 可以有4种方法设置C的值:
加法运算(包括CMN):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0。
减法运算(包括CMP):当运算时产生了借位时(无符号数溢出),C=0,否则C=1。
对于包含移位操作的非加/减运算指令,C为移出值的最后一位。
对于其它的非加/减运算指令,C的值通常不会改变。
V 可以有2种方法设置V的值:
对于加减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出
对于其它的非加/减运算指令,V的值通常不会改变。

0000 = EQ - Z set (equal,相等)
0001 = NE - Z clear (not equal,不相等)
0010 = CS - C set (unsigned higher or same,无符号大于或等于)
0011 = CC - C clear (unsigned lower,无符号小于)
0100 = MI - N set (negative,负数)
0101 = PL - N clear (positive or zero,正数或零)
0110 = VS - V set (overflow,溢出)
0111 = VC - V clear (no overflow,未溢出)
1000 = HI - C set and Z clear (unsigned higher,无符号大于)
1001 = LS - C clear or Z set (unsigned lower or same,无符号小于或等于)
1010 = GE - N set and V set, or N clear and V clear (greater or equal,带符号大于或等于)
1011 = LT - N set and V clear, or N clear and V set (less than,带符号小于)
1100 = GT - Z clear, and either N set and V set, or N clear and V clear (greater than,带符号大于)
1101 = LE - Z set, or N set and V clear, or N clear and V set (less than or equal,带符号小于或等于)
1110 = AL - always
1111 = NV - never

from:
https://blog.csdn.net/nanfangqiulin/article/details/51122718

movk

这两个有时有时一个接一个地使用。它们用于移动立即数。 MOVZ将立即数(16位值)移至寄存器,并且该立即数之外的所有其他位均设置为零。可以将立即数向左移0、16、32或48。MOVK移动并立即取值,但保持寄存器的其他位不变。例如,假设您需要将此值移动0x7fb7fb1f88来注册X0。首先,您将使用MOVZ指令移动前16位(位0到15),因此寄存器的其余部分设置为零。然后,您将使用MOVK指令移动后16位(第16到31位),因此之前移动的值(前16位)保留在寄存器中,其余的其余位也是如此。

      instruction                     value of x0
mov    x0, #0x1f88           |        0x1f88
movk   x0, #0xb7fb, lsl #16  |        0xb7fb1f88
movk   x0, #0x7f, lsl #32    |        0x7fb7fb1f88 

 brk #imm16

brk指令执行后将产生一个异常,一个同步异常

brk fault EC是0x3C

static struct break_hook bug_break_hook = {
    .esr_val = 0xf2000000 | BUG_BRK_IMM,
    .esr_mask = 0xffffffff,
    .fn = bug_handler,
};

AArch64 X/W宽度通用寄存器之间的关系

操作W宽度的寄存器,其高32位将会置0,只有低32位有效。比如往先往X10里写一个64bit的数UL(-2),再往W10里写一个32bit的数1<<31,之后再读X10,读到的值是0x80000000,如下面的测试code:

复制代码
    unsigned long val64 = UL(-2);
    unsigned int val32 = 1<<31;
    unsigned long result = 0;
    
    asm volatile("mov x10, %x1\n"
                 "mov w10, %w2\n"
                 "mov %x0, x10":  "=r"(result) : "r"(val64), "r"(val32));

    pr_emerg("result is %#lx.\n", result);
复制代码

 执行结果为:

result is 0x80000000.

 

links

https://insidelinuxdev.net/article/a03ups.html (arm instruction illustration, good)

 

posted @ 2021-04-25 13:33  aspirs  阅读(1281)  评论(0编辑  收藏  举报