v.gen.native: initial support for the asm statement in the native backend (#11292)

pull/11295/head
pancake 2021-08-24 14:30:41 +02:00 committed by GitHub
parent 57b148032f
commit 3c85a03b8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 0 deletions

View File

@ -37,6 +37,7 @@ enum Register {
const (
fn_arg_registers = [Register.rdi, .rsi, .rdx, .rcx, .r8, .r9]
amd64_cpuregs = ['eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi']
)
fn (mut g Gen) dec(reg Register) {
@ -53,6 +54,11 @@ fn (mut g Gen) dec(reg Register) {
g.println('dec $reg')
}
[inline]
fn byt(n int, s int) byte {
return byte((n >> (s * 8)) & 0xff)
}
fn (mut g Gen) inc(reg Register) {
g.write16(0xff49)
match reg {
@ -1038,6 +1044,109 @@ fn (mut g Gen) trap() {
g.println('trap')
}
fn (mut g Gen) gen_asm_stmt(asm_node ast.AsmStmt) {
if g.pref.arch == .arm64 {
g.gen_asm_stmt_arm64(asm_node)
} else {
g.gen_asm_stmt_amd64(asm_node)
}
}
fn (mut g Gen) gen_asm_stmt_amd64(asm_node ast.AsmStmt) {
// inline assembly using vasm
g.println('// asm inline')
mut reg := 0
mut imm := 0
mut regname := ''
// dump(asm_node)
for t in asm_node.templates {
mut line := t.name
mut comma := false
for a in t.args {
if comma {
line += ', '
} else {
comma = true
}
match a {
ast.AsmRegister {
regname = a.name
reg = native.amd64_cpuregs.index(regname)
line += a.typ.str()
}
ast.IntegerLiteral {
line += a.val
imm = a.val.int()
}
ast.BoolLiteral {
line += a.val.str()
imm = if a.val { 1 } else { 0 }
}
/*
ast.AsmAddressing {
}
ast.AsmAlias {
}
ast.AsmDisp {
}
ast.CharLiteral {
}
ast.FloatLiteral {
}
*/
string {
// XXX
g.v_error('no strings allowed in this context', asm_node.pos)
}
else {
g.v_error('unsupported instruction argument argument', asm_node.pos)
}
}
}
g.println(': $line')
match t.name {
'nop' {
g.write8(byte(0x90))
}
'syscall' {
g.write8(byte(0x0f))
g.write8(byte(0x05))
}
'ret' {
g.write8(byte(0xc3))
}
'int3' {
g.write8(byte(0xcc))
g.write8(byte(imm))
}
'sti' {
g.write8(byte(0xfb))
}
'cli' {
g.write8(byte(0xfa))
}
'int' {
g.write8(byte(0xcd))
g.write8(byte(imm))
}
'cpuid' {
g.write8(byte(0x0f))
g.write8(byte(0xa2))
}
'mov' {
g.write8(byte(0xb8 + reg))
g.write8(byt(imm, 0))
g.write8(byt(imm, 1))
g.write8(byt(imm, 2))
g.write8(byt(imm, 3))
}
else {
g.v_error('unsupported instruction $t.name', asm_node.pos)
}
}
}
}
fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
mut cjmp_addr := 0
mut ine := ast.InfixExpr{}

View File

@ -197,3 +197,7 @@ pub fn (mut g Gen) gen_arm64_exit(expr ast.Expr) {
g.mov_arm(.x0, 0)
g.svc()
}
fn (mut g Gen) gen_asm_stmt_arm64(asm_node ast.AsmStmt) {
g.v_error('The asm statement for arm64 not yet implemented', asm_node.pos)
}

View File

@ -380,6 +380,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
g.pop(.rbp)
g.ret()
}
ast.AsmStmt {
g.gen_asm_stmt(node)
}
ast.AssertStmt {
g.gen_assert(node)
}

View File

@ -0,0 +1,10 @@
fn asm_test() {
asm amd64 {
nop
}
println('inline works')
}
fn main() {
asm_test()
}

View File

@ -0,0 +1 @@
inline works