| ... | ... | @@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1028 | 1028 | .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak), |
| 1029 | 1029 | }); |
| 1030 | 1030 | |
| 1031 | | try self.code.resize(self.code.items.len + 4); |
| 1032 | | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); |
| 1031 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| 1033 | 1032 | }, |
| 1034 | 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 | 1350 | .mode = @enumToInt(Instructions.CallBreak.Mode.ecall), |
| 1352 | 1351 | }); |
| 1353 | 1352 | |
| 1354 | | try self.code.resize(self.code.items.len + 4); |
| 1355 | | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); |
| 1353 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| 1356 | 1354 | } else { |
| 1357 | 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 | 1544 | fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void { |
| 1547 | 1545 | switch (arch) { |
| 1548 | 1546 | .riscv64 => switch (mcv) { |
| 1549 | | .immediate => |x| { |
| 1550 | | if (x > math.maxInt(u11)) { |
| 1551 | | return self.fail(src, "TODO genSetReg 12+ bit immediates for riscv64", .{}); |
| 1547 | .dead => unreachable, |
| 1548 | .ptr_stack_offset => unreachable, |
| 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 { |
| 1554 | | opcode: u7, |
| 1555 | | rd: u5, |
| 1556 | | mode: u3, |
| 1557 | | rsi1: u5, |
| 1558 | | imm: u11, |
| 1559 | | signextend: u1 = 0, |
| 1560 | | }; |
| 1561 | | const full = @bitCast(u32, Instructions.Addi{ |
| 1562 | | .imm = @intCast(u11, x), |
| 1563 | | .rsi1 = Register.zero.id(), |
| 1564 | | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| 1559 | }, |
| 1560 | .immediate => |unsigned_x| { |
| 1561 | const x = @bitCast(i64, unsigned_x); |
| 1562 | if (math.minInt(i12) <= x and x <= math.maxInt(i12)) { |
| 1563 | const instruction = @bitCast(u32, Instructions.Addi{ |
| 1564 | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| 1565 | .imm = @truncate(i12, x), |
| 1566 | .rs1 = Register.zero.id(), |
| 1567 | .rd = reg.id(), |
| 1568 | }); |
| 1569 | |
| 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 | 1605 | .rd = reg.id(), |
| 1606 | .offset = 0, |
| 1566 | 1607 | }); |
| 1567 | 1608 | |
| 1568 | | try self.code.resize(self.code.items.len + 4); |
| 1569 | | mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full); |
| 1609 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), ld); |
| 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 | 1616 | .x86_64 => switch (mcv) { |
| 1574 | 1617 | .dead => unreachable, |