From e733c007bfbe65a68683bbe93932dce236b6064c Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 24 Mar 2025 07:00:57 +0800 Subject: [PATCH] cgen,parser: fix arm64 asm operand position; fix arm64 asm imm; support arm64 dot instruction (#24017) --- vlib/v/gen/c/cgen.v | 10 +- vlib/v/parser/parser.v | 10 +- vlib/v/slow_tests/assembly/asm_test.arm64.v | 124 ++++++++++++++++++++ 3 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 vlib/v/slow_tests/assembly/asm_test.arm64.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index d7161cb440..b9f570bdad 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3130,8 +3130,8 @@ fn (mut g Gen) asm_stmt(stmt ast.AsmStmt) { } else { g.write(' ') } - // swap destination and operands for att syntax - if template.args.len != 0 && !template.is_directive { + // swap destination and operands for att syntax, not for arm64 + if template.args.len != 0 && !template.is_directive && stmt.arch != .arm64 { template.args.prepend(template.args.last()) template.args.delete(template.args.len - 1) } @@ -3206,7 +3206,11 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) { g.write("'${arg.val}'") } ast.IntegerLiteral { - g.write('\$${arg.val}') + if stmt.arch == .arm64 { + g.write('#${arg.val}') + } else { + g.write('\$${arg.val}') + } } ast.FloatLiteral { if g.pref.nofloat { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index e20d5cb0c0..ca9dd8c46d 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1266,6 +1266,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { for p.tok.kind !in [.semicolon, .rcbr, .eof] { template_pos := p.tok.pos() mut name := '' + mut comments := []ast.Comment{} if p.tok.kind == .name && arch == .amd64 && p.tok.lit in ['rex', 'vex', 'xop'] { name += p.tok.lit p.next() @@ -1297,12 +1298,16 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { } else if p.tok.kind == .number { name += p.tok.lit p.next() + } else if p.tok.kind == .comment { + for p.tok.kind == .comment { + comments << p.comment() + } } else { name += p.tok.lit p.check(.name) } - // dots are part of instructions for some riscv extensions and webassembly - if arch in [.rv32, .rv64, .wasm32] { + // dots are part of instructions for some riscv extensions and webassembly, arm64 + if arch in [.rv32, .rv64, .wasm32, .arm64] { for p.tok.kind == .dot { name += '.' p.next() @@ -1405,7 +1410,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { // break // } } - mut comments := []ast.Comment{} for p.tok.kind == .comment { comments << p.comment() } diff --git a/vlib/v/slow_tests/assembly/asm_test.arm64.v b/vlib/v/slow_tests/assembly/asm_test.arm64.v new file mode 100644 index 0000000000..1321a70b0a --- /dev/null +++ b/vlib/v/slow_tests/assembly/asm_test.arm64.v @@ -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 +} +*/