@@ -444,20 +444,10 @@ fn (mut g Gen) jmp(addr i64) {
444
444
*/
445
445
446
446
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 )
460
449
}
450
+ g.write8 (0xb8 + int (reg) % 8 )
461
451
g.write32 (val)
462
452
g.println ('mov32 ${reg} , ${val} ' )
463
453
}
@@ -1895,7 +1885,6 @@ fn (mut g Gen) assign_right_expr(node ast.AssignStmt, i int, right ast.Expr, nam
1895
1885
match right {
1896
1886
ast.IntegerLiteral {
1897
1887
// g.allocate_var(name, 4, right.val.int())
1898
- // TODO float
1899
1888
match node.op {
1900
1889
.plus_assign {
1901
1890
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
1946
1935
}
1947
1936
ast.Ident {
1948
1937
// eprintln('identr') dump(node) dump(right)
1949
- // TODO float
1950
1938
match node.op {
1951
1939
.plus_assign {
1952
1940
g.mov_var_to_reg (.rax, ident)
@@ -2282,87 +2270,126 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
2282
2270
// `a := 1` | `a,b := 1,2`
2283
2271
for i, left in node.left {
2284
2272
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
+ })
2305
2296
}
2306
- } else {
2307
- if node.op != .assign {
2297
+ else {
2308
2298
g.n_error ('Unsupported assign instruction' )
2309
2299
}
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
2339
2350
} else {
2340
- size
2351
+ 8
2341
2352
}
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 )
2350
2367
}
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 )
2354
2378
}
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 )
2355
2384
}
2356
2385
}
2357
- .enum_ {
2358
- g.mov_store (.rdx, .rax, ._32 )
2359
- }
2360
- else {}
2361
2386
}
2387
+ .enum_ {
2388
+ g.mov_store (.rdx, .rax, ._32 )
2389
+ }
2390
+ else {}
2362
2391
}
2363
- continue
2364
2392
}
2365
- g.assign_right_expr (node, i, right, left.str (), left as ast.Ident )
2366
2393
}
2367
2394
}
2368
2395
@@ -2421,9 +2448,19 @@ fn (mut g Gen) gen_left_value(node ast.Expr) {
2421
2448
fn (mut g Gen) prefix_expr (node ast.PrefixExpr) {
2422
2449
match node.op {
2423
2450
.minus {
2424
- // TODO neg float
2425
2451
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
+ }
2427
2464
}
2428
2465
.amp {
2429
2466
g.gen_left_value (node.right)
@@ -2482,8 +2519,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
2482
2519
g.write8 (if node.op == .eq { 0x00 } else { 0x04 })
2483
2520
inst := if node.op == .eq { 'cmpeqss' } else { 'cmpneqss' }
2484
2521
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)
2487
2523
g.write ([u8 (0x83 ), 0xe0 , 0x01 ])
2488
2524
g.println ('and eax, 0x1' )
2489
2525
}
@@ -3583,6 +3619,36 @@ fn (mut g Gen) mov_ssereg(a SSERegister, b SSERegister) {
3583
3619
g.println ('movsd ${a} , ${b} ' )
3584
3620
}
3585
3621
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
+
3586
3652
fn (mut g Gen) add_sse (a SSERegister, b SSERegister, typ ast.Type) {
3587
3653
g.write8 (if typ == ast.f32_ type_idx { 0xf3 } else { 0xf2 })
3588
3654
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) {
3776
3842
}
3777
3843
match g.get_type_size (expr.expr_type) {
3778
3844
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' )
3781
3847
}
3782
3848
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' )
3785
3851
}
3786
3852
else {}
3787
3853
}
@@ -3794,12 +3860,12 @@ fn (mut g Gen) gen_cast_expr_amd64(expr ast.CastExpr) {
3794
3860
g.sub_sse (.xmm0 , .xmm1 , expr.expr_type)
3795
3861
match g.get_type_size (expr.expr_type) {
3796
3862
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' )
3799
3865
}
3800
3866
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' )
3803
3869
}
3804
3870
else {}
3805
3871
}
@@ -3808,12 +3874,12 @@ fn (mut g Gen) gen_cast_expr_amd64(expr ast.CastExpr) {
3808
3874
} else {
3809
3875
match g.get_type_size (expr.expr_type) {
3810
3876
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' )
3813
3879
}
3814
3880
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' )
3817
3883
}
3818
3884
else {}
3819
3885
}
0 commit comments