| ... | ... | @@ -1024,8 +1024,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1024 | 1024 | try self.code.append(0xcc); // int3 |
| 1025 | 1025 | }, |
| 1026 | 1026 | .riscv64 => { |
| 1027 | | const full = @bitCast(u32, Instructions.CallBreak{ |
| 1028 | | .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak), |
| 1027 | const full = @bitCast(u32, instructions.CallBreak{ |
| 1028 | .mode = @enumToInt(instructions.CallBreak.Mode.ebreak), |
| 1029 | 1029 | }); |
| 1030 | 1030 | |
| 1031 | 1031 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| ... | ... | @@ -1092,6 +1092,31 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1092 | 1092 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 1093 | 1093 | } |
| 1094 | 1094 | }, |
| 1095 | .riscv64 => { |
| 1096 | if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch}); |
| 1097 | |
| 1098 | if (inst.func.cast(ir.Inst.Constant)) |func_inst| { |
| 1099 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { |
| 1100 | const func = func_val.func; |
| 1101 | const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?]; |
| 1102 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1103 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 1104 | const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes); |
| 1105 | |
| 1106 | try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr }); |
| 1107 | const jalr = instructions.Jalr{ |
| 1108 | .rd = Register.ra.id(), |
| 1109 | .rs1 = Register.ra.id(), |
| 1110 | .offset = 0, |
| 1111 | }; |
| 1112 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr)); |
| 1113 | } else { |
| 1114 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1115 | } |
| 1116 | } else { |
| 1117 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 1118 | } |
| 1119 | }, |
| 1095 | 1120 | else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), |
| 1096 | 1121 | } |
| 1097 | 1122 | |
| ... | ... | @@ -1140,6 +1165,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1140 | 1165 | self.code.items[self.code.items.len - 5] = 0xe9; // jmp rel32 |
| 1141 | 1166 | try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4); |
| 1142 | 1167 | }, |
| 1168 | .riscv64 => { |
| 1169 | const jalr = instructions.Jalr{ |
| 1170 | .rd = Register.zero.id(), |
| 1171 | .rs1 = Register.ra.id(), |
| 1172 | .offset = 0, |
| 1173 | }; |
| 1174 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr)); |
| 1175 | }, |
| 1143 | 1176 | else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}), |
| 1144 | 1177 | } |
| 1145 | 1178 | return .unreach; |
| ... | ... | @@ -1346,8 +1379,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1346 | 1379 | } |
| 1347 | 1380 | |
| 1348 | 1381 | if (mem.eql(u8, inst.asm_source, "ecall")) { |
| 1349 | | const full = @bitCast(u32, Instructions.CallBreak{ |
| 1350 | | .mode = @enumToInt(Instructions.CallBreak.Mode.ecall), |
| 1382 | const full = @bitCast(u32, instructions.CallBreak{ |
| 1383 | .mode = @enumToInt(instructions.CallBreak.Mode.ecall), |
| 1351 | 1384 | }); |
| 1352 | 1385 | |
| 1353 | 1386 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full); |
| ... | ... | @@ -1560,8 +1593,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1560 | 1593 | .immediate => |unsigned_x| { |
| 1561 | 1594 | const x = @bitCast(i64, unsigned_x); |
| 1562 | 1595 | if (math.minInt(i12) <= x and x <= math.maxInt(i12)) { |
| 1563 | | const instruction = @bitCast(u32, Instructions.Addi{ |
| 1564 | | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| 1596 | const instruction = @bitCast(u32, instructions.Addi{ |
| 1597 | .mode = @enumToInt(instructions.Addi.Mode.addi), |
| 1565 | 1598 | .imm = @truncate(i12, x), |
| 1566 | 1599 | .rs1 = Register.zero.id(), |
| 1567 | 1600 | .rd = reg.id(), |
| ... | ... | @@ -1577,14 +1610,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1577 | 1610 | }, @truncate(i32, x)); |
| 1578 | 1611 | if (split.low12 < 0) return self.fail(src, "TODO support riscv64 genSetReg i32 immediates with 12th bit set to 1", .{}); |
| 1579 | 1612 | |
| 1580 | | const lui = @bitCast(u32, Instructions.Lui{ |
| 1613 | const lui = @bitCast(u32, instructions.Lui{ |
| 1581 | 1614 | .imm = split.up20, |
| 1582 | 1615 | .rd = reg.id(), |
| 1583 | 1616 | }); |
| 1584 | 1617 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), lui); |
| 1585 | 1618 | |
| 1586 | | const addi = @bitCast(u32, Instructions.Addi{ |
| 1587 | | .mode = @enumToInt(Instructions.Addi.Mode.addi), |
| 1619 | const addi = @bitCast(u32, instructions.Addi{ |
| 1620 | .mode = @enumToInt(instructions.Addi.Mode.addi), |
| 1588 | 1621 | .imm = @truncate(i12, split.low12), |
| 1589 | 1622 | .rs1 = reg.id(), |
| 1590 | 1623 | .rd = reg.id(), |
| ... | ... | @@ -1592,6 +1625,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1592 | 1625 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi); |
| 1593 | 1626 | return; |
| 1594 | 1627 | } |
| 1628 | // li rd, immediate |
| 1629 | // "Myriad sequences" |
| 1595 | 1630 | return self.fail(src, "TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf |
| 1596 | 1631 | }, |
| 1597 | 1632 | .memory => |addr| { |
| ... | ... | @@ -1599,8 +1634,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1599 | 1634 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 1600 | 1635 | try self.genSetReg(src, reg, .{ .immediate = addr }); |
| 1601 | 1636 | |
| 1602 | | const ld = @bitCast(u32, Instructions.Load{ |
| 1603 | | .mode = @enumToInt(Instructions.Load.Mode.ld), |
| 1637 | const ld = @bitCast(u32, instructions.Load{ |
| 1638 | .mode = @enumToInt(instructions.Load.Mode.ld), |
| 1604 | 1639 | .rs1 = reg.id(), |
| 1605 | 1640 | .rd = reg.id(), |
| 1606 | 1641 | .offset = 0, |
| ... | ... | @@ -2046,6 +2081,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2046 | 2081 | const FreeRegInt = @Type(.{ .Int = .{ .is_signed = false, .bits = callee_preserved_regs.len } }); |
| 2047 | 2082 | |
| 2048 | 2083 | fn parseRegName(name: []const u8) ?Register { |
| 2084 | if (@hasDecl(Register, "parseRegName")) { |
| 2085 | return Register.parseRegName(name); |
| 2086 | } |
| 2049 | 2087 | return std.meta.stringToEnum(Register, name); |
| 2050 | 2088 | } |
| 2051 | 2089 | |