native: better raw output and more arm64 cleanup
parent
9a3869c521
commit
9b07278930
|
@ -223,7 +223,7 @@ fn (mut g Gen) call(addr int) {
|
|||
// println('call addr=$addr.hex2() rel_addr=$rel.hex2() pos=$g.buf.len')
|
||||
g.write8(0xe8)
|
||||
g.write32(rel)
|
||||
// g.println('fn call')
|
||||
g.println('call $addr')
|
||||
}
|
||||
|
||||
fn (mut g Gen) syscall() {
|
||||
|
@ -589,6 +589,10 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
||||
if g.pref.arch == .arm64 {
|
||||
g.fn_decl_arm64(node)
|
||||
return
|
||||
}
|
||||
if g.pref.is_verbose {
|
||||
println(term.green('\n$node.name:'))
|
||||
}
|
||||
|
|
|
@ -1,11 +1,102 @@
|
|||
module native
|
||||
|
||||
pub struct Aarch64 {
|
||||
import v.ast
|
||||
|
||||
enum Arm64Register {
|
||||
x0
|
||||
x1
|
||||
x2
|
||||
x3
|
||||
x4
|
||||
x5
|
||||
x6
|
||||
x7
|
||||
x8
|
||||
x9
|
||||
x10
|
||||
x11
|
||||
x12
|
||||
x13
|
||||
x14
|
||||
x15
|
||||
x16
|
||||
}
|
||||
|
||||
pub struct Arm64 {
|
||||
mut:
|
||||
// arm64 specific stuff for code generation
|
||||
g Gen
|
||||
}
|
||||
|
||||
pub fn (mut x Aarch64) allocate_var(name string, size int, initial_val int) {
|
||||
pub fn (mut x Arm64) allocate_var(name string, size int, initial_val int) {
|
||||
eprintln('TODO: allocating var on arm64 ($name) = $size = $initial_val')
|
||||
}
|
||||
|
||||
fn (mut g Gen) mov_arm(reg Arm64Register, val u64) {
|
||||
// m := u64(0xffff)
|
||||
// x := u64(val)
|
||||
// println('========')
|
||||
// println(x & ~m)
|
||||
// println(x & ~(m << 16))
|
||||
// g.write32(0x777777)
|
||||
r := int(reg)
|
||||
if r == 0 && val == 1 {
|
||||
g.write32(0xd2800020)
|
||||
g.println('mov x0, 1')
|
||||
} else if r == 0 {
|
||||
g.write32(0xd2800000)
|
||||
g.println('mov x0, 0')
|
||||
} else if r == 16 {
|
||||
g.write32(0xd2800030)
|
||||
g.println('mov x16, 1')
|
||||
}
|
||||
/*
|
||||
if 1 ^ (x & ~m) != 0 {
|
||||
// println('yep')
|
||||
g.write32(int(u64(0x52800000) | u64(r) | x << 5))
|
||||
g.write32(0x88888888)
|
||||
g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||
} else if 1 ^ (x & ~(m << 16)) != 0 {
|
||||
// g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||
// println('yep2')
|
||||
// g.write32(0x52a00000 | r | val >> 11)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) fn_decl_arm64(node ast.FnDecl) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_arm64_helloworld() {
|
||||
// ADD THE CODE HERE THIS GOES INTO THE STMTS THING
|
||||
// g.write32(0x77777777)
|
||||
// assembly
|
||||
g.mov_arm(.x0, 1)
|
||||
g.adr()
|
||||
g.bl()
|
||||
g.mov_arm(.x0, 0)
|
||||
g.mov_arm(.x16, 1)
|
||||
g.svc()
|
||||
//
|
||||
g.write_string('Hello World!\n')
|
||||
g.write8(0) // padding?
|
||||
g.write8(0)
|
||||
g.write8(0)
|
||||
}
|
||||
|
||||
fn (mut g Gen) adr() {
|
||||
g.write32(0x100000a0)
|
||||
g.println('adr x0, 0x14')
|
||||
}
|
||||
|
||||
fn (mut g Gen) bl() {
|
||||
// g.write32(0xa9400000)
|
||||
g.write32(0x94000000)
|
||||
g.println('bl 0')
|
||||
}
|
||||
|
||||
fn (mut g Gen) svc() {
|
||||
g.write32(0xd4001001)
|
||||
g.println('svc')
|
||||
}
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module native
|
||||
|
||||
import os
|
||||
|
||||
const (
|
||||
mag0 = byte(0x7f)
|
||||
mag1 = `E`
|
||||
|
@ -72,11 +70,13 @@ pub fn (mut g Gen) generate_elf_header() {
|
|||
g.write64(0x1000) // p_align
|
||||
// user code starts here at
|
||||
// address: 00070 and a half
|
||||
println('code_start_pos = $g.buf.len.hex()')
|
||||
if g.pref.is_verbose {
|
||||
eprintln('code_start_pos = $g.buf.len.hex()')
|
||||
}
|
||||
g.code_start_pos = i64(g.buf.len)
|
||||
g.debug_pos = g.buf.len
|
||||
g.call(native.placeholder) // call main function, it's not guaranteed to be the first, we don't know its address yet
|
||||
g.println('call fn main')
|
||||
g.println('; call fn main')
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) generate_elf_footer() {
|
||||
|
@ -103,12 +103,5 @@ pub fn (mut g Gen) generate_elf_footer() {
|
|||
// +1 is for "e8"
|
||||
// -5 is for "e8 00 00 00 00"
|
||||
g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5)
|
||||
// Create the binary
|
||||
mut f := os.create(g.out_name) or { panic(err) }
|
||||
os.chmod(g.out_name, 0o775) // make it an executable
|
||||
unsafe { f.write_ptr(g.buf.data, g.buf.len) }
|
||||
f.close()
|
||||
if g.pref.is_verbose {
|
||||
println('\nnative elf binary has been successfully generated')
|
||||
}
|
||||
g.create_executable()
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module native
|
||||
|
||||
import os
|
||||
import v.ast
|
||||
import v.util
|
||||
import v.token
|
||||
|
@ -49,7 +50,7 @@ enum Size {
|
|||
|
||||
fn (g Gen) get_backend(pref &pref.Preferences) CodeGen {
|
||||
if pref.arch == .arm64 {
|
||||
return Aarch64{}
|
||||
return Arm64{}
|
||||
}
|
||||
return Amd64{}
|
||||
}
|
||||
|
@ -86,13 +87,28 @@ pub fn (mut g Gen) generate_header() {
|
|||
.linux {
|
||||
g.generate_elf_header()
|
||||
}
|
||||
.raw {}
|
||||
.raw {
|
||||
if g.pref.arch == .arm64 {
|
||||
g.gen_arm64_helloworld()
|
||||
}
|
||||
}
|
||||
else {
|
||||
verror('Error: only `raw`, `linux` and `macos` are supported for -os in -native')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) create_executable() {
|
||||
// Create the binary // should be .o ?
|
||||
mut f := os.create(g.out_name) or { panic(err) }
|
||||
os.chmod(g.out_name, 0o775) // make it executable
|
||||
unsafe { f.write_ptr(g.buf.data, g.buf.len) }
|
||||
f.close()
|
||||
if g.pref.is_verbose {
|
||||
println('\narm64 mach-o binary has been successfully generated')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) generate_footer() {
|
||||
match g.pref.os {
|
||||
.macos {
|
||||
|
@ -101,9 +117,10 @@ pub fn (mut g Gen) generate_footer() {
|
|||
.linux {
|
||||
g.generate_elf_footer()
|
||||
}
|
||||
else {
|
||||
g.generate_macho_footer()
|
||||
.raw {
|
||||
g.create_executable()
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,7 +238,7 @@ pub fn (mut g Gen) register_function_address(name string) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
|
||||
eprintln('for-in statement is not yet implemented')
|
||||
verror('for-in statement is not yet implemented')
|
||||
/*
|
||||
if node.is_range {
|
||||
// `for x in 1..10 {`
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module native
|
||||
|
||||
import os
|
||||
|
||||
const (
|
||||
s_attr_some_instructions = 0x00000400
|
||||
s_attr_pure_instructions = 0x80000000
|
||||
|
@ -99,33 +97,19 @@ pub fn (mut g Gen) generate_macho_header() {
|
|||
for _ in 0 .. 12 {
|
||||
g.write32(0)
|
||||
}
|
||||
// ADD THE CODE HERE THIS GOES INTO THE STMTS THING
|
||||
// g.write32(0x77777777)
|
||||
// assembly
|
||||
g.mov_arm(.x0, 1)
|
||||
g.adr()
|
||||
g.bl()
|
||||
g.mov_arm(.x0, 0)
|
||||
g.mov_arm(.x16, 1)
|
||||
g.svc()
|
||||
//
|
||||
g.write_string('Hello World!\n')
|
||||
g.write8(0) // padding?
|
||||
g.write8(0)
|
||||
g.write8(0)
|
||||
|
||||
if g.pref.arch == .arm64 {
|
||||
g.gen_arm64_helloworld()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) generate_macho_footer() {
|
||||
g.write_relocs()
|
||||
g.sym_table()
|
||||
g.sym_string_table()
|
||||
g.write8(0)
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) generate_macho_footer() {
|
||||
// Create the binary // should be .o ?
|
||||
mut f := os.create(g.out_name) or { panic(err) }
|
||||
os.chmod(g.out_name, 0o775) // make it executable
|
||||
unsafe { f.write_ptr(g.buf.data, g.buf.len) }
|
||||
f.close()
|
||||
// println('\narm64 mach-o binary has been successfully generated')
|
||||
g.create_executable()
|
||||
}
|
||||
|
||||
fn (mut g Gen) sym_table_command() {
|
||||
|
@ -184,68 +168,6 @@ pub fn (mut g Gen) zeroes(n int) {
|
|||
}
|
||||
}
|
||||
|
||||
enum Register2 {
|
||||
x0
|
||||
x1
|
||||
x2
|
||||
x3
|
||||
x4
|
||||
x5
|
||||
x6
|
||||
x7
|
||||
x8
|
||||
x9
|
||||
x10
|
||||
x11
|
||||
x12
|
||||
x13
|
||||
x14
|
||||
x15
|
||||
x16
|
||||
}
|
||||
|
||||
fn (mut g Gen) mov_arm(reg Register2, val u64) {
|
||||
// m := u64(0xffff)
|
||||
// x := u64(val)
|
||||
// println('========')
|
||||
// println(x & ~m)
|
||||
// println(x & ~(m << 16))
|
||||
// g.write32(0x777777)
|
||||
r := int(reg)
|
||||
if r == 0 && val == 1 {
|
||||
g.write32(0xd2800020)
|
||||
} else if r == 0 {
|
||||
g.write32(0xd2800000)
|
||||
} else if r == 16 {
|
||||
g.write32(0xd2800030)
|
||||
}
|
||||
/*
|
||||
if 1 ^ (x & ~m) != 0 {
|
||||
// println('yep')
|
||||
g.write32(int(u64(0x52800000) | u64(r) | x << 5))
|
||||
g.write32(0x88888888)
|
||||
g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||
} else if 1 ^ (x & ~(m << 16)) != 0 {
|
||||
// g.write32(int(u64(0x52800000) | u64(r) | x >> 11))
|
||||
// println('yep2')
|
||||
// g.write32(0x52a00000 | r | val >> 11)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn (mut g Gen) adr() {
|
||||
g.write32(0x100000a0)
|
||||
}
|
||||
|
||||
fn (mut g Gen) bl() {
|
||||
// g.write32(0xa9400000)
|
||||
g.write32(0x94000000)
|
||||
}
|
||||
|
||||
fn (mut g Gen) svc() {
|
||||
g.write32(0xd4001001)
|
||||
}
|
||||
|
||||
fn (mut g Gen) write_relocs() {
|
||||
g.write32(0x8)
|
||||
g.write32(0x2d000003)
|
||||
|
|
Loading…
Reference in New Issue