Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

缺失的指令 missing instructions #39

Open
shouhuanxiaoji opened this issue Jan 10, 2022 · 17 comments
Open

缺失的指令 missing instructions #39

shouhuanxiaoji opened this issue Jan 10, 2022 · 17 comments

Comments

@shouhuanxiaoji
Copy link

shouhuanxiaoji commented Jan 10, 2022

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:

@xen0n
Copy link
Contributor

xen0n commented Jan 10, 2022

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

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

@xen0n
Copy link
Contributor

xen0n commented Jan 10, 2022

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

@shouhuanxiaoji
Copy link
Author

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

@shouhuanxiaoji
Copy link
Author

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

@shouhuanxiaoji
Copy link
Author

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

@FreeFlyingSheep
Copy link
Collaborator

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

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

@FreeFlyingSheep
Copy link
Collaborator

FreeFlyingSheep commented Jan 10, 2022

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

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

@FreeFlyingSheep
Copy link
Collaborator

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

@xen0n
Copy link
Contributor

xen0n commented Jan 10, 2022

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

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

@shouhuanxiaoji
Copy link
Author

shouhuanxiaoji commented Jan 10, 2022

@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的?或者怎么变相实现?

@FreeFlyingSheep
Copy link
Collaborator

我一开始的表述不大准确,用 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 位置,并返回该位置的原始值。

@shouhuanxiaoji
Copy link
Author

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

@FreeFlyingSheep
Copy link
Collaborator

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

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

@xen0n
Copy link
Contributor

xen0n commented Jan 11, 2022

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

@shouhuanxiaoji
Copy link
Author

额,明白

@shouhuanxiaoji
Copy link
Author

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

@xry111
Copy link
Contributor

xry111 commented Apr 19, 2022

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants