@@ -2286,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2286
2286
.register_c_flag ,
2287
2287
.register_v_flag ,
2288
2288
= > unreachable , // cannot hold an address
2289
- .immediate = > | imm | try self .setRegOrMem (elem_ty , dst_mcv , .{ .memory = imm }),
2290
- .ptr_stack_offset = > | off | try self .setRegOrMem (elem_ty , dst_mcv , .{ .stack_offset = off }),
2289
+ .immediate = > | imm | {
2290
+ try self .setRegOrMem (elem_ty , dst_mcv , .{ .memory = imm });
2291
+ },
2292
+ .ptr_stack_offset = > | off | {
2293
+ try self .setRegOrMem (elem_ty , dst_mcv , .{ .stack_offset = off });
2294
+ },
2291
2295
.register = > | reg | {
2292
2296
const reg_lock = self .register_manager .lockReg (reg );
2293
2297
defer if (reg_lock ) | reg_locked | self .register_manager .unlockReg (reg_locked );
2294
2298
2295
2299
switch (dst_mcv ) {
2296
- .dead = > unreachable ,
2297
- .undef = > unreachable ,
2298
- .cpsr_flags = > unreachable ,
2299
2300
.register = > | dst_reg | {
2300
2301
try self .genLdrRegister (dst_reg , reg , elem_ty );
2301
2302
},
@@ -2331,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2331
2332
try self .genInlineMemcpy (src_reg , dst_reg , len_reg , count_reg , tmp_reg );
2332
2333
}
2333
2334
},
2334
- else = > return self . fail ( "TODO load from register into {}" , .{ dst_mcv }),
2335
+ else = > unreachable , // attempting to load into non- register or non-stack MCValue
2335
2336
}
2336
2337
},
2337
2338
.memory ,
@@ -2428,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2428
2429
// sub src_reg, fp, #off
2429
2430
try self .genSetReg (ptr_ty , src_reg , .{ .ptr_stack_offset = off });
2430
2431
},
2431
- .memory = > | addr | try self .genSetReg (Type . usize , src_reg , .{ .immediate = @intCast (u32 , addr ) }),
2432
+ .memory = > | addr | try self .genSetReg (ptr_ty , src_reg , .{ .immediate = @intCast (u32 , addr ) }),
2432
2433
.stack_argument_offset = > | off | {
2433
2434
_ = try self .addInst (.{
2434
2435
.tag = .ldr_ptr_stack_argument ,
@@ -3374,6 +3375,102 @@ fn genInlineMemcpy(
3374
3375
// end:
3375
3376
}
3376
3377
3378
+ fn genInlineMemset (
3379
+ self : * Self ,
3380
+ dst : MCValue ,
3381
+ val : MCValue ,
3382
+ len : MCValue ,
3383
+ ) ! void {
3384
+ const dst_reg = switch (dst ) {
3385
+ .register = > | r | r ,
3386
+ else = > try self .copyToTmpRegister (Type .initTag (.manyptr_u8 ), dst ),
3387
+ };
3388
+ const dst_reg_lock = self .register_manager .lockReg (dst_reg );
3389
+ defer if (dst_reg_lock ) | lock | self .register_manager .unlockReg (lock );
3390
+
3391
+ const val_reg = switch (val ) {
3392
+ .register = > | r | r ,
3393
+ else = > try self .copyToTmpRegister (Type .initTag (.u8 ), val ),
3394
+ };
3395
+ const val_reg_lock = self .register_manager .lockReg (val_reg );
3396
+ defer if (val_reg_lock ) | lock | self .register_manager .unlockReg (lock );
3397
+
3398
+ const len_reg = switch (len ) {
3399
+ .register = > | r | r ,
3400
+ else = > try self .copyToTmpRegister (Type .usize , len ),
3401
+ };
3402
+ const len_reg_lock = self .register_manager .lockReg (len_reg );
3403
+ defer if (len_reg_lock ) | lock | self .register_manager .unlockReg (lock );
3404
+
3405
+ const count_reg = try self .register_manager .allocReg (null , gp );
3406
+
3407
+ try self .genInlineMemsetCode (dst_reg , val_reg , len_reg , count_reg );
3408
+ }
3409
+
3410
+ fn genInlineMemsetCode (
3411
+ self : * Self ,
3412
+ dst : Register ,
3413
+ val : Register ,
3414
+ len : Register ,
3415
+ count : Register ,
3416
+ ) ! void {
3417
+ // mov count, #0
3418
+ _ = try self .addInst (.{
3419
+ .tag = .mov ,
3420
+ .data = .{ .rr_op = .{
3421
+ .rd = count ,
3422
+ .rn = .r0 ,
3423
+ .op = Instruction .Operand .imm (0 , 0 ),
3424
+ } },
3425
+ });
3426
+
3427
+ // loop:
3428
+ // cmp count, len
3429
+ _ = try self .addInst (.{
3430
+ .tag = .cmp ,
3431
+ .data = .{ .rr_op = .{
3432
+ .rd = .r0 ,
3433
+ .rn = count ,
3434
+ .op = Instruction .Operand .reg (len , Instruction .Operand .Shift .none ),
3435
+ } },
3436
+ });
3437
+
3438
+ // bge end
3439
+ _ = try self .addInst (.{
3440
+ .tag = .b ,
3441
+ .cond = .ge ,
3442
+ .data = .{ .inst = @intCast (u32 , self .mir_instructions .len + 4 ) },
3443
+ });
3444
+
3445
+ // strb val, [src, count]
3446
+ _ = try self .addInst (.{
3447
+ .tag = .strb ,
3448
+ .data = .{ .rr_offset = .{
3449
+ .rt = val ,
3450
+ .rn = dst ,
3451
+ .offset = .{ .offset = Instruction .Offset .reg (count , .none ) },
3452
+ } },
3453
+ });
3454
+
3455
+ // add count, count, #1
3456
+ _ = try self .addInst (.{
3457
+ .tag = .add ,
3458
+ .data = .{ .rr_op = .{
3459
+ .rd = count ,
3460
+ .rn = count ,
3461
+ .op = Instruction .Operand .imm (1 , 0 ),
3462
+ } },
3463
+ });
3464
+
3465
+ // b loop
3466
+ _ = try self .addInst (.{
3467
+ .tag = .b ,
3468
+ .data = .{ .inst = @intCast (u32 , self .mir_instructions .len - 4 ) },
3469
+ });
3470
+
3471
+ // end:
3472
+ }
3473
+
3377
3474
/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
3378
3475
/// after codegen for this symbol is done.
3379
3476
fn addDbgInfoTypeReloc (self : * Self , ty : Type ) error {OutOfMemory }! void {
@@ -4652,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4652
4749
if (! self .wantSafety ())
4653
4750
return ; // The already existing value will do just fine.
4654
4751
// TODO Upgrade this to a memset call when we have that available.
4655
- switch (ty .abiSize (self .target .* )) {
4656
- 1 = > return self .genSetStack (ty , stack_offset , .{ .immediate = 0xaa }),
4657
- 2 = > return self .genSetStack (ty , stack_offset , .{ .immediate = 0xaaaa }),
4658
- 4 = > return self .genSetStack (ty , stack_offset , .{ .immediate = 0xaaaaaaaa }),
4659
- else = > return self .fail ("TODO implement memset" , .{}),
4752
+ switch (abi_size ) {
4753
+ 1 = > try self .genSetStack (ty , stack_offset , .{ .immediate = 0xaa }),
4754
+ 2 = > try self .genSetStack (ty , stack_offset , .{ .immediate = 0xaaaa }),
4755
+ 4 = > try self .genSetStack (ty , stack_offset , .{ .immediate = 0xaaaaaaaa }),
4756
+ else = > try self .genInlineMemset (
4757
+ .{ .ptr_stack_offset = stack_offset },
4758
+ .{ .immediate = 0xaa },
4759
+ .{ .immediate = abi_size },
4760
+ ),
4660
4761
}
4661
4762
},
4662
4763
.cpsr_flags ,
@@ -5068,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5068
5169
return ; // The already existing value will do just fine.
5069
5170
// TODO Upgrade this to a memset call when we have that available.
5070
5171
switch (abi_size ) {
5071
- 1 = > return self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaa }),
5072
- 2 = > return self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaaaa }),
5073
- 4 = > return self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaaaaaaaa }),
5172
+ 1 = > try self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaa }),
5173
+ 2 = > try self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaaaa }),
5174
+ 4 = > try self .genSetStackArgument (ty , stack_offset , .{ .immediate = 0xaaaaaaaa }),
5074
5175
else = > return self .fail ("TODO implement memset" , .{}),
5075
5176
}
5076
5177
},
0 commit comments