LoongArch-Documentation icon indicating copy to clipboard operation
LoongArch-Documentation copied to clipboard

缺失的指令 missing instructions

Open shouhuanxiaoji opened this issue 2 years ago • 17 comments

Describe the question:

类似x86下的mov指令和ret指令在手册中未查到 Describe the idea:

在编写loongarch64汇编时,发现传送指令(类似x86的mov),无条件跳转指令(类似ret)是缺失的,经过对一个c文件,在gcc下进行汇编编译,我们认为这几个指令是可能的: jr指令,对应ret指令,用法为 jr $r1 la.local指令,对应mov,用法为 la.local 寄存器操作数, 被传送内容(x86下通常是.data域定义的变量) 另外还看到一个la.global不知是何含义 以上三个指令,在《loongarch架构手册第一部分》内查不到,请帮忙核实一下。 Additional context:

shouhuanxiaoji avatar Jan 10 '22 10:01 shouhuanxiaoji

用作寄存器-寄存器搬运的 "mov" 指令写法是 move rd, rj(和 MIPS 一致),是 or rd, rj, zero 的语法糖;

用作过程调用返回的 "ret" 指令写法是 jr $ra(也和 MIPS 一致),jr $foojirl $zero, $foo, 0 的语法糖。

xen0n avatar Jan 10 '22 10:01 xen0n

这俩指令(和一票别的东西)都是伪指令,这本手册没有讲伪指令。不过这些东西确实龙芯文档团队需要考虑优化。

xen0n avatar Jan 10 '22 10:01 xen0n

打错了,是jr指令,不是ja

shouhuanxiaoji avatar Jan 10 '22 10:01 shouhuanxiaoji

感谢,另外问一下ll和sc这一对操作(即原子读写操作),只看到有字和双字的操作,字节和半字操作并没有,操作byte原子读写应该怎么写?

shouhuanxiaoji avatar Jan 10 '22 10:01 shouhuanxiaoji

另外经过实际编译测试,jirl 0, 1, 0或jirl 0, $r1, 0 这一指令都会报错

shouhuanxiaoji avatar Jan 10 '22 10:01 shouhuanxiaoji

感谢,另外问一下ll和sc这一对操作(即原子读写操作),只看到有字和双字的操作,字节和半字操作并没有,操作byte原子读写应该怎么写?

把操作 byte 原子读写的过程放 llsc 这一对操作中间。

FreeFlyingSheep avatar Jan 10 '22 11:01 FreeFlyingSheep

另外经过实际编译测试,jirl 0, 1, 0或jirl 0, $r1, 0 这一指令都会报错

jirl 的指令格式是 jirl rd, rj, offs。其中,rdrj 是寄存器,因此常量 0 是非法的,需要使用 $zero/$r0 寄存器。

FreeFlyingSheep avatar Jan 10 '22 11:01 FreeFlyingSheep

la 系列的指令都是伪指令,用于加载地址。

FreeFlyingSheep avatar Jan 10 '22 11:01 FreeFlyingSheep

另外经过实际编译测试,jirl 0, 1, 0或jirl 0, $r1, 0 这一指令都会报错

jirl 的结构是 jirl 链接寄存器, 目标地址寄存器, 目标地址偏移 >> 2 因此前两个都是寄存器操作数,只有最后一个是立即数。

xen0n avatar Jan 10 '22 11:01 xen0n

@FreeFlyingSheep 是否能详细说说byte原子操作。 我们有一个汇编代码段,他的代码是这样:

la464_lock_read_b:
    dbar    0
    // address is r4, return is r4
    ll.w    $r4, $r4, 0
    jirl     $r0, $r1, 0		//ret    

另一个c原子会调用这个功能

//这是针对arm的代码,需要再写一段针对loongarch的
            if(MODREG) { // reg / reg: no lock
                tmp8u = GB;
                GB = EB->byte[0];
                EB->byte[0] = tmp8u;
            } else {
                do {
                    tmp8u = arm64_lock_read_b(EB);
                } while(arm64_lock_write_b(EB, GB));
                GB = tmp8u;
            }

这是一个写的锁操作,需要原子写入一个byte,但是因为ll只有ll.w(字的原子写)和ll.d(双字的原子写),有没有ll.b这种写入byte的?或者怎么变相实现?

shouhuanxiaoji avatar Jan 10 '22 12:01 shouhuanxiaoji

我一开始的表述不大准确,用 ll.w/sc.w 模拟 ll.b/sc.b 的过程比较复杂,大体思路是先对齐,然后用 ll.w/sc.w 结合位运算操作需要写入的 byte,具体的例子可以参考内核的 __xchg_small(volatile void *ptr, unsigned long val, unsigned int size) 函数,该函数会把 size 大小的 val 变量原子写到 ptr 位置,并返回该位置的原始值。

FreeFlyingSheep avatar Jan 11 '22 01:01 FreeFlyingSheep

又遇到一个奇怪的问题,在loongnix(dnf based,我不知道是不是fedora)和UOS(DEBIAN based)上,汇编的注释符并不一样,UOS上是//,loongnix是#,双方的gcc都是8.3.0

shouhuanxiaoji avatar Jan 11 '22 06:01 shouhuanxiaoji

又遇到一个奇怪的问题,在loongnix(dnf based,我不知道是不是fedora)和UOS(DEBIAN based)上,汇编的注释符并不一样,UOS上是//,loongnix是#,双方的gcc都是8.3.0

两种注释方式都可以,/* */ 也行。

FreeFlyingSheep avatar Jan 11 '22 06:01 FreeFlyingSheep

友情提醒:工单系统不是技术支持论坛,这边的人也都不是技术支持工程师(我甚至不是龙芯员工)。类似的问题可以去社区 http://bbs.loongnix.cn 问。

xen0n avatar Jan 11 '22 07:01 xen0n

额,明白

shouhuanxiaoji avatar Jan 11 '22 11:01 shouhuanxiaoji

同时也欢迎各位开源大佬关注我们的项目,https://github.com/ptitSeb/box64 另一个x86二进制模拟器

shouhuanxiaoji avatar Jan 11 '22 11:01 shouhuanxiaoji

我感觉 move 这个东西还是文档记录一下好,不然大家会自己乱写各种变体 (add $rd, $rs, $r0, addi $rd, $rs, 0, ori $rd, $rs, 0, ...)。另外不知道不同变体会不会导致性能的变化 (我不是很熟悉 CPU 内部的流水线这些东西)。

xry111 avatar Apr 19 '22 10:04 xry111