asm: make fixed labels possible as displacement (#9549)
parent
63f835c4ce
commit
8d5e310189
|
@ -540,6 +540,7 @@ pub mut:
|
||||||
warnings []errors.Warning // all the checker warnings in the file
|
warnings []errors.Warning // all the checker warnings in the file
|
||||||
notices []errors.Notice // all the checker notices in the file
|
notices []errors.Notice // all the checker notices in the file
|
||||||
generic_fns []&FnDecl
|
generic_fns []&FnDecl
|
||||||
|
global_labels []string // from `asm { .globl labelname }`
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IdentFn {
|
pub struct IdentFn {
|
||||||
|
@ -1064,13 +1065,12 @@ pub:
|
||||||
clobbered []AsmClobbered
|
clobbered []AsmClobbered
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
templates []AsmTemplate
|
templates []AsmTemplate
|
||||||
scope &Scope
|
scope &Scope
|
||||||
output []AsmIO
|
output []AsmIO
|
||||||
input []AsmIO
|
input []AsmIO
|
||||||
global_labels []string // listed after clobbers, paired with is_goto == true
|
global_labels []string // labels defined in assembly block, exported with `.globl`
|
||||||
local_labels []string // local to the assembly block
|
local_labels []string // local to the assembly block
|
||||||
exported_symbols []string // functions defined in assembly block, exported with `.globl`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsmTemplate {
|
pub struct AsmTemplate {
|
||||||
|
@ -1083,8 +1083,8 @@ pub mut:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
// [eax+5] | j | eax | true | `a` | 0.594 | 123 | 'hi' | label_name
|
// [eax+5] | j | displacement literal (e.g. 123 in [rax + 123] ) | eax | true | `a` | 0.594 | 123 | label_name
|
||||||
pub type AsmArg = AsmAddressing | AsmAlias | AsmRegister | BoolLiteral | CharLiteral |
|
pub type AsmArg = AsmAddressing | AsmAlias | AsmDisp | AsmRegister | BoolLiteral | CharLiteral |
|
||||||
FloatLiteral | IntegerLiteral | string
|
FloatLiteral | IntegerLiteral | string
|
||||||
|
|
||||||
pub struct AsmRegister {
|
pub struct AsmRegister {
|
||||||
|
@ -1095,6 +1095,12 @@ mut:
|
||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AsmDisp {
|
||||||
|
pub:
|
||||||
|
val string
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AsmAlias {
|
pub struct AsmAlias {
|
||||||
pub:
|
pub:
|
||||||
name string // a
|
name string // a
|
||||||
|
@ -1103,13 +1109,13 @@ pub:
|
||||||
|
|
||||||
pub struct AsmAddressing {
|
pub struct AsmAddressing {
|
||||||
pub:
|
pub:
|
||||||
displacement u32 // 8, 16 or 32 bit literal value
|
scale int = -1 // 1, 2, 4, or 8 literal
|
||||||
scale int = -1 // 1, 2, 4, or 8 literal
|
mode AddressingMode
|
||||||
mode AddressingMode
|
pos token.Position
|
||||||
pos token.Position
|
|
||||||
pub mut:
|
pub mut:
|
||||||
base AsmArg // gpr
|
displacement AsmArg // 8, 16 or 32 bit literal value
|
||||||
index AsmArg // gpr
|
base AsmArg // gpr
|
||||||
|
index AsmArg // gpr
|
||||||
}
|
}
|
||||||
|
|
||||||
// adressing modes:
|
// adressing modes:
|
||||||
|
@ -1125,9 +1131,8 @@ pub enum AddressingMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsmClobbered {
|
pub struct AsmClobbered {
|
||||||
pub:
|
|
||||||
reg AsmRegister
|
|
||||||
pub mut:
|
pub mut:
|
||||||
|
reg AsmRegister
|
||||||
comments []Comment
|
comments []Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1204,7 +1209,7 @@ pub const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: saved priviled registers for arm
|
// TODO: saved priviled registers for arm
|
||||||
const (
|
pub const (
|
||||||
arm_no_number_register_list = ['fp' /* aka r11 */, /* not instruction pointer: */ 'ip' /* aka r12 */,
|
arm_no_number_register_list = ['fp' /* aka r11 */, /* not instruction pointer: */ 'ip' /* aka r12 */,
|
||||||
'sp' /* aka r13 */, 'lr' /* aka r14 */, /* this is instruction pointer ('program counter'): */
|
'sp' /* aka r13 */, 'lr' /* aka r14 */, /* this is instruction pointer ('program counter'): */
|
||||||
'pc' /* aka r15 */,
|
'pc' /* aka r15 */,
|
||||||
|
@ -1214,7 +1219,7 @@ const (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
pub const (
|
||||||
riscv_no_number_register_list = ['zero', 'ra', 'sp', 'gp', 'tp']
|
riscv_no_number_register_list = ['zero', 'ra', 'sp', 'gp', 'tp']
|
||||||
riscv_with_number_register_list = map{
|
riscv_with_number_register_list = map{
|
||||||
'x#': 32
|
'x#': 32
|
||||||
|
|
|
@ -3768,11 +3768,11 @@ fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
for arg in template.args {
|
for mut arg in template.args {
|
||||||
c.asm_arg(arg, stmt, aliases)
|
c.asm_arg(arg, stmt, aliases)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for clob in stmt.clobbered {
|
for mut clob in stmt.clobbered {
|
||||||
c.asm_arg(clob.reg, stmt, aliases)
|
c.asm_arg(clob.reg, stmt, aliases)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3781,8 +3781,11 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) {
|
||||||
match mut arg {
|
match mut arg {
|
||||||
ast.AsmAlias {
|
ast.AsmAlias {
|
||||||
name := arg.name
|
name := arg.name
|
||||||
if name !in aliases && name !in stmt.local_labels && name !in stmt.global_labels {
|
if name !in aliases && name !in stmt.local_labels && name !in c.file.global_labels {
|
||||||
suggestion := util.new_suggestion(name, aliases)
|
mut possible := aliases.clone()
|
||||||
|
possible << stmt.local_labels
|
||||||
|
possible << c.file.global_labels
|
||||||
|
suggestion := util.new_suggestion(name, possible)
|
||||||
c.error(suggestion.say('alias or label `$arg.name` does not exist'), arg.pos)
|
c.error(suggestion.say('alias or label `$arg.name` does not exist'), arg.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3790,6 +3793,7 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) {
|
||||||
if arg.scale !in [-1, 1, 2, 4, 8] {
|
if arg.scale !in [-1, 1, 2, 4, 8] {
|
||||||
c.error('scale must be one of 1, 2, 4, or 8', arg.pos)
|
c.error('scale must be one of 1, 2, 4, or 8', arg.pos)
|
||||||
}
|
}
|
||||||
|
c.asm_arg(arg.displacement, stmt, aliases)
|
||||||
c.asm_arg(arg.base, stmt, aliases)
|
c.asm_arg(arg.base, stmt, aliases)
|
||||||
c.asm_arg(arg.index, stmt, aliases)
|
c.asm_arg(arg.index, stmt, aliases)
|
||||||
}
|
}
|
||||||
|
@ -3798,6 +3802,7 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) {
|
||||||
ast.CharLiteral {}
|
ast.CharLiteral {}
|
||||||
ast.IntegerLiteral {}
|
ast.IntegerLiteral {}
|
||||||
ast.AsmRegister {} // if the register is not found, the parser will register it as an alias
|
ast.AsmRegister {} // if the register is not found, the parser will register it as an alias
|
||||||
|
ast.AsmDisp {}
|
||||||
string {}
|
string {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -750,31 +750,36 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) {
|
||||||
f.asm_arg(base)
|
f.asm_arg(base)
|
||||||
}
|
}
|
||||||
.displacement {
|
.displacement {
|
||||||
f.write('$displacement')
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.base_plus_displacement {
|
.base_plus_displacement {
|
||||||
f.asm_arg(base)
|
f.asm_arg(base)
|
||||||
f.write(' + $displacement')
|
f.write(' + ')
|
||||||
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.index_times_scale_plus_displacement {
|
.index_times_scale_plus_displacement {
|
||||||
f.asm_arg(index)
|
f.asm_arg(index)
|
||||||
f.write(' * $scale + $displacement')
|
f.write(' * $scale + ')
|
||||||
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.base_plus_index_plus_displacement {
|
.base_plus_index_plus_displacement {
|
||||||
f.asm_arg(base)
|
f.asm_arg(base)
|
||||||
f.write(' + ')
|
f.write(' + ')
|
||||||
f.asm_arg(index)
|
f.asm_arg(index)
|
||||||
f.write(' + $displacement')
|
f.write(' + ')
|
||||||
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.base_plus_index_times_scale_plus_displacement {
|
.base_plus_index_times_scale_plus_displacement {
|
||||||
f.asm_arg(base)
|
f.asm_arg(base)
|
||||||
f.write(' + ')
|
f.write(' + ')
|
||||||
f.asm_arg(index)
|
f.asm_arg(index)
|
||||||
f.write(' * $scale + $displacement')
|
f.write(' * $scale + ')
|
||||||
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.rip_plus_displacement {
|
.rip_plus_displacement {
|
||||||
f.asm_arg(base)
|
f.asm_arg(base)
|
||||||
f.write(' + $displacement')
|
f.write(' + ')
|
||||||
|
f.asm_arg(displacement)
|
||||||
}
|
}
|
||||||
.invalid {
|
.invalid {
|
||||||
panic('fmt: invalid addressing mode')
|
panic('fmt: invalid addressing mode')
|
||||||
|
@ -782,6 +787,9 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) {
|
||||||
}
|
}
|
||||||
f.write(']')
|
f.write(']')
|
||||||
}
|
}
|
||||||
|
ast.AsmDisp {
|
||||||
|
f.write(arg.val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1861,12 +1861,9 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
|
||||||
match arg {
|
match arg {
|
||||||
ast.AsmAlias {
|
ast.AsmAlias {
|
||||||
name := arg.name
|
name := arg.name
|
||||||
if name in stmt.local_labels || name in stmt.global_labels {
|
if name in stmt.local_labels || name in stmt.global_labels
|
||||||
asm_formatted_name := if name in stmt.local_labels {
|
|| name in g.file.global_labels {
|
||||||
name
|
asm_formatted_name := if name in stmt.global_labels { '%l[$name]' } else { name }
|
||||||
} else { // val in stmt.global_labels
|
|
||||||
'%l[$name]'
|
|
||||||
}
|
|
||||||
g.write(asm_formatted_name)
|
g.write(asm_formatted_name)
|
||||||
} else {
|
} else {
|
||||||
g.write('%[$name]')
|
g.write('%[$name]')
|
||||||
|
@ -1896,43 +1893,53 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
|
||||||
.base {
|
.base {
|
||||||
g.write('(')
|
g.write('(')
|
||||||
g.asm_arg(base, stmt)
|
g.asm_arg(base, stmt)
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
.displacement {
|
.displacement {
|
||||||
g.write('${displacement}(')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('()')
|
||||||
}
|
}
|
||||||
.base_plus_displacement {
|
.base_plus_displacement {
|
||||||
g.write('${displacement}(')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('(')
|
||||||
g.asm_arg(base, stmt)
|
g.asm_arg(base, stmt)
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
.index_times_scale_plus_displacement {
|
.index_times_scale_plus_displacement {
|
||||||
g.write('${displacement}(,')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('(')
|
||||||
g.asm_arg(index, stmt)
|
g.asm_arg(index, stmt)
|
||||||
g.write(',')
|
g.write(',$scale)')
|
||||||
g.write(scale.str())
|
|
||||||
}
|
}
|
||||||
.base_plus_index_plus_displacement {
|
.base_plus_index_plus_displacement {
|
||||||
g.write('${displacement}(')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('(')
|
||||||
g.asm_arg(base, stmt)
|
g.asm_arg(base, stmt)
|
||||||
g.write(',')
|
g.write(',')
|
||||||
g.asm_arg(index, stmt)
|
g.asm_arg(index, stmt)
|
||||||
g.write(',1')
|
g.write(',1)')
|
||||||
}
|
}
|
||||||
.base_plus_index_times_scale_plus_displacement {
|
.base_plus_index_times_scale_plus_displacement {
|
||||||
g.write('${displacement}(')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('(')
|
||||||
g.asm_arg(base, stmt)
|
g.asm_arg(base, stmt)
|
||||||
g.write(',')
|
g.write(',')
|
||||||
g.asm_arg(index, stmt)
|
g.asm_arg(index, stmt)
|
||||||
g.write(',$scale')
|
g.write(',$scale)')
|
||||||
}
|
}
|
||||||
.rip_plus_displacement {
|
.rip_plus_displacement {
|
||||||
g.write('${displacement}(')
|
g.asm_arg(displacement, stmt)
|
||||||
|
g.write('(')
|
||||||
g.asm_arg(base, stmt)
|
g.asm_arg(base, stmt)
|
||||||
|
g.write(')')
|
||||||
}
|
}
|
||||||
.invalid {
|
.invalid {
|
||||||
g.error('invalid addressing mode', arg.pos)
|
g.error('invalid addressing mode', arg.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write(')')
|
}
|
||||||
|
ast.AsmDisp {
|
||||||
|
g.write(arg.val)
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
g.write('$arg')
|
g.write('$arg')
|
||||||
|
@ -1945,7 +1952,9 @@ fn (mut g Gen) gen_asm_ios(ios []ast.AsmIO) {
|
||||||
if io.alias != '' {
|
if io.alias != '' {
|
||||||
g.write('[$io.alias] ')
|
g.write('[$io.alias] ')
|
||||||
}
|
}
|
||||||
g.write('"$io.constraint" ($io.expr)')
|
g.write('"$io.constraint" (')
|
||||||
|
g.expr(io.expr)
|
||||||
|
g.write(')')
|
||||||
if i + 1 < ios.len {
|
if i + 1 < ios.len {
|
||||||
g.writeln(',')
|
g.writeln(',')
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -73,6 +73,7 @@ mut:
|
||||||
n_asm int // controls assembly labels
|
n_asm int // controls assembly labels
|
||||||
inside_asm_template bool
|
inside_asm_template bool
|
||||||
inside_asm bool
|
inside_asm bool
|
||||||
|
global_labels []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
|
@ -281,6 +282,7 @@ pub fn (mut p Parser) parse() ast.File {
|
||||||
global_scope: p.global_scope
|
global_scope: p.global_scope
|
||||||
errors: p.errors
|
errors: p.errors
|
||||||
warnings: p.warnings
|
warnings: p.warnings
|
||||||
|
global_labels: p.global_labels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,7 +878,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
}
|
}
|
||||||
|
|
||||||
mut local_labels := []string{}
|
mut local_labels := []string{}
|
||||||
mut exported_symbols := []string{}
|
|
||||||
// riscv: https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf
|
// riscv: https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf
|
||||||
// x86: https://www.felixcloutier.com/x86/
|
// x86: https://www.felixcloutier.com/x86/
|
||||||
// arm: https://developer.arm.com/documentation/dui0068/b/arm-instruction-reference
|
// arm: https://developer.arm.com/documentation/dui0068/b/arm-instruction-reference
|
||||||
|
@ -921,8 +922,15 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
args << ast.IntegerLiteral{
|
if is_directive {
|
||||||
...number_lit
|
args << ast.AsmDisp{
|
||||||
|
val: number_lit.val
|
||||||
|
pos: number_lit.pos
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args << ast.IntegerLiteral{
|
||||||
|
...number_lit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -967,7 +975,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
comments << p.comment()
|
comments << p.comment()
|
||||||
}
|
}
|
||||||
if is_directive && name in ['globl', 'global'] {
|
if is_directive && name in ['globl', 'global'] {
|
||||||
exported_symbols << args
|
for arg in args {
|
||||||
|
p.global_labels << (arg as ast.AsmAlias).name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
templates << ast.AsmTemplate{
|
templates << ast.AsmTemplate{
|
||||||
name: name
|
name: name
|
||||||
|
@ -1045,7 +1055,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
|
||||||
scope: scope
|
scope: scope
|
||||||
global_labels: global_labels
|
global_labels: global_labels
|
||||||
local_labels: local_labels
|
local_labels: local_labels
|
||||||
exported_symbols: exported_symbols
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1058,7 +1067,8 @@ fn (mut p Parser) reg_or_alias() ast.AsmArg {
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
return b
|
return b
|
||||||
} else {
|
} else {
|
||||||
panic('parser bug: non-register ast.ScopeObject found in scope')
|
verror('parser bug: non-register ast.ScopeObject found in scope')
|
||||||
|
return ast.AsmDisp{} // should not be reached
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
|
@ -1173,8 +1183,15 @@ 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 == .number {
|
} else if p.tok.kind == .number {
|
||||||
displacement := p.tok.lit.u32()
|
displacement := if p.tok.kind == .name {
|
||||||
p.check(.name)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.number)
|
||||||
|
x
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .displacement
|
mode: .displacement
|
||||||
|
@ -1187,13 +1204,22 @@ 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' {
|
||||||
p.check(.name)
|
rip := p.reg_or_alias()
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := p.tok.lit.u32()
|
|
||||||
p.check(.number)
|
displacement := if p.tok.kind == .name {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.number)
|
||||||
|
x
|
||||||
|
}
|
||||||
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .rip_plus_displacement
|
mode: .rip_plus_displacement
|
||||||
base: 'rip'
|
base: rip
|
||||||
displacement: displacement
|
displacement: displacement
|
||||||
pos: pos.extend(p.prev_tok.position())
|
pos: pos.extend(p.prev_tok.position())
|
||||||
}
|
}
|
||||||
|
@ -1202,8 +1228,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
if p.peek_tok.kind == .rsbr {
|
if p.peek_tok.kind == .rsbr {
|
||||||
if p.tok.kind == .number {
|
if p.tok.kind == .number {
|
||||||
displacement := p.tok.lit.u32()
|
displacement := if p.tok.kind == .name {
|
||||||
p.check(.number)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .base_plus_displacement
|
mode: .base_plus_displacement
|
||||||
|
@ -1221,8 +1254,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
scale := p.tok.lit.int()
|
scale := p.tok.lit.int()
|
||||||
p.check(.number)
|
p.check(.number)
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := p.tok.lit.u32()
|
displacement := if p.tok.kind == .name {
|
||||||
p.check(.number)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.number)
|
||||||
|
x
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .base_plus_index_times_scale_plus_displacement
|
mode: .base_plus_index_times_scale_plus_displacement
|
||||||
|
@ -1234,8 +1274,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
}
|
}
|
||||||
} else if p.tok.kind == .plus {
|
} else if p.tok.kind == .plus {
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := p.tok.lit.u32()
|
displacement := if p.tok.kind == .name {
|
||||||
p.check(.number)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.number)
|
||||||
|
x
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .base_plus_index_plus_displacement
|
mode: .base_plus_index_plus_displacement
|
||||||
|
@ -1252,8 +1299,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
|
||||||
scale := p.tok.lit.int()
|
scale := p.tok.lit.int()
|
||||||
p.check(.number)
|
p.check(.number)
|
||||||
p.check(.plus)
|
p.check(.plus)
|
||||||
displacement := p.tok.lit.u32()
|
displacement := if p.tok.kind == .name {
|
||||||
p.check(.number)
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.name)
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
x := ast.AsmArg(p.tok.lit)
|
||||||
|
p.check(.number)
|
||||||
|
x
|
||||||
|
}
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.AsmAddressing{
|
return ast.AsmAddressing{
|
||||||
mode: .index_times_scale_plus_displacement
|
mode: .index_times_scale_plus_displacement
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import v.tests.assembly.util
|
import v.tests.assembly.util
|
||||||
|
|
||||||
fn test_inline_asm() {
|
fn test_inline_asm() {
|
||||||
a, mut b := 10, 0
|
a, mut b := i64(10), i64(0)
|
||||||
asm amd64 {
|
asm amd64 {
|
||||||
mov rax, a
|
mov rax, a
|
||||||
mov b, rax
|
mov b, rax
|
||||||
|
@ -97,3 +97,26 @@ fn test_inline_asm() {
|
||||||
|
|
||||||
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v files
|
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
|
||||||
|
fn test_rip_relative_label() {
|
||||||
|
mut a := i64(4)
|
||||||
|
asm amd64 {
|
||||||
|
mov a, [rip + one_two_three] // see below
|
||||||
|
; =r (a)
|
||||||
|
}
|
||||||
|
assert a == 48321074923
|
||||||
|
|
||||||
|
mut b := i64(4)
|
||||||
|
asm amd64 {
|
||||||
|
mov b, one_two_three // see below
|
||||||
|
; =r (b)
|
||||||
|
}
|
||||||
|
assert b == 48321074923
|
||||||
|
}
|
||||||
|
|
||||||
|
asm amd64 {
|
||||||
|
.global one_two_three
|
||||||
|
one_two_three:
|
||||||
|
.quad 48321074923
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue