native: integer-to-string conversion (#14758)
							parent
							
								
									67716b5b59
								
							
						
					
					
						commit
						2f1a896d18
					
				|  | @ -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') | ||||
| } | ||||
|  |  | |||
|  | @ -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() { | ||||
|  |  | |||
|  | @ -4,3 +4,7 @@ Hello World | |||
| 4 | ||||
| 8 | ||||
| 0 | ||||
| 5 | ||||
| -8 | ||||
| 123 | ||||
| -456 | ||||
		Loading…
	
		Reference in New Issue