all: small asm fixes and number labels (#9730)
parent
968cb13a36
commit
0099458c0a
vlib/v
ast
checker
gen/c
parser
tests/assembly
|
@ -1101,9 +1101,8 @@ pub type AsmArg = AsmAddressing | AsmAlias | AsmDisp | AsmRegister | BoolLiteral
|
||||||
FloatLiteral | IntegerLiteral | string
|
FloatLiteral | IntegerLiteral | string
|
||||||
|
|
||||||
pub struct AsmRegister {
|
pub struct AsmRegister {
|
||||||
pub:
|
pub mut:
|
||||||
name string // eax or r12d
|
name string // eax or r12d etc.
|
||||||
mut:
|
|
||||||
typ Type
|
typ Type
|
||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
@ -1116,8 +1115,9 @@ pub:
|
||||||
|
|
||||||
pub struct AsmAlias {
|
pub struct AsmAlias {
|
||||||
pub:
|
pub:
|
||||||
|
pos token.Position
|
||||||
|
pub mut:
|
||||||
name string // a
|
name string // a
|
||||||
pos token.Position
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsmAddressing {
|
pub struct AsmAddressing {
|
||||||
|
|
|
@ -3839,12 +3839,9 @@ fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) {
|
||||||
*/
|
*/
|
||||||
if template.name !in ['skip', 'space', 'byte', 'word', 'short', 'int', 'long', 'quad',
|
if template.name !in ['skip', 'space', 'byte', 'word', 'short', 'int', 'long', 'quad',
|
||||||
'globl', 'global', 'section', 'text', 'data', 'bss', 'fill', 'org', 'previous',
|
'globl', 'global', 'section', 'text', 'data', 'bss', 'fill', 'org', 'previous',
|
||||||
'string', 'asciz', 'ascii'] { // all tcc supported assembler directive
|
'string', 'asciz', 'ascii'] { // all tcc-supported assembler directives
|
||||||
c.error('unknown assembler directive: `$template.name`', template.pos)
|
c.error('unknown assembler directive: `$template.name`', template.pos)
|
||||||
}
|
}
|
||||||
// if c.file in {
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
for mut arg in template.args {
|
for mut arg in template.args {
|
||||||
c.asm_arg(arg, stmt, aliases)
|
c.asm_arg(arg, stmt, aliases)
|
||||||
|
|
|
@ -1969,7 +1969,22 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.AsmDisp {
|
ast.AsmDisp {
|
||||||
g.write(arg.val)
|
if arg.val.len >= 2 && arg.val[0] in [`b`, `f`] {
|
||||||
|
mut is_digit := true
|
||||||
|
for c in arg.val[1..] {
|
||||||
|
if !c.is_digit() {
|
||||||
|
is_digit = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_digit {
|
||||||
|
g.write(arg.val[1..] + rune(arg.val[0]).str())
|
||||||
|
} else {
|
||||||
|
g.write(arg.val)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.write(arg.val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
g.write('$arg')
|
g.write('$arg')
|
||||||
|
|
|
@ -859,11 +859,11 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
if p.tok.lit == 'volatile' && p.tok.kind == .name {
|
if p.tok.lit == 'volatile' && p.tok.kind == .name {
|
||||||
arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto }
|
arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto }
|
||||||
is_volatile = true
|
is_volatile = true
|
||||||
p.check(.name)
|
p.next()
|
||||||
} else if p.tok.kind == .key_goto {
|
} else if p.tok.kind == .key_goto {
|
||||||
arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto }
|
arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto }
|
||||||
is_goto = true
|
is_goto = true
|
||||||
p.check(.key_goto)
|
p.next()
|
||||||
}
|
}
|
||||||
if arch == ._auto && !p.pref.is_fmt {
|
if arch == ._auto && !p.pref.is_fmt {
|
||||||
p.error('unknown assembly architecture')
|
p.error('unknown assembly architecture')
|
||||||
|
@ -871,7 +871,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
if p.tok.kind != .name {
|
if p.tok.kind != .name {
|
||||||
p.error('must specify assembly architecture')
|
p.error('must specify assembly architecture')
|
||||||
} else {
|
} else {
|
||||||
p.check(.name)
|
p.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
p.check_for_impure_v(ast.pref_arch_to_table_language(arch), p.prev_tok.position())
|
p.check_for_impure_v(ast.pref_arch_to_table_language(arch), p.prev_tok.position())
|
||||||
|
@ -894,11 +894,14 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
mut name := ''
|
mut name := ''
|
||||||
is_directive := p.tok.kind == .dot
|
is_directive := p.tok.kind == .dot
|
||||||
if is_directive {
|
if is_directive {
|
||||||
p.check(.dot)
|
p.next()
|
||||||
}
|
}
|
||||||
if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions.
|
if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions.
|
||||||
name = p.tok.kind.str()
|
name = p.tok.kind.str()
|
||||||
p.next()
|
p.next()
|
||||||
|
} else if p.tok.kind == .number {
|
||||||
|
name = p.tok.lit
|
||||||
|
p.next()
|
||||||
} else {
|
} else {
|
||||||
name = p.tok.lit
|
name = p.tok.lit
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
|
@ -907,7 +910,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
if arch in [.rv32, .rv64] {
|
if arch in [.rv32, .rv64] {
|
||||||
for p.tok.kind == .dot {
|
for p.tok.kind == .dot {
|
||||||
name += '.'
|
name += '.'
|
||||||
p.check(.dot)
|
p.next()
|
||||||
name += p.tok.lit
|
name += p.tok.lit
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
}
|
}
|
||||||
|
@ -915,69 +918,92 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
mut is_label := false
|
mut is_label := false
|
||||||
|
|
||||||
mut args := []ast.AsmArg{}
|
mut args := []ast.AsmArg{}
|
||||||
args_loop: for {
|
if p.tok.line_nr == p.prev_tok.line_nr {
|
||||||
if p.prev_tok.position().line_nr < p.tok.position().line_nr {
|
args_loop: for {
|
||||||
break
|
if p.prev_tok.position().line_nr < p.tok.position().line_nr {
|
||||||
}
|
break
|
||||||
match p.tok.kind {
|
|
||||||
.name {
|
|
||||||
args << p.reg_or_alias()
|
|
||||||
}
|
}
|
||||||
.number {
|
match p.tok.kind {
|
||||||
number_lit := p.parse_number_literal()
|
.name {
|
||||||
match number_lit {
|
if p.tok.kind == .name && p.tok.lit.len >= 2
|
||||||
ast.FloatLiteral {
|
&& (p.tok.lit.starts_with('b') || p.tok.lit.starts_with('f')) {
|
||||||
args << ast.FloatLiteral{
|
mut is_digit := true
|
||||||
...number_lit
|
for c in p.tok.lit[1..] {
|
||||||
}
|
if !c.is_digit() {
|
||||||
}
|
is_digit = false
|
||||||
ast.IntegerLiteral {
|
break
|
||||||
if is_directive {
|
|
||||||
args << ast.AsmDisp{
|
|
||||||
val: number_lit.val
|
|
||||||
pos: number_lit.pos
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if is_digit {
|
||||||
|
args << ast.AsmDisp{
|
||||||
|
val: p.tok.lit
|
||||||
|
pos: p.tok.position()
|
||||||
|
}
|
||||||
|
p.check(.name)
|
||||||
} else {
|
} else {
|
||||||
args << ast.IntegerLiteral{
|
args << p.reg_or_alias()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args << p.reg_or_alias()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.number {
|
||||||
|
number_lit := p.parse_number_literal()
|
||||||
|
match number_lit {
|
||||||
|
ast.FloatLiteral {
|
||||||
|
args << ast.FloatLiteral{
|
||||||
...number_lit
|
...number_lit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
ast.IntegerLiteral {
|
||||||
else {
|
if is_directive || number_lit.val.ends_with('b')
|
||||||
verror('p.parse_number_literal() invalid output: `$number_lit`')
|
|| number_lit.val.ends_with('f') {
|
||||||
|
args << ast.AsmDisp{
|
||||||
|
val: number_lit.val
|
||||||
|
pos: number_lit.pos
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args << ast.IntegerLiteral{
|
||||||
|
...number_lit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
verror('p.parse_number_literal() invalid output: `$number_lit`')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.chartoken {
|
||||||
.chartoken {
|
args << ast.CharLiteral{
|
||||||
args << ast.CharLiteral{
|
val: p.tok.lit
|
||||||
val: p.tok.lit
|
pos: p.tok.position()
|
||||||
pos: p.tok.position()
|
}
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
.colon {
|
||||||
|
is_label = true
|
||||||
|
p.next()
|
||||||
|
local_labels << name
|
||||||
|
break
|
||||||
|
}
|
||||||
|
.lsbr {
|
||||||
|
args << p.asm_addressing()
|
||||||
|
}
|
||||||
|
.rcbr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
.semicolon {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.error('invalid token in assembly block')
|
||||||
}
|
}
|
||||||
p.check(.chartoken)
|
|
||||||
}
|
}
|
||||||
.colon {
|
if p.tok.kind == .comma {
|
||||||
is_label = true
|
p.next()
|
||||||
p.check(.colon)
|
} else {
|
||||||
local_labels << name
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
.lsbr {
|
|
||||||
args << p.asm_addressing()
|
|
||||||
}
|
|
||||||
.rcbr {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
.semicolon {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.error('invalid token in assembly block')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p.tok.kind == .comma {
|
|
||||||
p.check(.comma)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
// if p.prev_tok.position().line_nr < p.tok.position().line_nr {
|
// if p.prev_tok.position().line_nr < p.tok.position().line_nr {
|
||||||
// break
|
// break
|
||||||
|
@ -1015,14 +1041,14 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
// because p.reg_or_alias() requires the scope with registers to recognize registers.
|
// because p.reg_or_alias() requires the scope with registers to recognize registers.
|
||||||
backup_scope = p.scope
|
backup_scope = p.scope
|
||||||
p.scope = scope
|
p.scope = scope
|
||||||
p.check(.semicolon)
|
p.next()
|
||||||
for p.tok.kind == .name {
|
for p.tok.kind == .name {
|
||||||
reg := ast.AsmRegister{
|
reg := ast.AsmRegister{
|
||||||
name: p.tok.lit
|
name: p.tok.lit
|
||||||
typ: 0
|
typ: 0
|
||||||
size: -1
|
size: -1
|
||||||
}
|
}
|
||||||
p.check(.name)
|
p.next()
|
||||||
|
|
||||||
mut comments := []ast.Comment{}
|
mut comments := []ast.Comment{}
|
||||||
for p.tok.kind == .comment {
|
for p.tok.kind == .comment {
|
||||||
|
@ -1039,10 +1065,10 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_goto && p.tok.kind == .semicolon {
|
if is_goto && p.tok.kind == .semicolon {
|
||||||
p.check(.semicolon)
|
p.next()
|
||||||
for p.tok.kind == .name {
|
for p.tok.kind == .name {
|
||||||
global_labels << p.tok.lit
|
global_labels << p.tok.lit
|
||||||
p.check(.name)
|
p.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1100,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) reg_or_alias() ast.AsmArg {
|
fn (mut p Parser) reg_or_alias() ast.AsmArg {
|
||||||
assert p.tok.kind == .name
|
|
||||||
if p.tok.lit in p.scope.objects {
|
if p.tok.lit in p.scope.objects {
|
||||||
x := p.scope.objects[p.tok.lit]
|
x := p.scope.objects[p.tok.lit]
|
||||||
if x is ast.AsmRegister {
|
if x is ast.AsmRegister {
|
||||||
|
@ -1200,7 +1225,7 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
} else if p.tok.kind == .number {
|
} else if p.tok.kind == .number {
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
@ -1220,11 +1245,11 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
if p.peek_tok.kind == .plus && p.tok.kind == .name { // [base + displacement], [base + index ∗ scale + displacement], [base + index + displacement] or [rip + displacement]
|
if p.peek_tok.kind == .plus && p.tok.kind == .name { // [base + displacement], [base + index ∗ scale + displacement], [base + index + displacement] or [rip + displacement]
|
||||||
if p.tok.lit == 'rip' {
|
if p.tok.lit == 'rip' {
|
||||||
rip := p.reg_or_alias()
|
rip := p.reg_or_alias()
|
||||||
p.check(.plus)
|
p.next()
|
||||||
|
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
@ -1240,16 +1265,16 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base := p.reg_or_alias()
|
base := p.reg_or_alias()
|
||||||
p.check(.plus)
|
p.next()
|
||||||
if p.peek_tok.kind == .rsbr {
|
if p.peek_tok.kind == .rsbr {
|
||||||
if p.tok.kind == .number {
|
if p.tok.kind == .number {
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.check(.number)
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
|
@ -1265,13 +1290,13 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
}
|
}
|
||||||
index := p.reg_or_alias()
|
index := p.reg_or_alias()
|
||||||
if p.tok.kind == .mul {
|
if p.tok.kind == .mul {
|
||||||
p.check(.mul)
|
p.next()
|
||||||
scale := p.tok.lit.int()
|
scale := p.tok.lit.int()
|
||||||
p.check(.number)
|
p.check(.number)
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
@ -1288,10 +1313,10 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
pos: pos.extend(p.prev_tok.position())
|
pos: pos.extend(p.prev_tok.position())
|
||||||
}
|
}
|
||||||
} else if p.tok.kind == .plus {
|
} else if p.tok.kind == .plus {
|
||||||
p.check(.plus)
|
p.next()
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
@ -1310,13 +1335,13 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
}
|
}
|
||||||
if p.peek_tok.kind == .mul { // [index ∗ scale + displacement]
|
if p.peek_tok.kind == .mul { // [index ∗ scale + displacement]
|
||||||
index := p.reg_or_alias()
|
index := p.reg_or_alias()
|
||||||
p.check(.mul)
|
p.next()
|
||||||
scale := p.tok.lit.int()
|
scale := p.tok.lit.int()
|
||||||
p.check(.number)
|
p.check(.number)
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := if p.tok.kind == .name {
|
displacement := if p.tok.kind == .name {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
p.check(.name)
|
p.next()
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x := ast.AsmArg(p.tok.lit)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
@ -1371,10 +1396,10 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO {
|
||||||
}
|
}
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
constraint += '='
|
constraint += '='
|
||||||
p.check(.assign)
|
p.next()
|
||||||
} else if p.tok.kind == .plus {
|
} else if p.tok.kind == .plus {
|
||||||
constraint += '+'
|
constraint += '+'
|
||||||
p.check(.plus)
|
p.next()
|
||||||
}
|
}
|
||||||
constraint += p.tok.lit
|
constraint += p.tok.lit
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
|
@ -1387,7 +1412,7 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO {
|
||||||
}
|
}
|
||||||
mut alias := ''
|
mut alias := ''
|
||||||
if p.tok.kind == .key_as {
|
if p.tok.kind == .key_as {
|
||||||
p.check(.key_as)
|
p.next()
|
||||||
alias = p.tok.lit
|
alias = p.tok.lit
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
} else if mut expr is ast.Ident {
|
} else if mut expr is ast.Ident {
|
||||||
|
|
|
@ -96,7 +96,36 @@ fn test_inline_asm() {
|
||||||
}
|
}
|
||||||
assert n == [7, 11, 2, 6]
|
assert n == [7, 11, 2, 6]
|
||||||
|
|
||||||
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v files
|
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files
|
||||||
|
|
||||||
|
mut manu := Manu{}
|
||||||
|
asm amd64 {
|
||||||
|
mov eax, 0
|
||||||
|
cpuid
|
||||||
|
; =b (manu.ebx) as ebx0
|
||||||
|
=d (manu.edx) as edx0
|
||||||
|
=c (manu.ecx) as ecx0
|
||||||
|
}
|
||||||
|
manu.str()
|
||||||
|
}
|
||||||
|
|
||||||
|
[packed]
|
||||||
|
struct Manu {
|
||||||
|
mut:
|
||||||
|
ebx u32
|
||||||
|
edx u32
|
||||||
|
ecx u32
|
||||||
|
zero byte // for string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (m Manu) str() string {
|
||||||
|
return unsafe {
|
||||||
|
string{
|
||||||
|
str: &byte(&m)
|
||||||
|
len: 24
|
||||||
|
is_lit: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
|
// this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
|
||||||
|
|
|
@ -95,4 +95,33 @@ fn test_inline_asm() {
|
||||||
r (n.data) as in_data
|
r (n.data) as in_data
|
||||||
}
|
}
|
||||||
assert n == [7, 11, 2, 6]
|
assert n == [7, 11, 2, 6]
|
||||||
|
|
||||||
|
mut manu := Manu{}
|
||||||
|
asm amd64 {
|
||||||
|
mov eax, 0
|
||||||
|
cpuid
|
||||||
|
; =b (manu.ebx) as ebx0
|
||||||
|
=d (manu.edx) as edx0
|
||||||
|
=c (manu.ecx) as ecx0
|
||||||
|
}
|
||||||
|
manu.str()
|
||||||
|
}
|
||||||
|
|
||||||
|
[packed]
|
||||||
|
struct Manu {
|
||||||
|
mut:
|
||||||
|
ebx u32
|
||||||
|
edx u32
|
||||||
|
ecx u32
|
||||||
|
zero byte // for string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (m Manu) str() string {
|
||||||
|
return unsafe {
|
||||||
|
string{
|
||||||
|
str: &byte(&m)
|
||||||
|
len: 24
|
||||||
|
is_lit: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ module util
|
||||||
pub fn add(a ...int) int {
|
pub fn add(a ...int) int {
|
||||||
mut res := 0
|
mut res := 0
|
||||||
asm amd64 {
|
asm amd64 {
|
||||||
loop_start3:
|
1:
|
||||||
addq rax, [in_data + rcx * 4 + 0]
|
addq rax, [in_data + rcx * 4 + 0]
|
||||||
loop loop_start3
|
loop b1
|
||||||
addq rax, [in_data + rcx * 4 + 0]
|
addq rax, [in_data + rcx * 4 + 0]
|
||||||
; +a (res)
|
; +a (res)
|
||||||
; c (a.len - 1) // c is counter (loop) register
|
; c (a.len - 1) // c is counter (loop) register
|
||||||
|
|
Loading…
Reference in New Issue