x64: fix off by one error in for loops

pull/2924/head
Alexander Medvednikov 2019-11-29 12:33:04 +03:00
parent 39bc38233a
commit 431568faad
2 changed files with 26 additions and 26 deletions

View File

@ -1,6 +1,6 @@
fn test_fn() { fn test_fn() {
println('test fn') println('test fn')
} }
fn main() { fn main() {
println('x64 test') println('x64 test')
@ -8,7 +8,7 @@ fn main() {
println('Hello world from V x64 machine code generator!') println('Hello world from V x64 machine code generator!')
} }
println('Hello again!') println('Hello again!')
test_fn() //test_fn()
println('dne') println('done')
} }

View File

@ -17,7 +17,7 @@ mut:
code_start_pos i64 // location of the start of the assembly instructions code_start_pos i64 // location of the start of the assembly instructions
fn_addr map[string]i64 fn_addr map[string]i64
//string_addr map[string]i64 //string_addr map[string]i64
} }
enum Register { enum Register {
eax eax
@ -35,31 +35,31 @@ enum Size {
_16 _16
_32 _32
_64 _64
} }
pub fn new_gen(out_name string) &Gen { pub fn new_gen(out_name string) &Gen {
return &Gen{ return &Gen{
sect_header_name_pos : 0 sect_header_name_pos : 0
buf: [] buf: []
out_name: out_name out_name: out_name
} }
} }
pub fn (g &Gen) pos() i64 { pub fn (g &Gen) pos() i64 {
return g.buf.len return g.buf.len
} }
fn (g mut Gen) write8(n int) { fn (g mut Gen) write8(n int) {
// write 1 byte // write 1 byte
g.buf << byte(n) g.buf << byte(n)
} }
fn (g mut Gen) write16(n int) { fn (g mut Gen) write16(n int) {
// write 2 bytes // write 2 bytes
g.buf << byte(n) g.buf << byte(n)
g.buf << byte(n >> 8) g.buf << byte(n >> 8)
} }
fn (g mut Gen) write32(n int) { fn (g mut Gen) write32(n int) {
// write 4 bytes // write 4 bytes
@ -67,7 +67,7 @@ fn (g mut Gen) write32(n int) {
g.buf << byte(n >> 8) g.buf << byte(n >> 8)
g.buf << byte(n >> 16) g.buf << byte(n >> 16)
g.buf << byte(n >> 24) g.buf << byte(n >> 24)
} }
fn (g mut Gen) write64(n i64) { fn (g mut Gen) write64(n i64) {
// write 8 bytes // write 8 bytes
@ -79,7 +79,7 @@ fn (g mut Gen) write64(n i64) {
g.buf << byte(n >> 40) g.buf << byte(n >> 40)
g.buf << byte(n >> 48) g.buf << byte(n >> 48)
g.buf << byte(n >> 56) g.buf << byte(n >> 56)
} }
fn (g mut Gen) write64_at(n i64, at i64) { fn (g mut Gen) write64_at(n i64, at i64) {
// write 8 bytes // write 8 bytes
@ -91,12 +91,12 @@ fn (g mut Gen) write64_at(n i64, at i64) {
g.buf[at+5] = byte(n >> 40) g.buf[at+5] = byte(n >> 40)
g.buf[at+6] = byte(n >> 48) g.buf[at+6] = byte(n >> 48)
g.buf[at+7] = byte(n >> 56) g.buf[at+7] = byte(n >> 56)
} }
fn (g mut Gen) write_string(s string) { fn (g mut Gen) write_string(s string) {
for c in s { for c in s {
g.write8(int(c)) g.write8(int(c))
} }
} }
fn (g mut Gen) inc(reg Register) { fn (g mut Gen) inc(reg Register) {
@ -104,8 +104,8 @@ fn (g mut Gen) inc(reg Register) {
match reg { match reg {
.r12 { g.write8(0xc4) } .r12 { g.write8(0xc4) }
else { panic('unhandled inc $reg') } else { panic('unhandled inc $reg') }
} }
} }
fn (g mut Gen) cmp(reg Register, size Size, val i64) { fn (g mut Gen) cmp(reg Register, size Size, val i64) {
g.write8(0x49) g.write8(0x49)
@ -114,12 +114,12 @@ fn (g mut Gen) cmp(reg Register, size Size, val i64) {
._8 { g.write8(0x83) } ._8 { g.write8(0x83) }
._32 { g.write8(0x81) } ._32 { g.write8(0x81) }
else { panic('unhandled cmp') } else { panic('unhandled cmp') }
} }
// Third byte depends on the register being compared to // Third byte depends on the register being compared to
match reg { match reg {
.r12 { g.write8(0xfc) } .r12 { g.write8(0xfc) }
else { panic('unhandled cmp') } else { panic('unhandled cmp') }
} }
g.write8(int(val)) g.write8(int(val))
} }
@ -141,7 +141,7 @@ fn (g mut Gen) jl(addr i64) {
fn (g &Gen) abs_to_rel_addr(addr i64) int { fn (g &Gen) abs_to_rel_addr(addr i64) int {
return int(abs(addr - g.buf.len))-1 return int(abs(addr - g.buf.len))-1
} }
fn (g mut Gen) jmp (addr i64) { fn (g mut Gen) jmp (addr i64) {
offset := 0xff - g.abs_to_rel_addr(addr) offset := 0xff - g.abs_to_rel_addr(addr)
@ -163,7 +163,7 @@ fn (g mut Gen) mov64(reg Register, val i64) {
fn (g mut Gen) call(addr int) { fn (g mut Gen) call(addr int) {
//rel := g.abs_to_rel_addr(addr) //rel := g.abs_to_rel_addr(addr)
rel := 0xffffffff - int(abs(addr - g.buf.len))-1 rel := 0xffffffff - int(abs(addr - g.buf.len))-1
println('call addr=$addr rel_addr=$addr pos=$g.buf.len') println('call addr=$addr rel_addr=$addr pos=$g.buf.len')
g.write8(0xe8) g.write8(0xe8)
g.write32(addr) g.write32(addr)
@ -189,7 +189,7 @@ pub fn (g mut Gen) gen_loop_start(from int) int {
pub fn (g mut Gen) gen_loop_end(to int, label int) { pub fn (g mut Gen) gen_loop_end(to int, label int) {
g.cmp(.r12, ._8, to) g.cmp(.r12, ._8, to)
g.jle(label) g.jl(label)
} }
pub fn (g mut Gen) save_main_fn_addr() { pub fn (g mut Gen) save_main_fn_addr() {
@ -206,7 +206,7 @@ pub fn (g mut Gen) gen_print(s string) {
g.mov64(.rsi, 0) //segment_start + 0x9f) // str pos // PLACEHOLDER g.mov64(.rsi, 0) //segment_start + 0x9f) // str pos // PLACEHOLDER
g.mov(.edx, s.len+1) // len g.mov(.edx, s.len+1) // len
g.syscall() g.syscall()
} }
pub fn (g mut Gen) gen_exit() { pub fn (g mut Gen) gen_exit() {
// Return 0 // Return 0
@ -227,11 +227,11 @@ fn (g mut Gen) mov(reg Register, val int) {
.r12 { .r12 {
g.write8(0x41) g.write8(0x41)
g.write8(0xbc) // r11 is 0xbb etc g.write8(0xbc) // r11 is 0xbb etc
} }
else { else {
panic('unhandled mov $reg') panic('unhandled mov $reg')
} }
} }
g.write32(val) g.write32(val)
} }
@ -245,7 +245,7 @@ pub fn (g mut Gen) register_function_address(name string) {
pub fn (g mut Gen) call_fn(name string) { pub fn (g mut Gen) call_fn(name string) {
if !name.contains('__') { if !name.contains('__') {
return return
} }
addr := g.fn_addr[name] addr := g.fn_addr[name]
g.call(int(addr)) g.call(int(addr))
println('call $name $addr') println('call $name $addr')