Skip to content

Commit

Permalink
v: parser: rv64: asm: Support for base+displacement addressing
Browse files Browse the repository at this point in the history
  • Loading branch information
raw-bin committed Jul 5, 2024
1 parent daa3a8a commit a9ad85b
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 3 deletions.
15 changes: 15 additions & 0 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,7 @@ pub mut:

// [eax+5] | j | displacement literal (e.g. 123 in [rax + 123] ) | eax | true | `a` | 0.594 | 123 | label_name
pub type AsmArg = AsmAddressing
| AsmAddressingRV64
| AsmAlias
| AsmDisp
| AsmRegister
Expand Down Expand Up @@ -1638,6 +1639,15 @@ pub mut:
index AsmArg // gpr
}

pub struct AsmAddressingRV64 {
pub:
mode AddressingModeRV64
pos token.Pos
pub mut:
displacement AsmArg // 8, 16 or 32 bit literal value
base AsmArg // gpr
}

// addressing modes:
pub enum AddressingMode {
invalid
Expand All @@ -1650,6 +1660,11 @@ pub enum AddressingMode {
rip_plus_displacement // rip + displacement
}

pub enum AddressingModeRV64 {
invalid
base_plus_displacement // base + displacement
}

pub struct AsmClobbered {
pub mut:
reg AsmRegister
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -2342,6 +2342,10 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) {
c.asm_arg(arg.base, stmt, aliases)
c.asm_arg(arg.index, stmt, aliases)
}
ast.AsmAddressingRV64 {
c.asm_arg(arg.displacement, stmt, aliases)
c.asm_arg(arg.base, stmt, aliases)
}
ast.BoolLiteral {} // all of these are guaranteed to be correct.
ast.FloatLiteral {}
ast.CharLiteral {}
Expand Down
8 changes: 8 additions & 0 deletions vlib/v/fmt/asm.v
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) {
string {
f.string_literal(ast.StringLiteral{ val: arg })
}
ast.AsmAddressingRV64 {
base := arg.base
displacement := arg.displacement
f.asm_arg(displacement)
f.write('(')
f.asm_arg(base)
f.write(')')
}
ast.AsmAddressing {
if arg.segment != '' {
f.write(arg.segment)
Expand Down
15 changes: 15 additions & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,21 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
}
}
}
ast.AsmAddressingRV64 {
base := arg.base
displacement := arg.displacement
match arg.mode {
.base_plus_displacement {
g.asm_arg(displacement, stmt)
g.write('(')
g.asm_arg(base, stmt)
g.write(')')
}
.invalid {
g.error('invalid addressing mode', arg.pos)
}
}
}
ast.AsmDisp {
g.write(arg.val)
}
Expand Down
100 changes: 97 additions & 3 deletions vlib/v/parser/parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
args << p.tok.lit
p.next()
}
.number {
.number, .minus {
number_lit := p.parse_number_literal()
match number_lit {
ast.FloatLiteral {
Expand All @@ -1273,8 +1273,12 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
pos: number_lit.pos
}
} else {
args << ast.IntegerLiteral{
...number_lit
if p.tok.kind == .lpar {
args << p.asm_addressing_rv64(RV64Displacement.int_as_base_no_pars, number_lit.val)
} else {
args << ast.IntegerLiteral{
...number_lit
}
}
}
}
Expand Down Expand Up @@ -1310,6 +1314,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
.semicolon {
break
}
.lpar {
args << p.asm_addressing_rv64(RV64Displacement.int_as_base_pars, none)
}
else {
p.error('invalid token in assembly block')
}
Expand Down Expand Up @@ -1527,6 +1534,93 @@ fn (mut p Parser) reg_or_alias() ast.AsmArg {
// }
// }

enum RV64Displacement {
int_as_base_no_pars
int_as_base_pars
}

fn (mut p Parser) asm_addressing_rv64(disp_type RV64Displacement, disp_val ?string) ast.AsmAddressingRV64 {
base, displacement := match disp_type {
.int_as_base_no_pars {
p.check(.lpar)
displacement := ast.AsmArg(ast.AsmDisp {
val: disp_val or { verror("Expected displacement string") }
pos: p.tok.pos()
})
base := p.reg_or_alias()
p.check(.rpar)
base, displacement
}
.int_as_base_pars {
p.check(.lpar)
first_number_lit := p.parse_number_literal()
first_number := match first_number_lit {
ast.IntegerLiteral {
ast.IntegerLiteral { ...first_number_lit }
}
else {
verror("Expected displacement integer")
}
}
match p.tok.kind {
.lpar {
p.next()
base := p.reg_or_alias()
p.check(.rpar)
displacement := ast.AsmArg(ast.AsmDisp {
val: '(' + first_number.val + ')'
pos: first_number.pos
})
base, displacement
}
.rpar {
displacement := ast.AsmArg(ast.AsmDisp {
val: '(' + first_number.val + ')'
pos: first_number.pos
})
p.next()
p.check(.lpar)
base := p.reg_or_alias()
p.check(.rpar)
base, displacement
}
.mul, .plus, .minus {
operator := p.tok.kind.str()
p.next()
second_number_lit := p.parse_number_literal()
second_number := match second_number_lit {
ast.IntegerLiteral {
ast.IntegerLiteral { ...second_number_lit }
}
else {
verror("Expected displacement integer")
}
}
displacement := ast.AsmArg(ast.AsmDisp {
val: '(' + first_number.val + ' ' + operator + ' ' + second_number.val + ')'
pos: second_number.pos
})
p.check(.rpar)
p.check(.lpar)
base := p.reg_or_alias()
p.check(.rpar)
base, displacement
}
else {
verror("Unsupported or invalid RV64 inline assembly")
}
}
}
}
pos := p.tok.pos()
return ast.AsmAddressingRV64{
mode: .base_plus_displacement
displacement: displacement
base: base
pos: pos.extend(p.prev_tok.pos())
}
}

fn (mut p Parser) asm_addressing() ast.AsmAddressing {
pos := p.tok.pos()
p.check(.lsbr)
Expand Down

0 comments on commit a9ad85b

Please sign in to comment.