Skip to content

Commit 00383ed

Browse files
authored
native: add more operator support for floats on amd64 (#16498)
1 parent c744030 commit 00383ed

File tree

3 files changed

+190
-105
lines changed

3 files changed

+190
-105
lines changed

vlib/v/gen/native/amd64.v

Lines changed: 166 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -444,20 +444,10 @@ fn (mut g Gen) jmp(addr i64) {
444444
*/
445445

446446
fn (mut g Gen) mov32(reg Register, val int) {
447-
match reg {
448-
.rax {
449-
g.write8(0xb8)
450-
}
451-
.rdi {
452-
g.write8(0xbf)
453-
}
454-
.rcx {
455-
g.write8(0xb9)
456-
}
457-
else {
458-
panic('unhandled mov32 ${reg}')
459-
}
447+
if int(reg) >= int(Register.r8) {
448+
g.write8(0x41)
460449
}
450+
g.write8(0xb8 + int(reg) % 8)
461451
g.write32(val)
462452
g.println('mov32 ${reg}, ${val}')
463453
}
@@ -1895,7 +1885,6 @@ fn (mut g Gen) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, nam
18951885
match right {
18961886
ast.IntegerLiteral {
18971887
// g.allocate_var(name, 4, right.val.int())
1898-
// TODO float
18991888
match node.op {
19001889
.plus_assign {
19011890
g.mov_var_to_reg(.rax, ident)
@@ -1946,7 +1935,6 @@ fn (mut g Gen) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, nam
19461935
}
19471936
ast.Ident {
19481937
// eprintln('identr') dump(node) dump(right)
1949-
// TODO float
19501938
match node.op {
19511939
.plus_assign {
19521940
g.mov_var_to_reg(.rax, ident)
@@ -2282,87 +2270,126 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
22822270
// `a := 1` | `a,b := 1,2`
22832271
for i, left in node.left {
22842272
right := node.right[i]
2285-
if left !is ast.Ident {
2286-
// TODO float
2287-
g.gen_left_value(left)
2288-
g.push(.rax)
2289-
g.expr(right)
2290-
g.pop(.rdx)
2291-
typ := node.left_types[i]
2292-
if typ.is_number() || typ.is_real_pointer() || typ.is_bool() {
2293-
match node.op {
2294-
.assign {
2295-
g.mov_store(.rdx, .rax, match g.get_type_size(typ) {
2296-
1 { ._8 }
2297-
2 { ._16 }
2298-
3 { ._32 }
2299-
else { ._64 }
2300-
})
2301-
}
2302-
else {
2303-
g.n_error('Unsupported assign instruction')
2304-
}
2273+
typ := node.left_types[i]
2274+
// this branch would be removed, but left for compatibility
2275+
if left is ast.Ident && !typ.is_pure_float() {
2276+
ident := left as ast.Ident
2277+
g.assign_right_expr(node, i, right, ident.name, ident)
2278+
continue
2279+
}
2280+
if left is ast.Ident && node.op == .decl_assign {
2281+
g.allocate_var((left as ast.Ident).name, g.get_type_size(typ), 0)
2282+
}
2283+
g.gen_left_value(left)
2284+
g.push(.rax)
2285+
g.expr(right)
2286+
g.pop(.rdx)
2287+
if g.is_register_type(typ) {
2288+
match node.op {
2289+
.assign {
2290+
g.mov_store(.rdx, .rax, match g.get_type_size(typ) {
2291+
1 { ._8 }
2292+
2 { ._16 }
2293+
3 { ._32 }
2294+
else { ._64 }
2295+
})
23052296
}
2306-
} else {
2307-
if node.op != .assign {
2297+
else {
23082298
g.n_error('Unsupported assign instruction')
23092299
}
2310-
ts := g.table.sym(typ)
2311-
match ts.kind {
2312-
.struct_ {
2313-
size := g.get_type_size(typ)
2314-
if size >= 8 {
2315-
for j in 0 .. size / 8 {
2316-
g.mov_deref(.rcx, .rdx, ast.u64_type_idx)
2317-
g.mov_store(.rax, .rcx, ._64)
2318-
offset := if j == size / 8 - 1 && size % 8 != 0 {
2319-
size % 8
2320-
} else {
2321-
8
2322-
}
2323-
g.add(.rax, offset)
2324-
g.add(.rdx, offset)
2325-
}
2326-
if size % 8 != 0 {
2327-
g.mov_deref(.rcx, .rdx, ast.u64_type_idx)
2328-
g.mov_store(.rax, .rcx, ._64)
2329-
}
2330-
} else {
2331-
mut left_size := if size >= 4 {
2332-
g.mov_deref(.rcx, .rdx, ast.u32_type_idx)
2333-
g.mov_store(.rax, .rcx, ._32)
2334-
if size > 4 {
2335-
g.add(.rax, 4)
2336-
g.add(.rdx, 4)
2337-
}
2338-
size - 4
2300+
}
2301+
} else if typ.is_pure_float() {
2302+
// TODO when the right type is integer
2303+
is_f32 := typ == ast.f32_type_idx
2304+
if node.op !in [.assign, .decl_assign] {
2305+
g.mov_ssereg(.xmm1, .xmm0)
2306+
if is_f32 {
2307+
g.write32(0x02100ff3)
2308+
g.println('movss xmm0, [rdx]')
2309+
} else {
2310+
g.write32(0x02100ff2)
2311+
g.println('movsd xmm0, [rdx]')
2312+
}
2313+
}
2314+
match node.op {
2315+
.plus_assign {
2316+
g.add_sse(.xmm0, .xmm1, typ)
2317+
}
2318+
.minus_assign {
2319+
g.sub_sse(.xmm0, .xmm1, typ)
2320+
}
2321+
.mult_assign {
2322+
g.mul_sse(.xmm0, .xmm1, typ)
2323+
}
2324+
.div_assign {
2325+
g.div_sse(.xmm0, .xmm1, typ)
2326+
}
2327+
else {}
2328+
}
2329+
if is_f32 {
2330+
g.write32(0x02110ff3)
2331+
g.println('movss [rdx], xmm0')
2332+
} else {
2333+
g.write32(0x02110ff2)
2334+
g.println('movsd [rdx], xmm0')
2335+
}
2336+
} else {
2337+
if node.op != .assign {
2338+
g.n_error('Unsupported assign instruction')
2339+
}
2340+
ts := g.table.sym(typ)
2341+
match ts.kind {
2342+
.struct_ {
2343+
size := g.get_type_size(typ)
2344+
if size >= 8 {
2345+
for j in 0 .. size / 8 {
2346+
g.mov_deref(.rcx, .rdx, ast.u64_type_idx)
2347+
g.mov_store(.rax, .rcx, ._64)
2348+
offset := if j == size / 8 - 1 && size % 8 != 0 {
2349+
size % 8
23392350
} else {
2340-
size
2351+
8
23412352
}
2342-
if left_size >= 2 {
2343-
g.mov_deref(.rcx, .rdx, ast.u16_type_idx)
2344-
g.mov_store(.rax, .rcx, ._16)
2345-
if left_size > 2 {
2346-
g.add(.rax, 2)
2347-
g.add(.rdx, 2)
2348-
}
2349-
left_size -= 2
2353+
g.add(.rax, offset)
2354+
g.add(.rdx, offset)
2355+
}
2356+
if size % 8 != 0 {
2357+
g.mov_deref(.rcx, .rdx, ast.u64_type_idx)
2358+
g.mov_store(.rax, .rcx, ._64)
2359+
}
2360+
} else {
2361+
mut left_size := if size >= 4 {
2362+
g.mov_deref(.rcx, .rdx, ast.u32_type_idx)
2363+
g.mov_store(.rax, .rcx, ._32)
2364+
if size > 4 {
2365+
g.add(.rax, 4)
2366+
g.add(.rdx, 4)
23502367
}
2351-
if left_size == 1 {
2352-
g.mov_deref(.rcx, .rdx, ast.u8_type_idx)
2353-
g.mov_store(.rax, .rcx, ._8)
2368+
size - 4
2369+
} else {
2370+
size
2371+
}
2372+
if left_size >= 2 {
2373+
g.mov_deref(.rcx, .rdx, ast.u16_type_idx)
2374+
g.mov_store(.rax, .rcx, ._16)
2375+
if left_size > 2 {
2376+
g.add(.rax, 2)
2377+
g.add(.rdx, 2)
23542378
}
2379+
left_size -= 2
2380+
}
2381+
if left_size == 1 {
2382+
g.mov_deref(.rcx, .rdx, ast.u8_type_idx)
2383+
g.mov_store(.rax, .rcx, ._8)
23552384
}
23562385
}
2357-
.enum_ {
2358-
g.mov_store(.rdx, .rax, ._32)
2359-
}
2360-
else {}
23612386
}
2387+
.enum_ {
2388+
g.mov_store(.rdx, .rax, ._32)
2389+
}
2390+
else {}
23622391
}
2363-
continue
23642392
}
2365-
g.assign_right_expr(node, i, right, left.str(), left as ast.Ident)
23662393
}
23672394
}
23682395

@@ -2421,9 +2448,19 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
24212448
fn (mut g Gen) prefix_expr(node ast.PrefixExpr) {
24222449
match node.op {
24232450
.minus {
2424-
// TODO neg float
24252451
g.expr(node.right)
2426-
g.neg(.rax)
2452+
if node.right_type.is_pure_float() {
2453+
g.mov_ssereg_to_reg(.rax, .xmm0, node.right_type)
2454+
if node.right_type == ast.f32_type_idx {
2455+
g.mov32(.rdx, int(u32(0x80000000)))
2456+
} else {
2457+
g.movabs(.rdx, i64(u64(0x8000000000000000)))
2458+
}
2459+
g.bitxor_reg(.rax, .rdx)
2460+
g.mov_reg_to_ssereg(.xmm0, .rax, node.right_type)
2461+
} else {
2462+
g.neg(.rax)
2463+
}
24272464
}
24282465
.amp {
24292466
g.gen_left_value(node.right)
@@ -2482,8 +2519,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
24822519
g.write8(if node.op == .eq { 0x00 } else { 0x04 })
24832520
inst := if node.op == .eq { 'cmpeqss' } else { 'cmpneqss' }
24842521
g.println('${inst} xmm0, xmm1')
2485-
g.write32(0xc07e0f66)
2486-
g.println('movd eax, xmm0')
2522+
g.mov_ssereg_to_reg(.rax, .xmm0, ast.f32_type_idx)
24872523
g.write([u8(0x83), 0xe0, 0x01])
24882524
g.println('and eax, 0x1')
24892525
}
@@ -3583,6 +3619,36 @@ fn (mut g Gen) mov_ssereg(a SSERegister, b SSERegister) {
35833619
g.println('movsd ${a}, ${b}')
35843620
}
35853621

3622+
fn (mut g Gen) mov_ssereg_to_reg(a Register, b SSERegister, typ ast.Type) {
3623+
g.write8(0x66)
3624+
rex_base, inst := if typ == ast.f32_type_idx {
3625+
0x40, 'movd'
3626+
} else {
3627+
0x48, 'movq'
3628+
}
3629+
if rex_base == 0x48 || int(a) >= int(Register.r8) || int(b) >= int(SSERegister.xmm8) {
3630+
g.write8(rex_base + int(a) / 8 * 4 + int(b) / 8)
3631+
}
3632+
g.write16(0x7e0f)
3633+
g.write8(0xc0 + int(a) % 8 * 8 + int(b) % 8)
3634+
g.println('${inst} ${a}, ${b}')
3635+
}
3636+
3637+
fn (mut g Gen) mov_reg_to_ssereg(a SSERegister, b Register, typ ast.Type) {
3638+
g.write8(0x66)
3639+
rex_base, inst := if typ == ast.f32_type_idx {
3640+
0x40, 'movd'
3641+
} else {
3642+
0x48, 'movq'
3643+
}
3644+
if rex_base == 0x48 || int(a) >= int(SSERegister.xmm8) || int(b) >= int(Register.r8) {
3645+
g.write8(rex_base + int(a) / 8 * 4 + int(b) / 8)
3646+
}
3647+
g.write16(0x6e0f)
3648+
g.write8(0xc0 + int(a) % 8 * 8 + int(b) % 8)
3649+
g.println('${inst} ${a}, ${b}')
3650+
}
3651+
35863652
fn (mut g Gen) add_sse(a SSERegister, b SSERegister, typ ast.Type) {
35873653
g.write8(if typ == ast.f32_type_idx { 0xf3 } else { 0xf2 })
35883654
if int(a) >= int(SSERegister.xmm8) || int(b) >= int(SSERegister.xmm8) {
@@ -3776,12 +3842,12 @@ fn (mut g Gen) gen_cast_expr_amd64(expr ast.CastExpr) {
37763842
}
37773843
match g.get_type_size(expr.expr_type) {
37783844
4 {
3779-
g.write([u8(0xf3), 0x48, 0x0f, 0x2d, 0xc0])
3780-
g.println('cvtss2si rax, xmm0')
3845+
g.write([u8(0xf3), 0x48, 0x0f, 0x2c, 0xc0])
3846+
g.println('cvttss2si rax, xmm0')
37813847
}
37823848
8 {
3783-
g.write([u8(0xf2), 0x48, 0x0f, 0x2d, 0xc0])
3784-
g.println('cvtsd2si rax, xmm0')
3849+
g.write([u8(0xf2), 0x48, 0x0f, 0x2c, 0xc0])
3850+
g.println('cvttsd2si rax, xmm0')
37853851
}
37863852
else {}
37873853
}
@@ -3794,12 +3860,12 @@ fn (mut g Gen) gen_cast_expr_amd64(expr ast.CastExpr) {
37943860
g.sub_sse(.xmm0, .xmm1, expr.expr_type)
37953861
match g.get_type_size(expr.expr_type) {
37963862
4 {
3797-
g.write([u8(0xf3), 0x48, 0x0f, 0x2d, 0xc0])
3798-
g.println('cvtss2si rax, xmm0')
3863+
g.write([u8(0xf3), 0x48, 0x0f, 0x2c, 0xc0])
3864+
g.println('cvttss2si rax, xmm0')
37993865
}
38003866
8 {
3801-
g.write([u8(0xf2), 0x48, 0x0f, 0x2d, 0xc0])
3802-
g.println('cvtsd2si rax, xmm0')
3867+
g.write([u8(0xf2), 0x48, 0x0f, 0x2c, 0xc0])
3868+
g.println('cvttsd2si rax, xmm0')
38033869
}
38043870
else {}
38053871
}
@@ -3808,12 +3874,12 @@ fn (mut g Gen) gen_cast_expr_amd64(expr ast.CastExpr) {
38083874
} else {
38093875
match g.get_type_size(expr.expr_type) {
38103876
4 {
3811-
g.write([u8(0xf3), 0x48, 0x0f, 0x2d, 0xc0])
3812-
g.println('cvtss2si rax, xmm0')
3877+
g.write([u8(0xf3), 0x48, 0x0f, 0x2c, 0xc0])
3878+
g.println('cvttss2si rax, xmm0')
38133879
}
38143880
8 {
3815-
g.write([u8(0xf2), 0x48, 0x0f, 0x2d, 0xc0])
3816-
g.println('cvtsd2si rax, xmm0')
3881+
g.write([u8(0xf2), 0x48, 0x0f, 0x2c, 0xc0])
3882+
g.println('cvttsd2si rax, xmm0')
38173883
}
38183884
else {}
38193885
}

0 commit comments

Comments
 (0)