| ... | @@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1028 | .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak), | 1028 | .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak), |
| 1029 | }); | 1029 | }); |
| 1030 | | 1030 | |
| 1031 | try self.code.resize(self.code.items.len + 4); | 1031 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| 1032 | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); | | |
| 1033 | }, | 1032 | }, |
| 1034 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), | 1033 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), |
| 1035 | } | 1034 | } |
| ... | @@ -1351,8 +1350,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1351,8 +1350,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1351 | .mode = @enumToInt(Instructions.CallBreak.Mode.ecall), | 1350 | .mode = @enumToInt(Instructions.CallBreak.Mode.ecall), |
| 1352 | }); | 1351 | }); |
| 1353 | | 1352 | |
| 1354 | try self.code.resize(self.code.items.len + 4); | 1353 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| 1355 | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); | | |
| 1356 | } else { | 1354 | } else { |
| 1357 | return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{}); | 1355 | return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{}); |
| 1358 | } | 1356 | } |
| ... | @@ -1546,29 +1544,74 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1546,29 +1544,74 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1546 | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { | 1544 | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { |
| 1547 | switch (arch) { | 1545 | switch (arch) { |
| 1548 | .riscv64 => switch (mcv) { | 1546 | .riscv64 => switch (mcv) { |
| 1549 | .immediate => |x| { | 1547 | .dead => unreachable, |
| 1550 | if (x > math.maxInt(u11)) { | 1548 | .ptr_stack_offset => unreachable, |
| 1551 | return self.fail(src, "TODO genSetReg 12+ bit immediates for riscv64", .{}); | 1549 | .ptr_embedded_in_code => unreachable, |
| | 1550 | .unreach, .none => return, // Nothing to do. |
| | 1551 | .undef => { |
| | 1552 | if (!self.wantSafety()) |
| | 1553 | return; // The already existing value will do just fine. |
| | 1554 | // Write the debug undefined value. |
| | 1555 | switch (reg.size()) { |
| | 1556 | 64 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), |
| | 1557 | else => unreachable, |
| 1552 | } | 1558 | } |
| 1553 | const Instruction = packed struct { | 1559 | }, |
| 1554 | opcode: u7, | 1560 | .immediate => |unsigned_x| { |
| 1555 | rd: u5, | 1561 | const x = @bitCast(i64, unsigned_x); |
| 1556 | mode: u3, | 1562 | if (math.minInt(i12) <= x and x <= math.maxInt(i12)) { |
| 1557 | rsi1: u5, | 1563 | const instruction = @bitCast(u32, Instructions.Addi{ |
| 1558 | imm: u11, | 1564 | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| 1559 | signextend: u1 = 0, | 1565 | .imm = @truncate(i12, x), |
| 1560 | }; | 1566 | .rs1 = Register.zero.id(), |
| 1561 | const full = @bitCast(u32, Instructions.Addi{ | 1567 | .rd = reg.id(), |
| 1562 | .imm = @intCast(u11, x), | 1568 | }); |
| 1563 | .rsi1 = Register.zero.id(), | 1569 | |
| 1564 | .mode = @enumToInt(Instructions.Addi.Mode.addi), | 1570 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), instruction); |
| | 1571 | return; |
| | 1572 | } |
| | 1573 | if (math.minInt(i32) <= x and x <= math.maxInt(i32)) { |
| | 1574 | const split = @bitCast(packed struct { |
| | 1575 | low12: i12, |
| | 1576 | up20: i20, |
| | 1577 | }, @truncate(i32, x)); |
| | 1578 | if (split.low12 < 0) return self.fail(src, "TODO support riscv64 genSetReg i32 immediates with 12th bit set to 1", .{}); |
| | 1579 | |
| | 1580 | const lui = @bitCast(u32, Instructions.Lui{ |
| | 1581 | .imm = split.up20, |
| | 1582 | .rd = reg.id(), |
| | 1583 | }); |
| | 1584 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), lui); |
| | 1585 | |
| | 1586 | const addi = @bitCast(u32, Instructions.Addi{ |
| | 1587 | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| | 1588 | .imm = @truncate(i12, split.low12), |
| | 1589 | .rs1 = reg.id(), |
| | 1590 | .rd = reg.id(), |
| | 1591 | }); |
| | 1592 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi); |
| | 1593 | return; |
| | 1594 | } |
| | 1595 | return self.fail(src, "TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf |
| | 1596 | }, |
| | 1597 | .memory => |addr| { |
| | 1598 | // The value is in memory at a hard-coded address. |
| | 1599 | // If the type is a pointer, it means the pointer address is at this memory location. |
| | 1600 | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| | 1601 | |
| | 1602 | const ld = @bitCast(u32, Instructions.Load{ |
| | 1603 | .mode = @enumToInt(Instructions.Load.Mode.ld), |
| | 1604 | .rs1 = reg.id(), |
| 1565 | .rd = reg.id(), | 1605 | .rd = reg.id(), |
| | 1606 | .offset = 0, |
| 1566 | }); | 1607 | }); |
| 1567 | | 1608 | |
| 1568 | try self.code.resize(self.code.items.len + 4); | 1609 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), ld); |
| 1569 | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); | 1610 | // LOAD imm=[i12 offset = 0], rs1 = |
| | 1611 | |
| | 1612 | // return self.fail("TODO implement genSetReg memory for riscv64"); |
| 1570 | }, | 1613 | }, |
| 1571 | else => return self.fail(src, "TODO implement getSetReg for riscv64 MCValue {}", .{mcv}), | 1614 | else => return self.fail(src, "TODO implement getSetReg for riscv64 {}", .{mcv}), |
| 1572 | }, | 1615 | }, |
| 1573 | .x86_64 => switch (mcv) { | 1616 | .x86_64 => switch (mcv) { |
| 1574 | .dead => unreachable, | 1617 | .dead => unreachable, |