@@ -1753,10 +1753,8 @@ fn (mut c Amd64) mov(r Register, val i32) {
17531753 }
17541754}
17551755
1756- fn (mut c Amd64) mul_reg (a Amd64 Register, b Amd64 Register) {
1757- if a != .rax {
1758- c.g.n_error ('mul always operates on rax' )
1759- }
1756+ // rax times b
1757+ fn (mut c Amd64) mul_reg_rax (b Amd64 Register) {
17601758 match b {
17611759 .rax {
17621760 c.g.write8 (0x48 )
@@ -1799,10 +1797,8 @@ fn (mut c Amd64) imul_reg(r Amd64Register) {
17991797 }
18001798}
18011799
1802- fn (mut c Amd64) div_reg (a Amd64 Register, b Amd64 Register) {
1803- if a != .rax {
1804- c.g.n_error ('div always operates on rax' )
1805- }
1800+ // rax divided by b
1801+ fn (mut c Amd64) div_reg_rax (b Amd64 Register) {
18061802 match b {
18071803 .rax {
18081804 c.g.write8 (0x48 )
@@ -1831,8 +1827,9 @@ fn (mut c Amd64) div_reg(a Amd64Register, b Amd64Register) {
18311827 c.g.println ('div ${b }' )
18321828}
18331829
1834- fn (mut c Amd64) mod_reg (a Amd64 Register, b Amd64 Register) {
1835- c.div_reg (a, b)
1830+ // rax % b
1831+ fn (mut c Amd64) mod_reg_rax (b Amd64 Register) {
1832+ c.div_reg_rax (b)
18361833 c.mov_reg (Amd64 Register.rdx, Amd64 Register.rax)
18371834}
18381835
@@ -2287,93 +2284,30 @@ fn (mut c Amd64) assign_var(var IdentVar, raw_type ast.Type) {
22872284// TODO: may have a problem if the literal is bigger than max_i64: needs u64
22882285fn (mut c Amd64) assign_ident_int_lit (node ast.AssignStmt, i i32 , int_lit ast.IntegerLiteral, left ast.Ident) {
22892286 match node.op {
2290- .plus_assign {
2291- c.mov_var_to_reg (Amd64 Register.rax, left)
2292- c.mov64 (Amd64 Register.rdx, i64 (int_lit.val.int ()))
2293- c.add_reg (Amd64 Register.rax, Amd64 Register.rdx)
2294- c.mov_reg_to_var (left, Amd64 Register.rax)
2295- }
2296- .minus_assign {
2297- c.mov_var_to_reg (Amd64 Register.rax, left)
2298- c.mov64 (Amd64 Register.rdx, i64 (int_lit.val.int ()))
2299- c.sub_reg (Amd64 Register.rax, Amd64 Register.rdx)
2300- c.mov_reg_to_var (left, Amd64 Register.rax)
2301- }
2302- .mult_assign {
2303- c.mov_var_to_reg (Amd64 Register.rax, left)
2304- c.mov64 (Amd64 Register.rdx, i64 (int_lit.val.int ()))
2305- c.mul_reg (.rax, .rdx)
2306- c.mov_reg_to_var (left, Amd64 Register.rax)
2307- }
2308- .div_assign {
2309- c.mov_var_to_reg (Amd64 Register.rax, left)
2310- c.mov64 (Amd64 Register.rdx, i64 (int_lit.val.int ()))
2311- c.div_reg (.rax, .rdx)
2312- c.mov_reg_to_var (left, Amd64 Register.rax)
2313- }
2314- .mod_assign {
2315- c.mov_var_to_reg (Amd64 Register.rax, left)
2316- c.mov64 (Amd64 Register.rdx, i64 (int_lit.val.int ()))
2317- c.mod_reg (.rax, .rdx)
2318- c.mov_reg_to_var (left, Amd64 Register.rax)
2319- }
23202287 .decl_assign {
23212288 c.allocate_var (left.name, 8 , i64 (int_lit.val.int ()))
23222289 }
23232290 .assign {
23242291 c.mov64 (Amd64 Register.rax, i64 (int_lit.val.int ()))
23252292 c.mov_reg_to_var (left, Amd64 Register.rax)
23262293 }
2327- .left_shift_assign {
2328- c.mov_var_to_reg (Amd64 Register.rax, left)
2329- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2330- c.shl_reg (.rax, .rcx)
2331- c.mov_reg_to_var (left, Amd64 Register.rax)
2332- }
2333- .right_shift_assign {
2334- c.mov_var_to_reg (Amd64 Register.rax, left)
2335- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2336- c.sar_reg (.rax, .rcx)
2337- c.mov_reg_to_var (left, Amd64 Register.rax)
2338- }
2339- .unsigned_right_shift_assign {
2340- c.mov_var_to_reg (Amd64 Register.rax, left)
2341- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2342- c.shr_reg (.rax, .rcx)
2343- c.mov_reg_to_var (left, Amd64 Register.rax)
2344- }
2345- .xor_assign {
2346- c.mov_var_to_reg (Amd64 Register.rax, left)
2347- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2348- c.bitxor_reg (.rax, .rcx)
2349- c.mov_reg_to_var (left, Amd64 Register.rax)
2350- }
2351- .or_assign {
2352- c.mov_var_to_reg (Amd64 Register.rax, left)
2353- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2354- c.bitor_reg (.rax, .rcx)
2355- c.mov_reg_to_var (left, Amd64 Register.rax)
2356- }
2357- .and_assign {
2358- c.mov_var_to_reg (Amd64 Register.rax, left)
2359- c.mov64 (Amd64 Register.rcx, i64 (int_lit.val.int ()))
2360- c.bitand_reg (.rax, .rcx)
2361- c.mov_reg_to_var (left, Amd64 Register.rax)
2362- }
23632294 .boolean_and_assign {
23642295 c.mov_var_to_reg (Amd64 Register.rax, left)
2365- c.mov64 (Amd64 Register.rcx , i64 (int_lit.val.int ()))
2366- c.bitand_reg (.rax, .rcx )
2296+ c.mov64 (Amd64 Register.rbx , i64 (int_lit.val.int ()))
2297+ c.bitand_reg (.rax, .rbx )
23672298 c.mov_reg_to_var (left, Amd64 Register.rax)
23682299 }
23692300 .boolean_or_assign {
23702301 c.mov_var_to_reg (Amd64 Register.rax, left)
2371- c.mov64 (Amd64 Register.rcx , i64 (int_lit.val.int ()))
2372- c.bitor_reg (.rax, .rcx )
2302+ c.mov64 (Amd64 Register.rbx , i64 (int_lit.val.int ()))
2303+ c.bitor_reg (.rax, .rbx )
23732304 c.mov_reg_to_var (left, Amd64 Register.rax)
23742305 }
23752306 else {
2376- c.g.n_error ('${@LOCATION } unexpected assignment op ${node .op }' )
2307+ c.mov_var_to_reg (Amd64 Register.rax, left)
2308+ c.mov64 (Amd64 Register.rbx, i64 (int_lit.val.int ()))
2309+ c.apply_op_int (.rax, .rbx, node.op)
2310+ c.mov_reg_to_var (left, Amd64 Register.rax)
23772311 }
23782312 }
23792313}
@@ -2591,19 +2525,26 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
25912525
25922526 c.mov_ssereg_to_var (ident, .xmm1 )
25932527 } else if left_type.is_int () {
2594- c.mov_var_to_reg (Amd64 Register.rbx, ident)
2595-
2528+ c.mov_reg (Amd64 Register.rbx, Amd64 Register.rax)
2529+ c.mov_var_to_reg (Amd64 Register.rax, ident)
2530+ c.apply_op_int (.rax, .rbx, node.op)
2531+ c.mov_reg_to_var (ident, Amd64 Register.rax)
2532+ } else {
25962533 match node.op {
2597- .plus_assign { c.add_reg (.rbx, .rax) }
2598- .minus_assign { c.sub_reg (.rbx, .rax) }
2599- .div_assign { c.div_reg (.rbx, .rax) }
2600- .mult_assign { c.mul_reg (.rbx, .rax) }
2601- else { c.g.n_error ('${@LOCATION } unexpected assignment operator ${node .op } for i32' ) }
2534+ .boolean_and_assign {
2535+ c.mov_var_to_reg (Amd64 Register.rbx, ident)
2536+ c.bitand_reg (.rbx, .rax)
2537+ c.mov_reg_to_var (ident, Amd64 Register.rbx)
2538+ }
2539+ .boolean_or_assign {
2540+ c.mov_var_to_reg (Amd64 Register.rbx, ident)
2541+ c.bitor_reg (.rbx, .rax)
2542+ c.mov_reg_to_var (ident, Amd64 Register.rbx)
2543+ }
2544+ else {
2545+ c.g.n_error ('${@LOCATION } assignment arithmetic not implemented for type ${node .left_types [i ]}' )
2546+ }
26022547 }
2603-
2604- c.mov_reg_to_var (ident, Amd64 Register.rbx)
2605- } else {
2606- c.g.n_error ('${@LOCATION } assignment arithmetic not implemented for type ${node .left_types [i ]}' )
26072548 }
26082549 }
26092550 }
@@ -2631,19 +2572,26 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
26312572
26322573 c.mov_ssereg_to_var (ident, .xmm1 )
26332574 } else if left_type.is_int () {
2634- c.mov_var_to_reg (Amd64 Register.rbx, ident)
2635-
2575+ c.mov_reg (Amd64 Register.rbx, Amd64 Register.rax)
2576+ c.mov_var_to_reg (Amd64 Register.rax, ident)
2577+ c.apply_op_int (.rax, .rbx, node.op)
2578+ c.mov_reg_to_var (ident, Amd64 Register.rax)
2579+ } else {
26362580 match node.op {
2637- .plus_assign { c.add_reg (.rbx, .rax) }
2638- .minus_assign { c.sub_reg (.rbx, .rax) }
2639- .div_assign { c.div_reg (.rbx, .rax) }
2640- .mult_assign { c.mul_reg (.rbx, .rax) }
2641- else { c.g.n_error ('${@LOCATION } unexpected assignment operator ${node .op } for i32' ) }
2581+ .boolean_and_assign {
2582+ c.mov_var_to_reg (Amd64 Register.rbx, ident)
2583+ c.bitand_reg (.rbx, .rax)
2584+ c.mov_reg_to_var (ident, Amd64 Register.rbx)
2585+ }
2586+ .boolean_or_assign {
2587+ c.mov_var_to_reg (Amd64 Register.rbx, ident)
2588+ c.bitor_reg (.rbx, .rax)
2589+ c.mov_reg_to_var (ident, Amd64 Register.rbx)
2590+ }
2591+ else {
2592+ c.g.n_error ('${@LOCATION } assignment arithmetic not implemented for type ${node .left_types [i ]}' )
2593+ }
26422594 }
2643-
2644- c.mov_reg_to_var (ident, Amd64 Register.rbx)
2645- } else {
2646- c.g.n_error ('${@LOCATION } assignment arithmetic not implemented for type ${node .left_types [i ]}' )
26472595 }
26482596 }
26492597 }
@@ -2680,6 +2628,59 @@ fn (mut c Amd64) assign_ident_right_expr(node ast.AssignStmt, i i32, right ast.E
26802628 }*/
26812629}
26822630
2631+ // /!\ for div, mul, mod the left value should always be .rax
2632+ fn (mut c Amd64) apply_op_int (left_value Amd64 Register, right_value Amd64 Register, op token.Kind) {
2633+ match op {
2634+ .plus_assign {
2635+ c.add_reg (left_value, right_value)
2636+ }
2637+ .minus_assign {
2638+ c.sub_reg (left_value, right_value)
2639+ }
2640+ .div_assign {
2641+ if left_value != .rax {
2642+ c.g.n_error ('@{LOCATION} div always operates on rax' )
2643+ }
2644+ c.mov (Amd64 Register.rdx, i32 (0 )) // 64bits IDIV uses RDX:RAX
2645+ c.div_reg_rax (right_value)
2646+ }
2647+ .mult_assign {
2648+ if left_value != .rax {
2649+ c.g.n_error ('@{LOCATION} mul always operates on rax' )
2650+ }
2651+ c.mul_reg_rax (right_value)
2652+ }
2653+ .xor_assign {
2654+ c.bitxor_reg (left_value, right_value)
2655+ }
2656+ .mod_assign {
2657+ if left_value != .rax {
2658+ c.g.n_error ('@{LOCATION} mod always operates on rax' )
2659+ }
2660+ c.mov (Amd64 Register.rdx, i32 (0 )) // 64bits IDIV uses RDX:RAX
2661+ c.mod_reg_rax (right_value)
2662+ }
2663+ .or_assign {
2664+ c.bitor_reg (left_value, right_value)
2665+ }
2666+ .and_assign {
2667+ c.bitand_reg (left_value, right_value)
2668+ }
2669+ .right_shift_assign {
2670+ c.shr_reg (left_value, right_value)
2671+ }
2672+ .left_shift_assign {
2673+ c.shl_reg (left_value, right_value)
2674+ }
2675+ .unsigned_right_shift_assign {
2676+ c.sar_reg (left_value, right_value)
2677+ }
2678+ else {
2679+ c.g.n_error ('${@LOCATION } unexpected operator ${op } for int' )
2680+ }
2681+ }
2682+ }
2683+
26832684fn (mut c Amd64) gen_type_promotion (from ast.Type, to ast.Type, option Amd64 RegisterOption) {
26842685 if ! to.is_pure_float () {
26852686 return
@@ -3077,52 +3078,6 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
30773078 .decl_assign, .assign {
30783079 c.mov_store (.rbx, .rcx, size)
30793080 }
3080- .plus_assign {
3081- c.add_reg (.rax, .rcx)
3082- c.mov_store (.rbx, .rax, size)
3083- }
3084- .minus_assign {
3085- c.sub_reg (.rax, .rcx)
3086- c.mov_store (.rbx, .rax, size)
3087- }
3088- .and_assign {
3089- c.bitand_reg (.rax, .rcx)
3090- c.mov_store (.rbx, .rax, size)
3091- }
3092- .mod_assign {
3093- c.mov (Amd64 Register.rdx, i32 (0 )) // 64bits IDIV uses RDX:RAX
3094- c.mod_reg (.rax, .rcx)
3095- c.mov_store (.rbx, .rax, size)
3096- }
3097- .mult_assign {
3098- c.mul_reg (.rax, .rcx)
3099- c.mov_store (.rbx, .rax, size)
3100- }
3101- .div_assign {
3102- c.mov (Amd64 Register.rdx, i32 (0 )) // 64bits IDIV uses RDX:RAX
3103- c.div_reg (.rax, .rcx)
3104- c.mov_store (.rbx, .rax, size)
3105- }
3106- .xor_assign {
3107- c.bitxor_reg (.rax, .rcx)
3108- c.mov_store (.rbx, .rax, size)
3109- }
3110- .or_assign {
3111- c.bitor_reg (.rax, .rcx)
3112- c.mov_store (.rbx, .rax, size)
3113- }
3114- .right_shift_assign {
3115- c.shr_reg (.rax, .rcx)
3116- c.mov_store (.rbx, .rax, size)
3117- }
3118- .left_shift_assign {
3119- c.shl_reg (.rax, .rcx)
3120- c.mov_store (.rbx, .rax, size)
3121- }
3122- .unsigned_right_shift_assign {
3123- c.sar_reg (.rax, .rcx)
3124- c.mov_store (.rbx, .rax, size)
3125- }
31263081 .boolean_and_assign {
31273082 c.bitand_reg (.rax, .rcx)
31283083 c.mov_store (.rbx, .rax, size)
@@ -3132,7 +3087,8 @@ fn (mut c Amd64) assign_stmt(node ast.AssignStmt) {
31323087 c.mov_store (.rbx, .rax, size)
31333088 }
31343089 else {
3135- c.g.n_error ('${@LOCATION } Unsupported assign instruction (${node .op })' )
3090+ c.apply_op_int (.rax, .rcx, node.op)
3091+ c.mov_store (.rbx, .rax, size)
31363092 }
31373093 }
31383094 } else if var_type.is_pure_float () {
@@ -4289,7 +4245,7 @@ fn (mut c Amd64) convert_int_to_string(a Register, b Register) {
42894245
42904246 c.mov (Amd64 Register.rdx, 0 ) // upperhalf of the dividend
42914247 c.mov (Amd64 Register.rbx, 10 )
4292- c.div_reg (.rax, .rbx) // rax will be the result of the division
4248+ c.div_reg_rax ( .rbx) // rax will be the result of the division
42934249 c.add8 (.rdx, i32 (`0` )) // rdx is the remainder, add 48 to convert it into it's ascii representation
42944250
42954251 c.mov_store (.rdi, .rdx, ._8 )
0 commit comments