diff --git a/vlib/v/gen/native/amd64.v b/vlib/v/gen/native/amd64.v index 82d13dc389..9e01e16444 100644 --- a/vlib/v/gen/native/amd64.v +++ b/vlib/v/gen/native/amd64.v @@ -59,12 +59,9 @@ fn byt(n int, s int) u8 { } fn (mut g Gen) inc(reg Register) { - g.write16(0xff49) - match reg { - .rcx { g.write8(0xc1) } - .r12 { g.write8(0xc4) } - else { panic('unhandled inc $reg') } - } + g.write8(0x48) + g.write8(0xff) + g.write8(0xc0 + int(reg)) g.println('inc $reg') } @@ -138,6 +135,16 @@ fn (mut g Gen) cmp_reg(reg Register, reg2 Register) { } } } + .rdi { + match reg2 { + .rsi { + g.write([u8(0x48), 0x39, 0xf7]) + } + else { + g.n_error('Cannot compare $reg and $reg2') + } + } + } else { g.n_error('Cannot compare $reg and $reg2') } @@ -235,14 +242,14 @@ fn abs(a i64) i64 { fn (mut g Gen) tmp_jle(addr i64) { // Calculate the relative offset to jump to // (`addr` is absolute address) - offset := 0xff - int(abs(addr - g.buf.len)) - 1 + offset := 0xff - g.abs_to_rel_addr(addr) g.write8(0x7e) g.write8(offset) g.println('jle') } fn (mut g Gen) jl(addr i64) { - offset := 0xff - int(abs(addr - g.buf.len)) - 1 + offset := 0xff - g.abs_to_rel_addr(addr) g.write8(0x7c) g.write8(offset) g.println('jl') @@ -381,7 +388,7 @@ fn (mut g Gen) mov_int_to_var(var_offset int, size Size, integer int) { fn (mut g Gen) lea_var_to_reg(reg Register, var_offset int) { match reg { - .rax, .rbx, .rsi { + .rax, .rbx, .rsi, .rdi { g.write8(0x48) } else {} @@ -445,6 +452,11 @@ fn (mut g Gen) syscall() { g.println('syscall') } +fn (mut g Gen) cdq() { + g.write8(0x99) + g.println('cdq') +} + pub fn (mut g Gen) ret() { g.write8(0xc3) g.println('ret') @@ -509,8 +521,7 @@ pub fn (mut g Gen) add(reg Register, val int) { pub fn (mut g Gen) add8(reg Register, val int) { g.write8(0x48) g.write8(0x83) - // g.write8(0xe8 + reg) // TODO rax is different? - g.write8(0xc4) + g.write8(0xc0 + int(reg)) g.write8(val) g.println('add8 $reg,$val.hex2()') } @@ -595,9 +606,18 @@ pub fn (mut g Gen) rep_stosb() { g.println('rep stosb') } -pub fn (mut g Gen) cld_repne_scasb() { +pub fn (mut g Gen) std() { + g.write8(0xfd) + g.println('std') +} + +pub fn (mut g Gen) cld() { g.write8(0xfc) g.println('cld') +} + +pub fn (mut g Gen) cld_repne_scasb() { + g.cld() g.write8(0xf2) g.write8(0xae) g.println('repne scasb') @@ -931,6 +951,9 @@ fn (mut g Gen) mov(reg Register, val int) { g.write8(0x41) g.write8(0xbc) // r11 is 0xbb etc } + .rbx { + g.write8(0xbb) + } else { g.n_error('unhandled mov $reg') } @@ -1084,6 +1107,18 @@ fn (mut g Gen) mov_reg(a Register, b Register) { g.write8(0x48) g.write8(0x89) g.write8(0xc7) + } else if a == .r12 && b == .rdi { + g.write8(0x49) + g.write8(0x89) + g.write8(0xfc) + } else if a == .rdi && b == .r12 { + g.write8(0x4c) + g.write8(0x89) + g.write8(0xe7) + } else if a == .rsi && b == .rdi { + g.write8(0x48) + g.write8(0x89) + g.write8(0xfe) } else { g.n_error('unhandled mov_reg combination for $a $b') } @@ -1988,6 +2023,9 @@ fn (mut g Gen) convert_int_to_string(r Register, buffer int) { g.labels.addrs[skip_zero_label] = g.pos() g.println('; label $skip_zero_label') + // load a pointer to the string to rdi + g.lea_var_to_reg(.rdi, buffer) + // detect if value in rax is negative g.cmp_zero(.rax) skip_minus_label := g.labels.new_label() @@ -2000,11 +2038,103 @@ fn (mut g Gen) convert_int_to_string(r Register, buffer int) { // add a `-` sign as the first character g.mov_int_to_var(buffer, ._8, '-'[0]) - g.neg(.rax) + g.neg(.rax) // negate our integer to make it positive + g.inc(.rdi) // increment rdi to skip the `-` character g.labels.addrs[skip_minus_label] = g.pos() + g.println('; label $skip_minus_label') - // TODO: convert non-zero integer to string + g.mov_reg(.r12, .rdi) // copy the buffer position to rcx + + loop_label := g.labels.new_label() + loop_start := g.pos() + g.println('; label $loop_label') + + g.push(.rax) + + g.mov(.rdx, 0) + g.mov(.rbx, 10) + g.div_reg(.rax, .rbx) + g.add8(.rdx, '0'[0]) + + g.write8(0x66) + g.write8(0x89) + g.write8(0x17) + g.println('mov BYTE PTR [rdi], rdx') + + // divide the integer in rax by 10 for next iteration + g.pop(.rax) + g.mov(.rbx, 10) + g.cdq() + g.write8(0x48) + g.write8(0xf7) + g.write8(0xfb) + g.println('idiv rbx') + + // go to the next character + g.inc(.rdi) + + // if the number in rax still isn't zero, repeat + g.cmp_zero(.rax) + loop_cjmp_addr := g.cjmp(.jg) + g.labels.patches << LabelPatch{ + id: loop_label + pos: loop_cjmp_addr + } + g.println('; jump to label $skip_minus_label') + g.labels.addrs[loop_label] = loop_start + + // after all was converted, reverse the string + g.reverse_string(.r12) g.labels.addrs[end_label] = g.pos() g.println('; label $end_label') } + +fn (mut g Gen) reverse_string(reg Register) { + if reg != .rdi { + g.mov_reg(.rdi, reg) + } + + g.mov(.eax, 0) + + g.write8(0x48) + g.write8(0x8d) + g.write8(0x48) + g.write8(0xff) + g.println('lea rcx, [rax-0x1]') + + g.mov_reg(.rsi, .rdi) + + g.write8(0xf2) + g.write8(0xae) + g.println('repnz scas al, BYTE PTR es:[rdi]') + + g.sub8(.rdi, 0x2) + g.cmp_reg(.rdi, .rsi) + + g.write8(0x7e) + g.write8(0x0a) + g.println('jle 0x1e') + + g.write8(0x86) + g.write8(0x07) + g.println('xchg BYTE PTR [rdi], al') + + g.write8(0x86) + g.write8(0x06) + g.println('xchg BYTE PTR [rsi], al') + + g.std() + + g.write8(0xaa) + g.println('stos BYTE PTR es:[rdi], al') + + g.cld() + + g.write8(0xac) + g.println('lods al, BYTE PTR ds:[rsi]') + + g.write8(0xeb) + g.write8(0xf1) + g.println('jmp 0xf') +} diff --git a/vlib/v/gen/native/tests/print.vv b/vlib/v/gen/native/tests/print.vv index fd972939dd..d570c52cdb 100644 --- a/vlib/v/gen/native/tests/print.vv +++ b/vlib/v/gen/native/tests/print.vv @@ -33,8 +33,17 @@ fn test_idents() { x := 0 println(x) - // y := -5 - // println(y) + y := 5 + println(y) + + z := -8 + println(z) + + a := 123 + println(a) + + b := -456 + println(b) } fn main() { diff --git a/vlib/v/gen/native/tests/print.vv.out b/vlib/v/gen/native/tests/print.vv.out index 71afe3f233..a068770e3a 100644 --- a/vlib/v/gen/native/tests/print.vv.out +++ b/vlib/v/gen/native/tests/print.vv.out @@ -4,3 +4,7 @@ Hello World 4 8 0 +5 +-8 +123 +-456 \ No newline at end of file