cgen,parser: fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017)

This commit is contained in:
kbkpbot 2025-03-24 07:00:57 +08:00 committed by GitHub
parent 1f07431e1a
commit e733c007bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 138 additions and 6 deletions

View File

@ -3130,8 +3130,8 @@ fn (mut g Gen) asm_stmt(stmt ast.AsmStmt) {
} else { } else {
g.write(' ') g.write(' ')
} }
// swap destination and operands for att syntax // swap destination and operands for att syntax, not for arm64
if template.args.len != 0 && !template.is_directive { if template.args.len != 0 && !template.is_directive && stmt.arch != .arm64 {
template.args.prepend(template.args.last()) template.args.prepend(template.args.last())
template.args.delete(template.args.len - 1) template.args.delete(template.args.len - 1)
} }
@ -3206,8 +3206,12 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
g.write("'${arg.val}'") g.write("'${arg.val}'")
} }
ast.IntegerLiteral { ast.IntegerLiteral {
if stmt.arch == .arm64 {
g.write('#${arg.val}')
} else {
g.write('\$${arg.val}') g.write('\$${arg.val}')
} }
}
ast.FloatLiteral { ast.FloatLiteral {
if g.pref.nofloat { if g.pref.nofloat {
g.write('\$${arg.val.int()}') g.write('\$${arg.val.int()}')

View File

@ -1266,6 +1266,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
for p.tok.kind !in [.semicolon, .rcbr, .eof] { for p.tok.kind !in [.semicolon, .rcbr, .eof] {
template_pos := p.tok.pos() template_pos := p.tok.pos()
mut name := '' mut name := ''
mut comments := []ast.Comment{}
if p.tok.kind == .name && arch == .amd64 && p.tok.lit in ['rex', 'vex', 'xop'] { if p.tok.kind == .name && arch == .amd64 && p.tok.lit in ['rex', 'vex', 'xop'] {
name += p.tok.lit name += p.tok.lit
p.next() p.next()
@ -1297,12 +1298,16 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
} else if p.tok.kind == .number { } else if p.tok.kind == .number {
name += p.tok.lit name += p.tok.lit
p.next() p.next()
} else if p.tok.kind == .comment {
for p.tok.kind == .comment {
comments << p.comment()
}
} else { } else {
name += p.tok.lit name += p.tok.lit
p.check(.name) p.check(.name)
} }
// dots are part of instructions for some riscv extensions and webassembly // dots are part of instructions for some riscv extensions and webassembly, arm64
if arch in [.rv32, .rv64, .wasm32] { if arch in [.rv32, .rv64, .wasm32, .arm64] {
for p.tok.kind == .dot { for p.tok.kind == .dot {
name += '.' name += '.'
p.next() p.next()
@ -1405,7 +1410,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
// break // break
// } // }
} }
mut comments := []ast.Comment{}
for p.tok.kind == .comment { for p.tok.kind == .comment {
comments << p.comment() comments << p.comment()
} }

View File

@ -0,0 +1,124 @@
// vtest build: gcc
fn test_inline_asm() {
a, mut b := 10, 0
asm arm64 {
mov x0, a
mov b, x0
; +r (b)
; r (a)
; x0
}
assert a == 10
assert b == 10
mut c := 0
asm arm64 {
mov x0, 5
mov c, x0
; +r (c)
; ; x0
}
assert c == 5
d, e, mut f := 10, 2, 0
asm arm64 {
mov x0, d
mov x1, e
add x0, x0, x1
add x0, x0, 5
mov f, x0
; +r (f) // output
; r (d)
r (e) // input
; x0
x1
}
assert d == 10
assert e == 2
assert f == 17
mut j := 0
// do 5*3
// adding three, five times
asm arm64 {
mov x0, 5 // loop 5 times
mov x1, 0
loop_start:
add x1, x1, 3
sub x0, x0, 1
cmp x0, 0
b.gt loop_start
mov j, x1
; +r (j)
; ; x0
x1
}
assert j == 5 * 3
/*
// not marked as mut because we dereference m to change l
l := 5
m := &l
asm arm64 {
movd [m], 7 // have to specify size with q
; ; r (m)
}
assert l == 7
mut manu := Manu{}
asm arm64 {
mov x0, MIDR_EL1
mov x1, ID_AA64ISAR0_EL1
mov x2, ID_AA64MMFR0_EL1
; =r (manu.midr_el1) as x0
=r (manu.id_aa64isar0_el1) as x1
=r (manu.id_aa64mmfr0_el1) as x2
}
manu.str()
*/
}
/*
@[packed]
struct Manu {
mut:
midr_el1 u64
id_aa64isar0_el1 u64
id_aa64mmfr0_el1 u64
zero u8 // for string
}
fn (m Manu) str() string {
return unsafe {
string{
str: &u8(&m)
len: 24
is_lit: 1
}
}
}
fn test_asm_generic() {
u := u64(49)
b := unsafe { bool(123) }
assert generic_asm(u) == 14
assert u == 63
assert u64(generic_asm(b)) == 14
assert u64(b) == 137
}
fn generic_asm[T](var &T) T {
mut ret := T(14)
unsafe {
asm volatile arm64 {
mov x0, ret
mov x1, var
add x1, x0, 0
mov var, x1
; +m (var[0]) as var
+r (ret)
; ; memory x0 x1
}
}
return ret
}
*/