| ... | @@ -1301,8 +1301,64 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1301,8 +1301,64 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1301 | .embedded_in_code => { | 1301 | .embedded_in_code => { |
| 1302 | return self.fail("TODO implement loading from MCValue.embedded_in_code", .{}); | 1302 | return self.fail("TODO implement loading from MCValue.embedded_in_code", .{}); |
| 1303 | }, | 1303 | }, |
| 1304 | .register => { | 1304 | .register => |addr_reg| { |
| 1305 | return self.fail("TODO implement loading from MCValue.register for {}", .{self.target.cpu.arch}); | 1305 | self.register_manager.freezeRegs(&.{addr_reg}); |
| | 1306 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| | 1307 | |
| | 1308 | switch (dst_mcv) { |
| | 1309 | .dead => unreachable, |
| | 1310 | .undef => unreachable, |
| | 1311 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| | 1312 | .embedded_in_code => unreachable, |
| | 1313 | .stack_offset => |off| { |
| | 1314 | if (elem_ty.abiSize(self.target.*) <= 8) { |
| | 1315 | const tmp_reg = try self.register_manager.allocReg(null); |
| | 1316 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| | 1317 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| | 1318 | |
| | 1319 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| | 1320 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| | 1321 | } else { |
| | 1322 | // TODO optimize the register allocation |
| | 1323 | const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }); |
| | 1324 | self.register_manager.freezeRegs(&regs); |
| | 1325 | defer self.register_manager.unfreezeRegs(&regs); |
| | 1326 | |
| | 1327 | const src_reg = addr_reg; |
| | 1328 | const dst_reg = regs[0]; |
| | 1329 | const len_reg = regs[1]; |
| | 1330 | const count_reg = regs[2]; |
| | 1331 | const tmp_reg = regs[3]; |
| | 1332 | |
| | 1333 | // sub dst_reg, fp, #off |
| | 1334 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| | 1335 | const adj_off = off + elem_size; |
| | 1336 | const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{}); |
| | 1337 | _ = try self.addInst(.{ |
| | 1338 | .tag = .sub_immediate, |
| | 1339 | .data = .{ .rr_imm12_sh = .{ |
| | 1340 | .rd = dst_reg, |
| | 1341 | .rn = .x29, |
| | 1342 | .imm12 = offset, |
| | 1343 | } }, |
| | 1344 | }); |
| | 1345 | |
| | 1346 | // mov len, #elem_size |
| | 1347 | const len_imm = math.cast(u16, elem_size) catch return self.fail("TODO load: larger stack offsets", .{}); |
| | 1348 | _ = try self.addInst(.{ |
| | 1349 | .tag = .movk, |
| | 1350 | .data = .{ .r_imm16_sh = .{ |
| | 1351 | .rd = len_reg, |
| | 1352 | .imm16 = len_imm, |
| | 1353 | } }, |
| | 1354 | }); |
| | 1355 | |
| | 1356 | // memcpy(src, dst, len) |
| | 1357 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); |
| | 1358 | } |
| | 1359 | }, |
| | 1360 | else => return self.fail("TODO load from register into {}", .{dst_mcv}), |
| | 1361 | } |
| 1306 | }, | 1362 | }, |
| 1307 | .memory, | 1363 | .memory, |
| 1308 | .stack_offset, | 1364 | .stack_offset, |
| ... | @@ -1317,6 +1373,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1317,6 +1373,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1317 | } | 1373 | } |
| 1318 | } | 1374 | } |
| 1319 | | 1375 | |
| | 1376 | fn genInlineMemcpy( |
| | 1377 | self: *Self, |
| | 1378 | src: Register, |
| | 1379 | dst: Register, |
| | 1380 | len: Register, |
| | 1381 | count: Register, |
| | 1382 | tmp: Register, |
| | 1383 | ) !void { |
| | 1384 | // movk count, #0 |
| | 1385 | _ = try self.addInst(.{ |
| | 1386 | .tag = .movk, |
| | 1387 | .data = .{ .r_imm16_sh = .{ |
| | 1388 | .rd = count, |
| | 1389 | .imm16 = 0, |
| | 1390 | } }, |
| | 1391 | }); |
| | 1392 | |
| | 1393 | // loop: |
| | 1394 | // cmp count, len |
| | 1395 | _ = try self.addInst(.{ |
| | 1396 | .tag = .cmp_shifted_register, |
| | 1397 | .data = .{ .rrr_imm6_shift = .{ |
| | 1398 | .rd = .xzr, |
| | 1399 | .rn = count, |
| | 1400 | .rm = len, |
| | 1401 | .imm6 = 0, |
| | 1402 | .shift = .lsl, |
| | 1403 | } }, |
| | 1404 | }); |
| | 1405 | |
| | 1406 | // bge end |
| | 1407 | _ = try self.addInst(.{ |
| | 1408 | .tag = .b_cond, |
| | 1409 | .data = .{ .inst_cond = .{ |
| | 1410 | .inst = @intCast(u32, self.mir_instructions.len + 5), |
| | 1411 | .cond = .ge, |
| | 1412 | } }, |
| | 1413 | }); |
| | 1414 | |
| | 1415 | // ldrb tmp, [src, count] |
| | 1416 | _ = try self.addInst(.{ |
| | 1417 | .tag = .ldrb_register, |
| | 1418 | .data = .{ .load_store_register_register = .{ |
| | 1419 | .rt = tmp, |
| | 1420 | .rn = src, |
| | 1421 | .offset = Instruction.LoadStoreOffset.reg(count).register, |
| | 1422 | } }, |
| | 1423 | }); |
| | 1424 | |
| | 1425 | // strb tmp, [dest, count] |
| | 1426 | _ = try self.addInst(.{ |
| | 1427 | .tag = .strb_register, |
| | 1428 | .data = .{ .load_store_register_register = .{ |
| | 1429 | .rt = tmp, |
| | 1430 | .rn = dst, |
| | 1431 | .offset = Instruction.LoadStoreOffset.reg(count).register, |
| | 1432 | } }, |
| | 1433 | }); |
| | 1434 | |
| | 1435 | // add count, count, #1 |
| | 1436 | _ = try self.addInst(.{ |
| | 1437 | .tag = .add_immediate, |
| | 1438 | .data = .{ .rr_imm12_sh = .{ |
| | 1439 | .rd = count, |
| | 1440 | .rn = count, |
| | 1441 | .imm12 = 1, |
| | 1442 | } }, |
| | 1443 | }); |
| | 1444 | |
| | 1445 | // b loop |
| | 1446 | _ = try self.addInst(.{ |
| | 1447 | .tag = .b, |
| | 1448 | .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 5) }, |
| | 1449 | }); |
| | 1450 | |
| | 1451 | // end: |
| | 1452 | } |
| | 1453 | |
| 1320 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | 1454 | fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1321 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1455 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1322 | const elem_ty = self.air.typeOfIndex(inst); | 1456 | const elem_ty = self.air.typeOfIndex(inst); |