@@ -1460,7 +1460,35 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
14601460 }
14611461 },
14621462 .arm = > {
1463- if (info .args .len > 0 ) return self .fail (inst .base .src , "TODO implement fn args for {}" , .{self .target .cpu .arch });
1463+ for (info .args ) | mc_arg , arg_i | {
1464+ const arg = inst .args [arg_i ];
1465+ const arg_mcv = try self .resolveInst (inst .args [arg_i ]);
1466+
1467+ switch (mc_arg ) {
1468+ .none = > continue ,
1469+ .undef = > unreachable ,
1470+ .immediate = > unreachable ,
1471+ .unreach = > unreachable ,
1472+ .dead = > unreachable ,
1473+ .embedded_in_code = > unreachable ,
1474+ .memory = > unreachable ,
1475+ .compare_flags_signed = > unreachable ,
1476+ .compare_flags_unsigned = > unreachable ,
1477+ .register = > | reg | {
1478+ try self .genSetReg (arg .src , reg , arg_mcv );
1479+ // TODO interact with the register allocator to mark the instruction as moved.
1480+ },
1481+ .stack_offset = > {
1482+ return self .fail (inst .base .src , "TODO implement calling with parameters in memory" , .{});
1483+ },
1484+ .ptr_stack_offset = > {
1485+ return self .fail (inst .base .src , "TODO implement calling with MCValue.ptr_stack_offset arg" , .{});
1486+ },
1487+ .ptr_embedded_in_code = > {
1488+ return self .fail (inst .base .src , "TODO implement calling with MCValue.ptr_embedded_in_code arg" , .{});
1489+ },
1490+ }
1491+ }
14641492
14651493 if (inst .func .cast (ir .Inst .Constant )) | func_inst | {
14661494 if (func_inst .val .cast (Value .Payload .Function )) | func_val | {
@@ -1481,7 +1509,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
14811509 // of course. Add pushing lr to stack
14821510 // and popping after call
14831511 try self .genSetReg (inst .base .src , .lr , .{ .memory = got_addr });
1484- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .blx (.al , .lr ).toU32 ());
1512+
1513+ if (Target .arm .featureSetHas (self .target .cpu .features , .has_v5t )) {
1514+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .blx (.al , .lr ).toU32 ());
1515+ } else {
1516+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , .lr , Instruction .Operand .reg (.pc , Instruction .Operand .Shift .none )).toU32 ());
1517+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .bx (.al , .lr ).toU32 ());
1518+ }
14851519 } else {
14861520 return self .fail (inst .base .src , "TODO implement calling bitcasted functions" , .{});
14871521 }
@@ -2212,14 +2246,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
22122246 // least amount of necessary instructions (use
22132247 // more intelligent rotating)
22142248 if (x <= math .maxInt (u8 )) {
2215- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , 0 , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
2249+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
22162250 return ;
22172251 } else if (x <= math .maxInt (u16 )) {
22182252 // TODO Use movw Note: Not supported on
22192253 // all ARM targets!
22202254
2221- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , 0 , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
2222- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , 0 , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 8 ), 12 )).toU32 ());
2255+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
2256+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 8 ), 12 )).toU32 ());
22232257 } else if (x <= math .maxInt (u32 )) {
22242258 // TODO Use movw and movt Note: Not
22252259 // supported on all ARM targets! Also TODO
@@ -2231,15 +2265,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
22312265 // orr reg, reg, #0xbb, 24
22322266 // orr reg, reg, #0xcc, 16
22332267 // orr reg, reg, #0xdd, 8
2234- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , 0 , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
2235- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , 0 , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 8 ), 12 )).toU32 ());
2236- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , 0 , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 16 ), 8 )).toU32 ());
2237- mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , 0 , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 24 ), 4 )).toU32 ());
2268+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , reg , Instruction .Operand .imm (@truncate (u8 , x ), 0 )).toU32 ());
2269+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 8 ), 12 )).toU32 ());
2270+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 16 ), 8 )).toU32 ());
2271+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .orr (.al , reg , reg , Instruction .Operand .imm (@truncate (u8 , x >> 24 ), 4 )).toU32 ());
22382272 return ;
22392273 } else {
22402274 return self .fail (src , "ARM registers are 32-bit wide" , .{});
22412275 }
22422276 },
2277+ .register = > | src_reg | {
2278+ // If the registers are the same, nothing to do.
2279+ if (src_reg .id () == reg .id ())
2280+ return ;
2281+
2282+ // mov reg, src_reg
2283+ mem .writeIntLittle (u32 , try self .code .addManyAsArray (4 ), Instruction .mov (.al , reg , Instruction .Operand .reg (src_reg , Instruction .Operand .Shift .none )).toU32 ());
2284+ },
22432285 .memory = > | addr | {
22442286 // The value is in memory at a hard-coded address.
22452287 // If the type is a pointer, it means the pointer address is at this memory location.
@@ -2700,6 +2742,53 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27002742 else = > return self .fail (src , "TODO implement function parameters for {} on x86_64" , .{cc }),
27012743 }
27022744 },
2745+ .arm = > {
2746+ switch (cc ) {
2747+ .Naked = > {
2748+ assert (result .args .len == 0 );
2749+ result .return_value = .{ .unreach = {} };
2750+ result .stack_byte_count = 0 ;
2751+ result .stack_align = 1 ;
2752+ return result ;
2753+ },
2754+ .Unspecified , .C = > {
2755+ // ARM Procedure Call Standard, Chapter 6.5
2756+ var ncrn : usize = 0 ; // Next Core Register Number
2757+ var nsaa : u32 = 0 ; // Next stacked argument address
2758+
2759+ for (param_types ) | ty , i | {
2760+ if (ty .abiAlignment (self .target .* ) == 8 ) {
2761+ // Round up NCRN to the next even number
2762+ ncrn += ncrn % 2 ;
2763+ }
2764+
2765+ const param_size = @intCast (u32 , ty .abiSize (self .target .* ));
2766+ if (std .math .divCeil (u32 , param_size , 4 ) catch unreachable <= 4 - ncrn ) {
2767+ if (param_size <= 4 ) {
2768+ result .args [i ] = .{ .register = c_abi_int_param_regs [ncrn ] };
2769+ ncrn += 1 ;
2770+ } else {
2771+ return self .fail (src , "TODO MCValues with multiple registers" , .{});
2772+ }
2773+ } else {
2774+ ncrn = 4 ;
2775+ if (ty .abiAlignment (self .target .* ) == 8 ) {
2776+ if (nsaa % 8 != 0 ) {
2777+ nsaa += 8 - (nsaa % 8 );
2778+ }
2779+ }
2780+
2781+ result .args [i ] = .{ .stack_offset = nsaa };
2782+ nsaa += param_size ;
2783+ }
2784+ }
2785+
2786+ result .stack_byte_count = nsaa ;
2787+ result .stack_align = 4 ;
2788+ },
2789+ else = > return self .fail (src , "TODO implement function parameters for {} on arm" , .{cc }),
2790+ }
2791+ },
27032792 else = > if (param_types .len != 0 )
27042793 return self .fail (src , "TODO implement codegen parameters for {}" , .{self .target .cpu .arch }),
27052794 }
@@ -2718,6 +2807,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27182807 },
27192808 else = > return self .fail (src , "TODO implement function return values for {}" , .{cc }),
27202809 },
2810+ .arm = > switch (cc ) {
2811+ .Naked = > unreachable ,
2812+ .Unspecified , .C = > {
2813+ const ret_ty_size = @intCast (u32 , ret_ty .abiSize (self .target .* ));
2814+ if (ret_ty_size <= 4 ) {
2815+ result .return_value = .{ .register = c_abi_int_return_regs [0 ] };
2816+ } else {
2817+ return self .fail (src , "TODO support more return types for ARM backend" , .{});
2818+ }
2819+ },
2820+ else = > return self .fail (src , "TODO implement function return values for {}" , .{cc }),
2821+ },
27212822 else = > return self .fail (src , "TODO implement codegen return values for {}" , .{self .target .cpu .arch }),
27222823 }
27232824 return result ;
0 commit comments