| author | |
| committer | |
| log | 1a7d89a84d7fef87eb45da8207bbeb852e3f0c02 |
| tree | 1d7306a194386d23d2ddfa3611c07613f68dbece |
| parent | 574028ed5ec6ad455961ed46babdb7a5fe9f68bb |
| signature | Commit is signed but in an unrecognized format. |
19 files changed, 1720 insertions(+), 2391 deletions(-)
CMakeLists.txt+2-2| ... | @@ -539,10 +539,10 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -539,10 +539,10 @@ set(ZIG_STAGE2_SOURCES |
| 539 | src/arch/riscv64/bits.zig | 539 | src/arch/riscv64/bits.zig |
| 540 | src/arch/riscv64/CodeGen.zig | 540 | src/arch/riscv64/CodeGen.zig |
| 541 | src/arch/riscv64/Emit.zig | 541 | src/arch/riscv64/Emit.zig |
| 542 | src/arch/riscv64/encoder.zig | 542 | src/arch/riscv64/encoding.zig |
| 543 | src/arch/riscv64/Encoding.zig | ||
| 544 | src/arch/riscv64/Lower.zig | 543 | src/arch/riscv64/Lower.zig |
| 545 | src/arch/riscv64/Mir.zig | 544 | src/arch/riscv64/Mir.zig |
| 545 | src/arch/riscv64/mnem.zig | ||
| 546 | src/arch/sparc64/CodeGen.zig | 546 | src/arch/sparc64/CodeGen.zig |
| 547 | src/arch/sparc64/Emit.zig | 547 | src/arch/sparc64/Emit.zig |
| 548 | src/arch/sparc64/Mir.zig | 548 | src/arch/sparc64/Mir.zig |
lib/compiler/test_runner.zig-1| ... | @@ -271,7 +271,6 @@ pub fn mainSimple() anyerror!void { | ... | @@ -271,7 +271,6 @@ pub fn mainSimple() anyerror!void { |
| 271 | }; | 271 | }; |
| 272 | // is the backend capable of using std.fmt.format to print a summary at the end? | 272 | // is the backend capable of using std.fmt.format to print a summary at the end? |
| 273 | const print_summary = switch (builtin.zig_backend) { | 273 | const print_summary = switch (builtin.zig_backend) { |
| 274 | .stage2_riscv64 => true, | ||
| 275 | else => false, | 274 | else => false, |
| 276 | }; | 275 | }; |
| 277 | 276 |
src/arch/riscv64/CodeGen.zig+217-306| ... | @@ -20,6 +20,7 @@ const InternPool = @import("../../InternPool.zig"); | ... | @@ -20,6 +20,7 @@ const InternPool = @import("../../InternPool.zig"); |
| 20 | const Compilation = @import("../../Compilation.zig"); | 20 | const Compilation = @import("../../Compilation.zig"); |
| 21 | const trace = @import("../../tracy.zig").trace; | 21 | const trace = @import("../../tracy.zig").trace; |
| 22 | const codegen = @import("../../codegen.zig"); | 22 | const codegen = @import("../../codegen.zig"); |
| 23 | const Mnemonic = @import("mnem.zig").Mnemonic; | ||
| 23 | 24 | ||
| 24 | const ErrorMsg = Zcu.ErrorMsg; | 25 | const ErrorMsg = Zcu.ErrorMsg; |
| 25 | const Target = std.Target; | 26 | const Target = std.Target; |
| ... | @@ -65,7 +66,6 @@ arg_index: usize, | ... | @@ -65,7 +66,6 @@ arg_index: usize, |
| 65 | src_loc: Zcu.LazySrcLoc, | 66 | src_loc: Zcu.LazySrcLoc, |
| 66 | 67 | ||
| 67 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | 68 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| 68 | mir_extra: std.ArrayListUnmanaged(u32) = .{}, | ||
| 69 | 69 | ||
| 70 | owner: Owner, | 70 | owner: Owner, |
| 71 | 71 | ||
| ... | @@ -794,7 +794,6 @@ pub fn generate( | ... | @@ -794,7 +794,6 @@ pub fn generate( |
| 794 | function.const_tracking.deinit(gpa); | 794 | function.const_tracking.deinit(gpa); |
| 795 | function.exitlude_jump_relocs.deinit(gpa); | 795 | function.exitlude_jump_relocs.deinit(gpa); |
| 796 | function.mir_instructions.deinit(gpa); | 796 | function.mir_instructions.deinit(gpa); |
| 797 | function.mir_extra.deinit(gpa); | ||
| 798 | } | 797 | } |
| 799 | 798 | ||
| 800 | wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); | 799 | wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)}); |
| ... | @@ -855,7 +854,6 @@ pub fn generate( | ... | @@ -855,7 +854,6 @@ pub fn generate( |
| 855 | 854 | ||
| 856 | var mir: Mir = .{ | 855 | var mir: Mir = .{ |
| 857 | .instructions = function.mir_instructions.toOwnedSlice(), | 856 | .instructions = function.mir_instructions.toOwnedSlice(), |
| 858 | .extra = try function.mir_extra.toOwnedSlice(gpa), | ||
| 859 | .frame_locs = function.frame_locs.toOwnedSlice(), | 857 | .frame_locs = function.frame_locs.toOwnedSlice(), |
| 860 | }; | 858 | }; |
| 861 | defer mir.deinit(gpa); | 859 | defer mir.deinit(gpa); |
| ... | @@ -940,10 +938,7 @@ pub fn generateLazy( | ... | @@ -940,10 +938,7 @@ pub fn generateLazy( |
| 940 | .avl = null, | 938 | .avl = null, |
| 941 | .vtype = null, | 939 | .vtype = null, |
| 942 | }; | 940 | }; |
| 943 | defer { | 941 | defer function.mir_instructions.deinit(gpa); |
| 944 | function.mir_instructions.deinit(gpa); | ||
| 945 | function.mir_extra.deinit(gpa); | ||
| 946 | } | ||
| 947 | 942 | ||
| 948 | function.genLazy(lazy_sym) catch |err| switch (err) { | 943 | function.genLazy(lazy_sym) catch |err| switch (err) { |
| 949 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, | 944 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, |
| ... | @@ -955,7 +950,6 @@ pub fn generateLazy( | ... | @@ -955,7 +950,6 @@ pub fn generateLazy( |
| 955 | 950 | ||
| 956 | var mir: Mir = .{ | 951 | var mir: Mir = .{ |
| 957 | .instructions = function.mir_instructions.toOwnedSlice(), | 952 | .instructions = function.mir_instructions.toOwnedSlice(), |
| 958 | .extra = try function.mir_extra.toOwnedSlice(gpa), | ||
| 959 | .frame_locs = function.frame_locs.toOwnedSlice(), | 953 | .frame_locs = function.frame_locs.toOwnedSlice(), |
| 960 | }; | 954 | }; |
| 961 | defer mir.deinit(gpa); | 955 | defer mir.deinit(gpa); |
| ... | @@ -1022,7 +1016,6 @@ fn formatWipMir( | ... | @@ -1022,7 +1016,6 @@ fn formatWipMir( |
| 1022 | .allocator = data.func.gpa, | 1016 | .allocator = data.func.gpa, |
| 1023 | .mir = .{ | 1017 | .mir = .{ |
| 1024 | .instructions = data.func.mir_instructions.slice(), | 1018 | .instructions = data.func.mir_instructions.slice(), |
| 1025 | .extra = data.func.mir_extra.items, | ||
| 1026 | .frame_locs = data.func.frame_locs.slice(), | 1019 | .frame_locs = data.func.frame_locs.slice(), |
| 1027 | }, | 1020 | }, |
| 1028 | .cc = .Unspecified, | 1021 | .cc = .Unspecified, |
| ... | @@ -1120,7 +1113,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { | ... | @@ -1120,7 +1113,7 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1120 | try func.mir_instructions.ensureUnusedCapacity(gpa, 1); | 1113 | try func.mir_instructions.ensureUnusedCapacity(gpa, 1); |
| 1121 | const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len); | 1114 | const result_index: Mir.Inst.Index = @intCast(func.mir_instructions.len); |
| 1122 | func.mir_instructions.appendAssumeCapacity(inst); | 1115 | func.mir_instructions.appendAssumeCapacity(inst); |
| 1123 | if (inst.tag != .pseudo or switch (inst.ops) { | 1116 | if (switch (inst.tag) { |
| 1124 | else => true, | 1117 | else => true, |
| 1125 | .pseudo_dbg_prologue_end, | 1118 | .pseudo_dbg_prologue_end, |
| 1126 | .pseudo_dbg_line_column, | 1119 | .pseudo_dbg_line_column, |
| ... | @@ -1131,49 +1124,13 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { | ... | @@ -1131,49 +1124,13 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 1131 | return result_index; | 1124 | return result_index; |
| 1132 | } | 1125 | } |
| 1133 | 1126 | ||
| 1134 | fn addNop(func: *Func) error{OutOfMemory}!Mir.Inst.Index { | 1127 | fn addPseudo(func: *Func, mnem: Mnemonic) error{OutOfMemory}!Mir.Inst.Index { |
| 1135 | return func.addInst(.{ | ||
| 1136 | .tag = .nop, | ||
| 1137 | .ops = .none, | ||
| 1138 | .data = undefined, | ||
| 1139 | }); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | fn addPseudoNone(func: *Func, ops: Mir.Inst.Ops) !void { | ||
| 1143 | _ = try func.addInst(.{ | ||
| 1144 | .tag = .pseudo, | ||
| 1145 | .ops = ops, | ||
| 1146 | .data = undefined, | ||
| 1147 | }); | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | fn addPseudo(func: *Func, ops: Mir.Inst.Ops) !Mir.Inst.Index { | ||
| 1151 | return func.addInst(.{ | 1128 | return func.addInst(.{ |
| 1152 | .tag = .pseudo, | 1129 | .tag = mnem, |
| 1153 | .ops = ops, | 1130 | .data = .none, |
| 1154 | .data = undefined, | ||
| 1155 | }); | 1131 | }); |
| 1156 | } | 1132 | } |
| 1157 | 1133 | ||
| 1158 | pub fn addExtra(func: *Func, extra: anytype) Allocator.Error!u32 { | ||
| 1159 | const fields = std.meta.fields(@TypeOf(extra)); | ||
| 1160 | try func.mir_extra.ensureUnusedCapacity(func.gpa, fields.len); | ||
| 1161 | return func.addExtraAssumeCapacity(extra); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | pub fn addExtraAssumeCapacity(func: *Func, extra: anytype) u32 { | ||
| 1165 | const fields = std.meta.fields(@TypeOf(extra)); | ||
| 1166 | const result: u32 = @intCast(func.mir_extra.items.len); | ||
| 1167 | inline for (fields) |field| { | ||
| 1168 | func.mir_extra.appendAssumeCapacity(switch (field.type) { | ||
| 1169 | u32 => @field(extra, field.name), | ||
| 1170 | i32 => @bitCast(@field(extra, field.name)), | ||
| 1171 | else => @compileError("bad field type"), | ||
| 1172 | }); | ||
| 1173 | } | ||
| 1174 | return result; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | /// Returns a temporary register that contains the value of the `reg` csr. | 1134 | /// Returns a temporary register that contains the value of the `reg` csr. |
| 1178 | /// | 1135 | /// |
| 1179 | /// Caller's duty to lock the return register is needed. | 1136 | /// Caller's duty to lock the return register is needed. |
| ... | @@ -1182,14 +1139,11 @@ fn getCsr(func: *Func, csr: CSR) !Register { | ... | @@ -1182,14 +1139,11 @@ fn getCsr(func: *Func, csr: CSR) !Register { |
| 1182 | const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.u64)); | 1139 | const dst_reg = try func.register_manager.allocReg(null, func.regTempClassForType(Type.u64)); |
| 1183 | _ = try func.addInst(.{ | 1140 | _ = try func.addInst(.{ |
| 1184 | .tag = .csrrs, | 1141 | .tag = .csrrs, |
| 1185 | .ops = .csr, | 1142 | .data = .{ .csr = .{ |
| 1186 | .data = .{ | 1143 | .csr = csr, |
| 1187 | .csr = .{ | 1144 | .rd = dst_reg, |
| 1188 | .csr = csr, | 1145 | .rs1 = .x0, |
| 1189 | .rd = dst_reg, | 1146 | } }, |
| 1190 | .rs1 = .x0, | ||
| 1191 | }, | ||
| 1192 | }, | ||
| 1193 | }); | 1147 | }); |
| 1194 | return dst_reg; | 1148 | return dst_reg; |
| 1195 | } | 1149 | } |
| ... | @@ -1208,7 +1162,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { | ... | @@ -1208,7 +1162,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { |
| 1208 | const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options)); | 1162 | const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options)); |
| 1209 | _ = try func.addInst(.{ | 1163 | _ = try func.addInst(.{ |
| 1210 | .tag = .vsetvli, | 1164 | .tag = .vsetvli, |
| 1211 | .ops = .rri, | ||
| 1212 | .data = .{ .i_type = .{ | 1165 | .data = .{ .i_type = .{ |
| 1213 | .rd = dst_reg, | 1166 | .rd = dst_reg, |
| 1214 | .rs1 = .zero, | 1167 | .rs1 = .zero, |
| ... | @@ -1221,7 +1174,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { | ... | @@ -1221,7 +1174,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { |
| 1221 | const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options)); | 1174 | const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options)); |
| 1222 | _ = try func.addInst(.{ | 1175 | _ = try func.addInst(.{ |
| 1223 | .tag = .vsetivli, | 1176 | .tag = .vsetivli, |
| 1224 | .ops = .rri, | ||
| 1225 | .data = .{ | 1177 | .data = .{ |
| 1226 | .i_type = .{ | 1178 | .i_type = .{ |
| 1227 | .rd = dst_reg, | 1179 | .rd = dst_reg, |
| ... | @@ -1235,7 +1187,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { | ... | @@ -1235,7 +1187,6 @@ fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void { |
| 1235 | const temp_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = avl }); | 1187 | const temp_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = avl }); |
| 1236 | _ = try func.addInst(.{ | 1188 | _ = try func.addInst(.{ |
| 1237 | .tag = .vsetvli, | 1189 | .tag = .vsetvli, |
| 1238 | .ops = .rri, | ||
| 1239 | .data = .{ .i_type = .{ | 1190 | .data = .{ .i_type = .{ |
| 1240 | .rd = dst_reg, | 1191 | .rd = dst_reg, |
| 1241 | .rs1 = temp_reg, | 1192 | .rs1 = temp_reg, |
| ... | @@ -1270,7 +1221,7 @@ fn gen(func: *Func) !void { | ... | @@ -1270,7 +1221,7 @@ fn gen(func: *Func) !void { |
| 1270 | } | 1221 | } |
| 1271 | 1222 | ||
| 1272 | if (fn_info.cc != .Naked) { | 1223 | if (fn_info.cc != .Naked) { |
| 1273 | try func.addPseudoNone(.pseudo_dbg_prologue_end); | 1224 | _ = try func.addPseudo(.pseudo_dbg_prologue_end); |
| 1274 | 1225 | ||
| 1275 | const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead); | 1226 | const backpatch_stack_alloc = try func.addPseudo(.pseudo_dead); |
| 1276 | const backpatch_ra_spill = try func.addPseudo(.pseudo_dead); | 1227 | const backpatch_ra_spill = try func.addPseudo(.pseudo_dead); |
| ... | @@ -1300,11 +1251,11 @@ fn gen(func: *Func) !void { | ... | @@ -1300,11 +1251,11 @@ fn gen(func: *Func) !void { |
| 1300 | try func.genBody(func.air.getMainBody()); | 1251 | try func.genBody(func.air.getMainBody()); |
| 1301 | 1252 | ||
| 1302 | for (func.exitlude_jump_relocs.items) |jmp_reloc| { | 1253 | for (func.exitlude_jump_relocs.items) |jmp_reloc| { |
| 1303 | func.mir_instructions.items(.data)[jmp_reloc].inst = | 1254 | func.mir_instructions.items(.data)[jmp_reloc].j_type.inst = |
| 1304 | @intCast(func.mir_instructions.len); | 1255 | @intCast(func.mir_instructions.len); |
| 1305 | } | 1256 | } |
| 1306 | 1257 | ||
| 1307 | try func.addPseudoNone(.pseudo_dbg_epilogue_begin); | 1258 | _ = try func.addPseudo(.pseudo_dbg_epilogue_begin); |
| 1308 | 1259 | ||
| 1309 | const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead); | 1260 | const backpatch_restore_callee_preserved_regs = try func.addPseudo(.pseudo_dead); |
| 1310 | const backpatch_ra_restore = try func.addPseudo(.pseudo_dead); | 1261 | const backpatch_ra_restore = try func.addPseudo(.pseudo_dead); |
| ... | @@ -1314,7 +1265,6 @@ fn gen(func: *Func) !void { | ... | @@ -1314,7 +1265,6 @@ fn gen(func: *Func) !void { |
| 1314 | // ret | 1265 | // ret |
| 1315 | _ = try func.addInst(.{ | 1266 | _ = try func.addInst(.{ |
| 1316 | .tag = .jalr, | 1267 | .tag = .jalr, |
| 1317 | .ops = .rri, | ||
| 1318 | .data = .{ | 1268 | .data = .{ |
| 1319 | .i_type = .{ | 1269 | .i_type = .{ |
| 1320 | .rd = .zero, | 1270 | .rd = .zero, |
| ... | @@ -1329,7 +1279,6 @@ fn gen(func: *Func) !void { | ... | @@ -1329,7 +1279,6 @@ fn gen(func: *Func) !void { |
| 1329 | 1279 | ||
| 1330 | func.mir_instructions.set(backpatch_stack_alloc, .{ | 1280 | func.mir_instructions.set(backpatch_stack_alloc, .{ |
| 1331 | .tag = .addi, | 1281 | .tag = .addi, |
| 1332 | .ops = .rri, | ||
| 1333 | .data = .{ .i_type = .{ | 1282 | .data = .{ .i_type = .{ |
| 1334 | .rd = .sp, | 1283 | .rd = .sp, |
| 1335 | .rs1 = .sp, | 1284 | .rs1 = .sp, |
| ... | @@ -1337,8 +1286,7 @@ fn gen(func: *Func) !void { | ... | @@ -1337,8 +1286,7 @@ fn gen(func: *Func) !void { |
| 1337 | } }, | 1286 | } }, |
| 1338 | }); | 1287 | }); |
| 1339 | func.mir_instructions.set(backpatch_ra_spill, .{ | 1288 | func.mir_instructions.set(backpatch_ra_spill, .{ |
| 1340 | .tag = .pseudo, | 1289 | .tag = .pseudo_store_rm, |
| 1341 | .ops = .pseudo_store_rm, | ||
| 1342 | .data = .{ .rm = .{ | 1290 | .data = .{ .rm = .{ |
| 1343 | .r = .ra, | 1291 | .r = .ra, |
| 1344 | .m = .{ | 1292 | .m = .{ |
| ... | @@ -1348,8 +1296,7 @@ fn gen(func: *Func) !void { | ... | @@ -1348,8 +1296,7 @@ fn gen(func: *Func) !void { |
| 1348 | } }, | 1296 | } }, |
| 1349 | }); | 1297 | }); |
| 1350 | func.mir_instructions.set(backpatch_ra_restore, .{ | 1298 | func.mir_instructions.set(backpatch_ra_restore, .{ |
| 1351 | .tag = .pseudo, | 1299 | .tag = .pseudo_load_rm, |
| 1352 | .ops = .pseudo_load_rm, | ||
| 1353 | .data = .{ .rm = .{ | 1300 | .data = .{ .rm = .{ |
| 1354 | .r = .ra, | 1301 | .r = .ra, |
| 1355 | .m = .{ | 1302 | .m = .{ |
| ... | @@ -1359,8 +1306,7 @@ fn gen(func: *Func) !void { | ... | @@ -1359,8 +1306,7 @@ fn gen(func: *Func) !void { |
| 1359 | } }, | 1306 | } }, |
| 1360 | }); | 1307 | }); |
| 1361 | func.mir_instructions.set(backpatch_fp_spill, .{ | 1308 | func.mir_instructions.set(backpatch_fp_spill, .{ |
| 1362 | .tag = .pseudo, | 1309 | .tag = .pseudo_store_rm, |
| 1363 | .ops = .pseudo_store_rm, | ||
| 1364 | .data = .{ .rm = .{ | 1310 | .data = .{ .rm = .{ |
| 1365 | .r = .s0, | 1311 | .r = .s0, |
| 1366 | .m = .{ | 1312 | .m = .{ |
| ... | @@ -1370,8 +1316,7 @@ fn gen(func: *Func) !void { | ... | @@ -1370,8 +1316,7 @@ fn gen(func: *Func) !void { |
| 1370 | } }, | 1316 | } }, |
| 1371 | }); | 1317 | }); |
| 1372 | func.mir_instructions.set(backpatch_fp_restore, .{ | 1318 | func.mir_instructions.set(backpatch_fp_restore, .{ |
| 1373 | .tag = .pseudo, | 1319 | .tag = .pseudo_load_rm, |
| 1374 | .ops = .pseudo_load_rm, | ||
| 1375 | .data = .{ .rm = .{ | 1320 | .data = .{ .rm = .{ |
| 1376 | .r = .s0, | 1321 | .r = .s0, |
| 1377 | .m = .{ | 1322 | .m = .{ |
| ... | @@ -1382,7 +1327,6 @@ fn gen(func: *Func) !void { | ... | @@ -1382,7 +1327,6 @@ fn gen(func: *Func) !void { |
| 1382 | }); | 1327 | }); |
| 1383 | func.mir_instructions.set(backpatch_fp_add, .{ | 1328 | func.mir_instructions.set(backpatch_fp_add, .{ |
| 1384 | .tag = .addi, | 1329 | .tag = .addi, |
| 1385 | .ops = .rri, | ||
| 1386 | .data = .{ .i_type = .{ | 1330 | .data = .{ .i_type = .{ |
| 1387 | .rd = .s0, | 1331 | .rd = .s0, |
| 1388 | .rs1 = .sp, | 1332 | .rs1 = .sp, |
| ... | @@ -1391,7 +1335,6 @@ fn gen(func: *Func) !void { | ... | @@ -1391,7 +1335,6 @@ fn gen(func: *Func) !void { |
| 1391 | }); | 1335 | }); |
| 1392 | func.mir_instructions.set(backpatch_stack_alloc_restore, .{ | 1336 | func.mir_instructions.set(backpatch_stack_alloc_restore, .{ |
| 1393 | .tag = .addi, | 1337 | .tag = .addi, |
| 1394 | .ops = .rri, | ||
| 1395 | .data = .{ .i_type = .{ | 1338 | .data = .{ .i_type = .{ |
| 1396 | .rd = .sp, | 1339 | .rd = .sp, |
| 1397 | .rs1 = .sp, | 1340 | .rs1 = .sp, |
| ... | @@ -1401,27 +1344,24 @@ fn gen(func: *Func) !void { | ... | @@ -1401,27 +1344,24 @@ fn gen(func: *Func) !void { |
| 1401 | 1344 | ||
| 1402 | if (need_save_reg) { | 1345 | if (need_save_reg) { |
| 1403 | func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{ | 1346 | func.mir_instructions.set(backpatch_spill_callee_preserved_regs, .{ |
| 1404 | .tag = .pseudo, | 1347 | .tag = .pseudo_spill_regs, |
| 1405 | .ops = .pseudo_spill_regs, | ||
| 1406 | .data = .{ .reg_list = frame_layout.save_reg_list }, | 1348 | .data = .{ .reg_list = frame_layout.save_reg_list }, |
| 1407 | }); | 1349 | }); |
| 1408 | 1350 | ||
| 1409 | func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{ | 1351 | func.mir_instructions.set(backpatch_restore_callee_preserved_regs, .{ |
| 1410 | .tag = .pseudo, | 1352 | .tag = .pseudo_restore_regs, |
| 1411 | .ops = .pseudo_restore_regs, | ||
| 1412 | .data = .{ .reg_list = frame_layout.save_reg_list }, | 1353 | .data = .{ .reg_list = frame_layout.save_reg_list }, |
| 1413 | }); | 1354 | }); |
| 1414 | } | 1355 | } |
| 1415 | } else { | 1356 | } else { |
| 1416 | try func.addPseudoNone(.pseudo_dbg_prologue_end); | 1357 | _ = try func.addPseudo(.pseudo_dbg_prologue_end); |
| 1417 | try func.genBody(func.air.getMainBody()); | 1358 | try func.genBody(func.air.getMainBody()); |
| 1418 | try func.addPseudoNone(.pseudo_dbg_epilogue_begin); | 1359 | _ = try func.addPseudo(.pseudo_dbg_epilogue_begin); |
| 1419 | } | 1360 | } |
| 1420 | 1361 | ||
| 1421 | // Drop them off at the rbrace. | 1362 | // Drop them off at the rbrace. |
| 1422 | _ = try func.addInst(.{ | 1363 | _ = try func.addInst(.{ |
| 1423 | .tag = .pseudo, | 1364 | .tag = .pseudo_dbg_line_column, |
| 1424 | .ops = .pseudo_dbg_line_column, | ||
| 1425 | .data = .{ .pseudo_dbg_line_column = .{ | 1365 | .data = .{ .pseudo_dbg_line_column = .{ |
| 1426 | .line = func.end_di_line, | 1366 | .line = func.end_di_line, |
| 1427 | .column = func.end_di_column, | 1367 | .column = func.end_di_column, |
| ... | @@ -1493,9 +1433,11 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { | ... | @@ -1493,9 +1433,11 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1493 | ); | 1433 | ); |
| 1494 | 1434 | ||
| 1495 | exitlude_jump_reloc.* = try func.addInst(.{ | 1435 | exitlude_jump_reloc.* = try func.addInst(.{ |
| 1496 | .tag = .pseudo, | 1436 | .tag = .pseudo_j, |
| 1497 | .ops = .pseudo_j, | 1437 | .data = .{ .j_type = .{ |
| 1498 | .data = .{ .inst = undefined }, | 1438 | .rd = .zero, |
| 1439 | .inst = undefined, | ||
| 1440 | } }, | ||
| 1499 | }); | 1441 | }); |
| 1500 | func.performReloc(skip_reloc); | 1442 | func.performReloc(skip_reloc); |
| 1501 | 1443 | ||
| ... | @@ -1508,7 +1450,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { | ... | @@ -1508,7 +1450,7 @@ fn genLazy(func: *Func, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1508 | 1450 | ||
| 1509 | _ = try func.addInst(.{ | 1451 | _ = try func.addInst(.{ |
| 1510 | .tag = .jalr, | 1452 | .tag = .jalr, |
| 1511 | .ops = .rri, | 1453 | |
| 1512 | .data = .{ | 1454 | .data = .{ |
| 1513 | .i_type = .{ | 1455 | .i_type = .{ |
| 1514 | .rd = .zero, | 1456 | .rd = .zero, |
| ... | @@ -2041,7 +1983,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { | ... | @@ -2041,7 +1983,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { |
| 2041 | .signed => { | 1983 | .signed => { |
| 2042 | _ = try func.addInst(.{ | 1984 | _ = try func.addInst(.{ |
| 2043 | .tag = .slli, | 1985 | .tag = .slli, |
| 2044 | .ops = .rri, | 1986 | |
| 2045 | .data = .{ | 1987 | .data = .{ |
| 2046 | .i_type = .{ | 1988 | .i_type = .{ |
| 2047 | .rd = reg, | 1989 | .rd = reg, |
| ... | @@ -2052,7 +1994,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { | ... | @@ -2052,7 +1994,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { |
| 2052 | }); | 1994 | }); |
| 2053 | _ = try func.addInst(.{ | 1995 | _ = try func.addInst(.{ |
| 2054 | .tag = .srai, | 1996 | .tag = .srai, |
| 2055 | .ops = .rri, | 1997 | |
| 2056 | .data = .{ | 1998 | .data = .{ |
| 2057 | .i_type = .{ | 1999 | .i_type = .{ |
| 2058 | .rd = reg, | 2000 | .rd = reg, |
| ... | @@ -2067,7 +2009,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { | ... | @@ -2067,7 +2009,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { |
| 2067 | if (mask < 256) { | 2009 | if (mask < 256) { |
| 2068 | _ = try func.addInst(.{ | 2010 | _ = try func.addInst(.{ |
| 2069 | .tag = .andi, | 2011 | .tag = .andi, |
| 2070 | .ops = .rri, | 2012 | |
| 2071 | .data = .{ | 2013 | .data = .{ |
| 2072 | .i_type = .{ | 2014 | .i_type = .{ |
| 2073 | .rd = reg, | 2015 | .rd = reg, |
| ... | @@ -2079,7 +2021,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { | ... | @@ -2079,7 +2021,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { |
| 2079 | } else { | 2021 | } else { |
| 2080 | _ = try func.addInst(.{ | 2022 | _ = try func.addInst(.{ |
| 2081 | .tag = .slli, | 2023 | .tag = .slli, |
| 2082 | .ops = .rri, | 2024 | |
| 2083 | .data = .{ | 2025 | .data = .{ |
| 2084 | .i_type = .{ | 2026 | .i_type = .{ |
| 2085 | .rd = reg, | 2027 | .rd = reg, |
| ... | @@ -2090,7 +2032,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { | ... | @@ -2090,7 +2032,7 @@ fn truncateRegister(func: *Func, ty: Type, reg: Register) !void { |
| 2090 | }); | 2032 | }); |
| 2091 | _ = try func.addInst(.{ | 2033 | _ = try func.addInst(.{ |
| 2092 | .tag = .srli, | 2034 | .tag = .srli, |
| 2093 | .ops = .rri, | 2035 | |
| 2094 | .data = .{ | 2036 | .data = .{ |
| 2095 | .i_type = .{ | 2037 | .i_type = .{ |
| 2096 | .rd = reg, | 2038 | .rd = reg, |
| ... | @@ -2411,8 +2353,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -2411,8 +2353,7 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void { |
| 2411 | switch (ty.zigTypeTag(zcu)) { | 2353 | switch (ty.zigTypeTag(zcu)) { |
| 2412 | .Bool => { | 2354 | .Bool => { |
| 2413 | _ = try func.addInst(.{ | 2355 | _ = try func.addInst(.{ |
| 2414 | .tag = .pseudo, | 2356 | .tag = .pseudo_not, |
| 2415 | .ops = .pseudo_not, | ||
| 2416 | .data = .{ | 2357 | .data = .{ |
| 2417 | .rr = .{ | 2358 | .rr = .{ |
| 2418 | .rs = operand_reg, | 2359 | .rs = operand_reg, |
| ... | @@ -2430,7 +2371,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -2430,7 +2371,6 @@ fn airNot(func: *Func, inst: Air.Inst.Index) !void { |
| 2430 | 32, 64 => { | 2371 | 32, 64 => { |
| 2431 | _ = try func.addInst(.{ | 2372 | _ = try func.addInst(.{ |
| 2432 | .tag = .xori, | 2373 | .tag = .xori, |
| 2433 | .ops = .rri, | ||
| 2434 | .data = .{ | 2374 | .data = .{ |
| 2435 | .i_type = .{ | 2375 | .i_type = .{ |
| 2436 | .rd = dst_reg, | 2376 | .rd = dst_reg, |
| ... | @@ -2628,7 +2568,7 @@ fn genBinOp( | ... | @@ -2628,7 +2568,7 @@ fn genBinOp( |
| 2628 | 2568 | ||
| 2629 | switch (lhs_ty.zigTypeTag(zcu)) { | 2569 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2630 | .Int => { | 2570 | .Int => { |
| 2631 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2571 | const mnem: Mnemonic = switch (tag) { |
| 2632 | .add, .add_wrap => switch (bit_size) { | 2572 | .add, .add_wrap => switch (bit_size) { |
| 2633 | 8, 16, 64 => .add, | 2573 | 8, 16, 64 => .add, |
| 2634 | 32 => .addw, | 2574 | 32 => .addw, |
| ... | @@ -2656,8 +2596,7 @@ fn genBinOp( | ... | @@ -2656,8 +2596,7 @@ fn genBinOp( |
| 2656 | }; | 2596 | }; |
| 2657 | 2597 | ||
| 2658 | _ = try func.addInst(.{ | 2598 | _ = try func.addInst(.{ |
| 2659 | .tag = mir_tag, | 2599 | .tag = mnem, |
| 2660 | .ops = .rrr, | ||
| 2661 | .data = .{ | 2600 | .data = .{ |
| 2662 | .r_type = .{ | 2601 | .r_type = .{ |
| 2663 | .rd = dst_reg, | 2602 | .rd = dst_reg, |
| ... | @@ -2668,7 +2607,7 @@ fn genBinOp( | ... | @@ -2668,7 +2607,7 @@ fn genBinOp( |
| 2668 | }); | 2607 | }); |
| 2669 | }, | 2608 | }, |
| 2670 | .Float => { | 2609 | .Float => { |
| 2671 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2610 | const mir_tag: Mnemonic = switch (tag) { |
| 2672 | .add => switch (bit_size) { | 2611 | .add => switch (bit_size) { |
| 2673 | 32 => .fadds, | 2612 | 32 => .fadds, |
| 2674 | 64 => .faddd, | 2613 | 64 => .faddd, |
| ... | @@ -2689,7 +2628,6 @@ fn genBinOp( | ... | @@ -2689,7 +2628,6 @@ fn genBinOp( |
| 2689 | 2628 | ||
| 2690 | _ = try func.addInst(.{ | 2629 | _ = try func.addInst(.{ |
| 2691 | .tag = mir_tag, | 2630 | .tag = mir_tag, |
| 2692 | .ops = .rrr, | ||
| 2693 | .data = .{ | 2631 | .data = .{ |
| 2694 | .r_type = .{ | 2632 | .r_type = .{ |
| 2695 | .rd = dst_reg, | 2633 | .rd = dst_reg, |
| ... | @@ -2705,7 +2643,7 @@ fn genBinOp( | ... | @@ -2705,7 +2643,7 @@ fn genBinOp( |
| 2705 | 2643 | ||
| 2706 | const child_ty = lhs_ty.childType(zcu); | 2644 | const child_ty = lhs_ty.childType(zcu); |
| 2707 | 2645 | ||
| 2708 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2646 | const mir_tag: Mnemonic = switch (tag) { |
| 2709 | .add => switch (child_ty.zigTypeTag(zcu)) { | 2647 | .add => switch (child_ty.zigTypeTag(zcu)) { |
| 2710 | .Int => .vaddvv, | 2648 | .Int => .vaddvv, |
| 2711 | .Float => .vfaddvv, | 2649 | .Float => .vfaddvv, |
| ... | @@ -2739,7 +2677,6 @@ fn genBinOp( | ... | @@ -2739,7 +2677,6 @@ fn genBinOp( |
| 2739 | 2677 | ||
| 2740 | _ = try func.addInst(.{ | 2678 | _ = try func.addInst(.{ |
| 2741 | .tag = mir_tag, | 2679 | .tag = mir_tag, |
| 2742 | .ops = .rrr, | ||
| 2743 | .data = .{ | 2680 | .data = .{ |
| 2744 | .r_type = .{ | 2681 | .r_type = .{ |
| 2745 | .rd = dst_reg, | 2682 | .rd = dst_reg, |
| ... | @@ -2764,7 +2701,6 @@ fn genBinOp( | ... | @@ -2764,7 +2701,6 @@ fn genBinOp( |
| 2764 | 2701 | ||
| 2765 | _ = try func.addInst(.{ | 2702 | _ = try func.addInst(.{ |
| 2766 | .tag = .add, | 2703 | .tag = .add, |
| 2767 | .ops = .rrr, | ||
| 2768 | .data = .{ .r_type = .{ | 2704 | .data = .{ .r_type = .{ |
| 2769 | .rd = tmp_reg, | 2705 | .rd = tmp_reg, |
| 2770 | .rs1 = rhs_reg, | 2706 | .rs1 = rhs_reg, |
| ... | @@ -2774,7 +2710,6 @@ fn genBinOp( | ... | @@ -2774,7 +2710,6 @@ fn genBinOp( |
| 2774 | 2710 | ||
| 2775 | _ = try func.addInst(.{ | 2711 | _ = try func.addInst(.{ |
| 2776 | .tag = .sltu, | 2712 | .tag = .sltu, |
| 2777 | .ops = .rrr, | ||
| 2778 | .data = .{ .r_type = .{ | 2713 | .data = .{ .r_type = .{ |
| 2779 | .rd = dst_reg, | 2714 | .rd = dst_reg, |
| 2780 | .rs1 = tmp_reg, | 2715 | .rs1 = tmp_reg, |
| ... | @@ -2785,7 +2720,6 @@ fn genBinOp( | ... | @@ -2785,7 +2720,6 @@ fn genBinOp( |
| 2785 | // neg dst_reg, dst_reg | 2720 | // neg dst_reg, dst_reg |
| 2786 | _ = try func.addInst(.{ | 2721 | _ = try func.addInst(.{ |
| 2787 | .tag = .sub, | 2722 | .tag = .sub, |
| 2788 | .ops = .rrr, | ||
| 2789 | .data = .{ .r_type = .{ | 2723 | .data = .{ .r_type = .{ |
| 2790 | .rd = dst_reg, | 2724 | .rd = dst_reg, |
| 2791 | .rs1 = .zero, | 2725 | .rs1 = .zero, |
| ... | @@ -2795,7 +2729,6 @@ fn genBinOp( | ... | @@ -2795,7 +2729,6 @@ fn genBinOp( |
| 2795 | 2729 | ||
| 2796 | _ = try func.addInst(.{ | 2730 | _ = try func.addInst(.{ |
| 2797 | .tag = .@"or", | 2731 | .tag = .@"or", |
| 2798 | .ops = .rrr, | ||
| 2799 | .data = .{ .r_type = .{ | 2732 | .data = .{ .r_type = .{ |
| 2800 | .rd = dst_reg, | 2733 | .rd = dst_reg, |
| 2801 | .rs1 = dst_reg, | 2734 | .rs1 = dst_reg, |
| ... | @@ -2850,7 +2783,6 @@ fn genBinOp( | ... | @@ -2850,7 +2783,6 @@ fn genBinOp( |
| 2850 | .bit_or, .bool_or => .@"or", | 2783 | .bit_or, .bool_or => .@"or", |
| 2851 | else => unreachable, | 2784 | else => unreachable, |
| 2852 | }, | 2785 | }, |
| 2853 | .ops = .rrr, | ||
| 2854 | .data = .{ | 2786 | .data = .{ |
| 2855 | .r_type = .{ | 2787 | .r_type = .{ |
| 2856 | .rd = dst_reg, | 2788 | .rd = dst_reg, |
| ... | @@ -2876,7 +2808,7 @@ fn genBinOp( | ... | @@ -2876,7 +2808,7 @@ fn genBinOp( |
| 2876 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); | 2808 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); |
| 2877 | try func.truncateRegister(rhs_ty, rhs_reg); | 2809 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2878 | 2810 | ||
| 2879 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 2811 | const mir_tag: Mnemonic = switch (tag) { |
| 2880 | .shl, .shl_exact => switch (bit_size) { | 2812 | .shl, .shl_exact => switch (bit_size) { |
| 2881 | 1...31, 33...64 => .sll, | 2813 | 1...31, 33...64 => .sll, |
| 2882 | 32 => .sllw, | 2814 | 32 => .sllw, |
| ... | @@ -2892,7 +2824,6 @@ fn genBinOp( | ... | @@ -2892,7 +2824,6 @@ fn genBinOp( |
| 2892 | 2824 | ||
| 2893 | _ = try func.addInst(.{ | 2825 | _ = try func.addInst(.{ |
| 2894 | .tag = mir_tag, | 2826 | .tag = mir_tag, |
| 2895 | .ops = .rrr, | ||
| 2896 | .data = .{ .r_type = .{ | 2827 | .data = .{ .r_type = .{ |
| 2897 | .rd = dst_reg, | 2828 | .rd = dst_reg, |
| 2898 | .rs1 = lhs_reg, | 2829 | .rs1 = lhs_reg, |
| ... | @@ -2910,8 +2841,7 @@ fn genBinOp( | ... | @@ -2910,8 +2841,7 @@ fn genBinOp( |
| 2910 | .cmp_gte, | 2841 | .cmp_gte, |
| 2911 | => { | 2842 | => { |
| 2912 | _ = try func.addInst(.{ | 2843 | _ = try func.addInst(.{ |
| 2913 | .tag = .pseudo, | 2844 | .tag = .pseudo_compare, |
| 2914 | .ops = .pseudo_compare, | ||
| 2915 | .data = .{ | 2845 | .data = .{ |
| 2916 | .compare = .{ | 2846 | .compare = .{ |
| 2917 | .op = switch (tag) { | 2847 | .op = switch (tag) { |
| ... | @@ -2966,7 +2896,6 @@ fn genBinOp( | ... | @@ -2966,7 +2896,6 @@ fn genBinOp( |
| 2966 | 2896 | ||
| 2967 | _ = try func.addInst(.{ | 2897 | _ = try func.addInst(.{ |
| 2968 | .tag = if (int_info.signedness == .unsigned) .sltu else .slt, | 2898 | .tag = if (int_info.signedness == .unsigned) .sltu else .slt, |
| 2969 | .ops = .rrr, | ||
| 2970 | .data = .{ .r_type = .{ | 2899 | .data = .{ .r_type = .{ |
| 2971 | .rd = mask_reg, | 2900 | .rd = mask_reg, |
| 2972 | .rs1 = lhs_reg, | 2901 | .rs1 = lhs_reg, |
| ... | @@ -2976,7 +2905,6 @@ fn genBinOp( | ... | @@ -2976,7 +2905,6 @@ fn genBinOp( |
| 2976 | 2905 | ||
| 2977 | _ = try func.addInst(.{ | 2906 | _ = try func.addInst(.{ |
| 2978 | .tag = .sub, | 2907 | .tag = .sub, |
| 2979 | .ops = .rrr, | ||
| 2980 | .data = .{ .r_type = .{ | 2908 | .data = .{ .r_type = .{ |
| 2981 | .rd = mask_reg, | 2909 | .rd = mask_reg, |
| 2982 | .rs1 = .zero, | 2910 | .rs1 = .zero, |
| ... | @@ -2986,7 +2914,6 @@ fn genBinOp( | ... | @@ -2986,7 +2914,6 @@ fn genBinOp( |
| 2986 | 2914 | ||
| 2987 | _ = try func.addInst(.{ | 2915 | _ = try func.addInst(.{ |
| 2988 | .tag = .xor, | 2916 | .tag = .xor, |
| 2989 | .ops = .rrr, | ||
| 2990 | .data = .{ .r_type = .{ | 2917 | .data = .{ .r_type = .{ |
| 2991 | .rd = dst_reg, | 2918 | .rd = dst_reg, |
| 2992 | .rs1 = lhs_reg, | 2919 | .rs1 = lhs_reg, |
| ... | @@ -2996,7 +2923,6 @@ fn genBinOp( | ... | @@ -2996,7 +2923,6 @@ fn genBinOp( |
| 2996 | 2923 | ||
| 2997 | _ = try func.addInst(.{ | 2924 | _ = try func.addInst(.{ |
| 2998 | .tag = .@"and", | 2925 | .tag = .@"and", |
| 2999 | .ops = .rrr, | ||
| 3000 | .data = .{ .r_type = .{ | 2926 | .data = .{ .r_type = .{ |
| 3001 | .rd = mask_reg, | 2927 | .rd = mask_reg, |
| 3002 | .rs1 = dst_reg, | 2928 | .rs1 = dst_reg, |
| ... | @@ -3006,7 +2932,6 @@ fn genBinOp( | ... | @@ -3006,7 +2932,6 @@ fn genBinOp( |
| 3006 | 2932 | ||
| 3007 | _ = try func.addInst(.{ | 2933 | _ = try func.addInst(.{ |
| 3008 | .tag = .xor, | 2934 | .tag = .xor, |
| 3009 | .ops = .rrr, | ||
| 3010 | .data = .{ .r_type = .{ | 2935 | .data = .{ .r_type = .{ |
| 3011 | .rd = dst_reg, | 2936 | .rd = dst_reg, |
| 3012 | .rs1 = if (tag == .min) rhs_reg else lhs_reg, | 2937 | .rs1 = if (tag == .min) rhs_reg else lhs_reg, |
| ... | @@ -3103,7 +3028,6 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3103,7 +3028,6 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3103 | 3028 | ||
| 3104 | _ = try func.addInst(.{ | 3029 | _ = try func.addInst(.{ |
| 3105 | .tag = .add, | 3030 | .tag = .add, |
| 3106 | .ops = .rrr, | ||
| 3107 | .data = .{ .r_type = .{ | 3031 | .data = .{ .r_type = .{ |
| 3108 | .rs1 = rhs_reg, | 3032 | .rs1 = rhs_reg, |
| 3109 | .rs2 = lhs_reg, | 3033 | .rs2 = lhs_reg, |
| ... | @@ -3209,7 +3133,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3209,7 +3133,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3209 | .unsigned => { | 3133 | .unsigned => { |
| 3210 | _ = try func.addInst(.{ | 3134 | _ = try func.addInst(.{ |
| 3211 | .tag = .sltu, | 3135 | .tag = .sltu, |
| 3212 | .ops = .rrr, | ||
| 3213 | .data = .{ .r_type = .{ | 3136 | .data = .{ .r_type = .{ |
| 3214 | .rd = overflow_reg, | 3137 | .rd = overflow_reg, |
| 3215 | .rs1 = lhs_reg, | 3138 | .rs1 = lhs_reg, |
| ... | @@ -3231,7 +3154,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3231,7 +3154,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3231 | 64 => { | 3154 | 64 => { |
| 3232 | _ = try func.addInst(.{ | 3155 | _ = try func.addInst(.{ |
| 3233 | .tag = .slt, | 3156 | .tag = .slt, |
| 3234 | .ops = .rrr, | ||
| 3235 | .data = .{ .r_type = .{ | 3157 | .data = .{ .r_type = .{ |
| 3236 | .rd = overflow_reg, | 3158 | .rd = overflow_reg, |
| 3237 | .rs1 = overflow_reg, | 3159 | .rs1 = overflow_reg, |
| ... | @@ -3241,7 +3163,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3241,7 +3163,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3241 | 3163 | ||
| 3242 | _ = try func.addInst(.{ | 3164 | _ = try func.addInst(.{ |
| 3243 | .tag = .slt, | 3165 | .tag = .slt, |
| 3244 | .ops = .rrr, | ||
| 3245 | .data = .{ .r_type = .{ | 3166 | .data = .{ .r_type = .{ |
| 3246 | .rd = rhs_reg, | 3167 | .rd = rhs_reg, |
| 3247 | .rs1 = rhs_reg, | 3168 | .rs1 = rhs_reg, |
| ... | @@ -3251,7 +3172,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3251,7 +3172,6 @@ fn airSubWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3251 | 3172 | ||
| 3252 | _ = try func.addInst(.{ | 3173 | _ = try func.addInst(.{ |
| 3253 | .tag = .xor, | 3174 | .tag = .xor, |
| 3254 | .ops = .rrr, | ||
| 3255 | .data = .{ .r_type = .{ | 3175 | .data = .{ .r_type = .{ |
| 3256 | .rd = lhs_reg, | 3176 | .rd = lhs_reg, |
| 3257 | .rs1 = overflow_reg, | 3177 | .rs1 = overflow_reg, |
| ... | @@ -3843,7 +3763,6 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | ... | @@ -3843,7 +3763,6 @@ fn genSliceElemPtr(func: *Func, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 3843 | 3763 | ||
| 3844 | _ = try func.addInst(.{ | 3764 | _ = try func.addInst(.{ |
| 3845 | .tag = .add, | 3765 | .tag = .add, |
| 3846 | .ops = .rrr, | ||
| 3847 | .data = .{ .r_type = .{ | 3766 | .data = .{ .r_type = .{ |
| 3848 | .rd = addr_reg, | 3767 | .rd = addr_reg, |
| 3849 | .rs1 = addr_reg, | 3768 | .rs1 = addr_reg, |
| ... | @@ -3907,7 +3826,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3907,7 +3826,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { |
| 3907 | 3826 | ||
| 3908 | _ = try func.addInst(.{ | 3827 | _ = try func.addInst(.{ |
| 3909 | .tag = .vslidedownvx, | 3828 | .tag = .vslidedownvx, |
| 3910 | .ops = .rrr, | ||
| 3911 | .data = .{ .r_type = .{ | 3829 | .data = .{ .r_type = .{ |
| 3912 | .rd = src_reg, | 3830 | .rd = src_reg, |
| 3913 | .rs1 = index_reg, | 3831 | .rs1 = index_reg, |
| ... | @@ -3925,7 +3843,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3925,7 +3843,6 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void { |
| 3925 | defer func.register_manager.unlockReg(offset_lock); | 3843 | defer func.register_manager.unlockReg(offset_lock); |
| 3926 | _ = try func.addInst(.{ | 3844 | _ = try func.addInst(.{ |
| 3927 | .tag = .add, | 3845 | .tag = .add, |
| 3928 | .ops = .rrr, | ||
| 3929 | .data = .{ .r_type = .{ | 3846 | .data = .{ .r_type = .{ |
| 3930 | .rd = addr_reg, | 3847 | .rd = addr_reg, |
| 3931 | .rs1 = addr_reg, | 3848 | .rs1 = addr_reg, |
| ... | @@ -4080,7 +3997,6 @@ fn airClz(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4080,7 +3997,6 @@ fn airClz(func: *Func, inst: Air.Inst.Index) !void { |
| 4080 | 32 => .clzw, | 3997 | 32 => .clzw, |
| 4081 | else => .clz, | 3998 | else => .clz, |
| 4082 | }, | 3999 | }, |
| 4083 | .ops = .rrr, | ||
| 4084 | .data = .{ | 4000 | .data = .{ |
| 4085 | .r_type = .{ | 4001 | .r_type = .{ |
| 4086 | .rs2 = .zero, // rs2 is 0 filled in the spec | 4002 | .rs2 = .zero, // rs2 is 0 filled in the spec |
| ... | @@ -4093,7 +4009,6 @@ fn airClz(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4093,7 +4009,6 @@ fn airClz(func: *Func, inst: Air.Inst.Index) !void { |
| 4093 | if (!(bit_size == 32 or bit_size == 64)) { | 4009 | if (!(bit_size == 32 or bit_size == 64)) { |
| 4094 | _ = try func.addInst(.{ | 4010 | _ = try func.addInst(.{ |
| 4095 | .tag = .addi, | 4011 | .tag = .addi, |
| 4096 | .ops = .rri, | ||
| 4097 | .data = .{ .i_type = .{ | 4012 | .data = .{ .i_type = .{ |
| 4098 | .rd = dst_reg, | 4013 | .rd = dst_reg, |
| 4099 | .rs1 = dst_reg, | 4014 | .rs1 = dst_reg, |
| ... | @@ -4151,7 +4066,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4151,7 +4066,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4151 | 64 => .srai, | 4066 | 64 => .srai, |
| 4152 | else => unreachable, | 4067 | else => unreachable, |
| 4153 | }, | 4068 | }, |
| 4154 | .ops = .rri, | ||
| 4155 | .data = .{ .i_type = .{ | 4069 | .data = .{ .i_type = .{ |
| 4156 | .rd = temp_reg, | 4070 | .rd = temp_reg, |
| 4157 | .rs1 = operand_reg, | 4071 | .rs1 = operand_reg, |
| ... | @@ -4161,7 +4075,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4161,7 +4075,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4161 | 4075 | ||
| 4162 | _ = try func.addInst(.{ | 4076 | _ = try func.addInst(.{ |
| 4163 | .tag = .xor, | 4077 | .tag = .xor, |
| 4164 | .ops = .rrr, | ||
| 4165 | .data = .{ .r_type = .{ | 4078 | .data = .{ .r_type = .{ |
| 4166 | .rd = operand_reg, | 4079 | .rd = operand_reg, |
| 4167 | .rs1 = operand_reg, | 4080 | .rs1 = operand_reg, |
| ... | @@ -4175,7 +4088,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4175,7 +4088,6 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4175 | 64 => .sub, | 4088 | 64 => .sub, |
| 4176 | else => unreachable, | 4089 | else => unreachable, |
| 4177 | }, | 4090 | }, |
| 4178 | .ops = .rrr, | ||
| 4179 | .data = .{ .r_type = .{ | 4091 | .data = .{ .r_type = .{ |
| 4180 | .rd = operand_reg, | 4092 | .rd = operand_reg, |
| 4181 | .rs1 = operand_reg, | 4093 | .rs1 = operand_reg, |
| ... | @@ -4187,14 +4099,14 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4187,14 +4099,14 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4187 | }, | 4099 | }, |
| 4188 | .Float => { | 4100 | .Float => { |
| 4189 | const float_bits = scalar_ty.floatBits(zcu.getTarget()); | 4101 | const float_bits = scalar_ty.floatBits(zcu.getTarget()); |
| 4190 | switch (float_bits) { | 4102 | const mnem: Mnemonic = switch (float_bits) { |
| 4191 | 16 => return func.fail("TODO: airAbs 16-bit float", .{}), | 4103 | 16 => return func.fail("TODO: airAbs 16-bit float", .{}), |
| 4192 | 32 => {}, | 4104 | 32 => .fsgnjxs, |
| 4193 | 64 => {}, | 4105 | 64 => .fsgnjxd, |
| 4194 | 80 => return func.fail("TODO: airAbs 80-bit float", .{}), | 4106 | 80 => return func.fail("TODO: airAbs 80-bit float", .{}), |
| 4195 | 128 => return func.fail("TODO: airAbs 128-bit float", .{}), | 4107 | 128 => return func.fail("TODO: airAbs 128-bit float", .{}), |
| 4196 | else => unreachable, | 4108 | else => unreachable, |
| 4197 | } | 4109 | }; |
| 4198 | 4110 | ||
| 4199 | const return_mcv = try func.copyToNewRegister(inst, operand); | 4111 | const return_mcv = try func.copyToNewRegister(inst, operand); |
| 4200 | const operand_reg = return_mcv.register; | 4112 | const operand_reg = return_mcv.register; |
| ... | @@ -4202,13 +4114,12 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4202,13 +4114,12 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 4202 | assert(operand_reg.class() == .float); | 4114 | assert(operand_reg.class() == .float); |
| 4203 | 4115 | ||
| 4204 | _ = try func.addInst(.{ | 4116 | _ = try func.addInst(.{ |
| 4205 | .tag = .pseudo, | 4117 | .tag = mnem, |
| 4206 | .ops = .pseudo_fabs, | ||
| 4207 | .data = .{ | 4118 | .data = .{ |
| 4208 | .fabs = .{ | 4119 | .r_type = .{ |
| 4209 | .rd = operand_reg, | 4120 | .rd = operand_reg, |
| 4210 | .rs = operand_reg, | 4121 | .rs1 = operand_reg, |
| 4211 | .bits = float_bits, | 4122 | .rs2 = operand_reg, |
| 4212 | }, | 4123 | }, |
| 4213 | }, | 4124 | }, |
| 4214 | }); | 4125 | }); |
| ... | @@ -4231,54 +4142,56 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4231,54 +4142,56 @@ fn airByteSwap(func: *Func, inst: Air.Inst.Index) !void { |
| 4231 | const ty = func.typeOf(ty_op.operand); | 4142 | const ty = func.typeOf(ty_op.operand); |
| 4232 | const operand = try func.resolveInst(ty_op.operand); | 4143 | const operand = try func.resolveInst(ty_op.operand); |
| 4233 | 4144 | ||
| 4234 | const int_bits = ty.intInfo(zcu).bits; | 4145 | switch (ty.zigTypeTag(zcu)) { |
| 4146 | .Int => { | ||
| 4147 | const int_bits = ty.intInfo(zcu).bits; | ||
| 4235 | 4148 | ||
| 4236 | // bytes are no-op | 4149 | // bytes are no-op |
| 4237 | if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) { | 4150 | if (int_bits == 8 and func.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 4238 | return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none }); | 4151 | return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none }); |
| 4239 | } | 4152 | } |
| 4240 | 4153 | ||
| 4241 | const dest_mcv = try func.copyToNewRegister(inst, operand); | 4154 | const dest_mcv = try func.copyToNewRegister(inst, operand); |
| 4242 | const dest_reg = dest_mcv.register; | 4155 | const dest_reg = dest_mcv.register; |
| 4243 | 4156 | ||
| 4244 | switch (int_bits) { | 4157 | switch (int_bits) { |
| 4245 | 16 => { | 4158 | 16 => { |
| 4246 | const temp_reg, const temp_lock = try func.allocReg(.int); | 4159 | const temp_reg, const temp_lock = try func.allocReg(.int); |
| 4247 | defer func.register_manager.unlockReg(temp_lock); | 4160 | defer func.register_manager.unlockReg(temp_lock); |
| 4248 | 4161 | ||
| 4249 | _ = try func.addInst(.{ | 4162 | _ = try func.addInst(.{ |
| 4250 | .tag = .srli, | 4163 | .tag = .srli, |
| 4251 | .ops = .rri, | 4164 | .data = .{ .i_type = .{ |
| 4252 | .data = .{ .i_type = .{ | 4165 | .imm12 = Immediate.s(8), |
| 4253 | .imm12 = Immediate.s(8), | 4166 | .rd = temp_reg, |
| 4254 | .rd = temp_reg, | 4167 | .rs1 = dest_reg, |
| 4255 | .rs1 = dest_reg, | 4168 | } }, |
| 4256 | } }, | 4169 | }); |
| 4257 | }); | ||
| 4258 | 4170 | ||
| 4259 | _ = try func.addInst(.{ | 4171 | _ = try func.addInst(.{ |
| 4260 | .tag = .slli, | 4172 | .tag = .slli, |
| 4261 | .ops = .rri, | 4173 | .data = .{ .i_type = .{ |
| 4262 | .data = .{ .i_type = .{ | 4174 | .imm12 = Immediate.s(8), |
| 4263 | .imm12 = Immediate.s(8), | 4175 | .rd = dest_reg, |
| 4264 | .rd = dest_reg, | 4176 | .rs1 = dest_reg, |
| 4265 | .rs1 = dest_reg, | 4177 | } }, |
| 4266 | } }, | 4178 | }); |
| 4267 | }); | 4179 | _ = try func.addInst(.{ |
| 4268 | _ = try func.addInst(.{ | 4180 | .tag = .@"or", |
| 4269 | .tag = .@"or", | 4181 | .data = .{ .r_type = .{ |
| 4270 | .ops = .rri, | 4182 | .rd = dest_reg, |
| 4271 | .data = .{ .r_type = .{ | 4183 | .rs1 = dest_reg, |
| 4272 | .rd = dest_reg, | 4184 | .rs2 = temp_reg, |
| 4273 | .rs1 = dest_reg, | 4185 | } }, |
| 4274 | .rs2 = temp_reg, | 4186 | }); |
| 4275 | } }, | 4187 | }, |
| 4276 | }); | 4188 | else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}), |
| 4189 | } | ||
| 4190 | |||
| 4191 | break :result dest_mcv; | ||
| 4277 | }, | 4192 | }, |
| 4278 | else => return func.fail("TODO: {d} bits for airByteSwap", .{int_bits}), | 4193 | else => return func.fail("TODO: airByteSwap {}", .{ty.fmt(pt)}), |
| 4279 | } | 4194 | } |
| 4280 | |||
| 4281 | break :result dest_mcv; | ||
| 4282 | }; | 4195 | }; |
| 4283 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 4196 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 4284 | } | 4197 | } |
| ... | @@ -4322,7 +4235,6 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { | ... | @@ -4322,7 +4235,6 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4322 | .sqrt => { | 4235 | .sqrt => { |
| 4323 | _ = try func.addInst(.{ | 4236 | _ = try func.addInst(.{ |
| 4324 | .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts, | 4237 | .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts, |
| 4325 | .ops = .rrr, | ||
| 4326 | .data = .{ | 4238 | .data = .{ |
| 4327 | .r_type = .{ | 4239 | .r_type = .{ |
| 4328 | .rd = dst_reg, | 4240 | .rd = dst_reg, |
| ... | @@ -4332,6 +4244,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { | ... | @@ -4332,6 +4244,7 @@ fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 4332 | }, | 4244 | }, |
| 4333 | }); | 4245 | }); |
| 4334 | }, | 4246 | }, |
| 4247 | |||
| 4335 | else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}), | 4248 | else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}), |
| 4336 | } | 4249 | } |
| 4337 | }, | 4250 | }, |
| ... | @@ -4538,17 +4451,14 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -4538,17 +4451,14 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 4538 | const zcu = pt.zcu; | 4451 | const zcu = pt.zcu; |
| 4539 | const ptr_field_ty = func.typeOfIndex(inst); | 4452 | const ptr_field_ty = func.typeOfIndex(inst); |
| 4540 | const ptr_container_ty = func.typeOf(operand); | 4453 | const ptr_container_ty = func.typeOf(operand); |
| 4541 | const ptr_container_ty_info = ptr_container_ty.ptrInfo(zcu); | ||
| 4542 | const container_ty = ptr_container_ty.childType(zcu); | 4454 | const container_ty = ptr_container_ty.childType(zcu); |
| 4543 | 4455 | ||
| 4544 | const field_offset: i32 = if (zcu.typeToPackedStruct(container_ty)) |struct_obj| | 4456 | const field_offset: i32 = switch (container_ty.containerLayout(zcu)) { |
| 4545 | if (ptr_field_ty.ptrInfo(zcu).packed_offset.host_size == 0) | 4457 | .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, pt)), |
| 4546 | @divExact(pt.structPackedFieldBitOffset(struct_obj, index) + | 4458 | .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) + |
| 4547 | ptr_container_ty_info.packed_offset.bit_offset, 8) | 4459 | (if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, index) else 0) - |
| 4548 | else | 4460 | ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8), |
| 4549 | 0 | 4461 | }; |
| 4550 | else | ||
| 4551 | @intCast(container_ty.structFieldOffset(index, pt)); | ||
| 4552 | 4462 | ||
| 4553 | const src_mcv = try func.resolveInst(operand); | 4463 | const src_mcv = try func.resolveInst(operand); |
| 4554 | const dst_mcv = if (switch (src_mcv) { | 4464 | const dst_mcv = if (switch (src_mcv) { |
| ... | @@ -4600,7 +4510,6 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4600,7 +4510,6 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { |
| 4600 | if (field_off > 0) { | 4510 | if (field_off > 0) { |
| 4601 | _ = try func.addInst(.{ | 4511 | _ = try func.addInst(.{ |
| 4602 | .tag = .srli, | 4512 | .tag = .srli, |
| 4603 | .ops = .rri, | ||
| 4604 | .data = .{ .i_type = .{ | 4513 | .data = .{ .i_type = .{ |
| 4605 | .imm12 = Immediate.u(@intCast(field_off)), | 4514 | .imm12 = Immediate.u(@intCast(field_off)), |
| 4606 | .rd = dst_reg, | 4515 | .rd = dst_reg, |
| ... | @@ -4720,8 +4629,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4720,8 +4629,7 @@ fn airArg(func: *Func, inst: Air.Inst.Index) !void { |
| 4720 | fn airTrap(func: *Func) !void { | 4629 | fn airTrap(func: *Func) !void { |
| 4721 | _ = try func.addInst(.{ | 4630 | _ = try func.addInst(.{ |
| 4722 | .tag = .unimp, | 4631 | .tag = .unimp, |
| 4723 | .ops = .none, | 4632 | .data = .none, |
| 4724 | .data = undefined, | ||
| 4725 | }); | 4633 | }); |
| 4726 | return func.finishAirBookkeeping(); | 4634 | return func.finishAirBookkeeping(); |
| 4727 | } | 4635 | } |
| ... | @@ -4729,8 +4637,7 @@ fn airTrap(func: *Func) !void { | ... | @@ -4729,8 +4637,7 @@ fn airTrap(func: *Func) !void { |
| 4729 | fn airBreakpoint(func: *Func) !void { | 4637 | fn airBreakpoint(func: *Func) !void { |
| 4730 | _ = try func.addInst(.{ | 4638 | _ = try func.addInst(.{ |
| 4731 | .tag = .ebreak, | 4639 | .tag = .ebreak, |
| 4732 | .ops = .none, | 4640 | .data = .none, |
| 4733 | .data = undefined, | ||
| 4734 | }); | 4641 | }); |
| 4735 | return func.finishAirBookkeeping(); | 4642 | return func.finishAirBookkeeping(); |
| 4736 | } | 4643 | } |
| ... | @@ -4758,8 +4665,7 @@ fn airFence(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4758,8 +4665,7 @@ fn airFence(func: *Func, inst: Air.Inst.Index) !void { |
| 4758 | }; | 4665 | }; |
| 4759 | 4666 | ||
| 4760 | _ = try func.addInst(.{ | 4667 | _ = try func.addInst(.{ |
| 4761 | .tag = .pseudo, | 4668 | .tag = .pseudo_fence, |
| 4762 | .ops = .pseudo_fence, | ||
| 4763 | .data = .{ | 4669 | .data = .{ |
| 4764 | .fence = .{ | 4670 | .fence = .{ |
| 4765 | .pred = pred, | 4671 | .pred = pred, |
| ... | @@ -4951,7 +4857,6 @@ fn genCall( | ... | @@ -4951,7 +4857,6 @@ fn genCall( |
| 4951 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); | 4857 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); |
| 4952 | _ = try func.addInst(.{ | 4858 | _ = try func.addInst(.{ |
| 4953 | .tag = .jalr, | 4859 | .tag = .jalr, |
| 4954 | .ops = .rri, | ||
| 4955 | .data = .{ .i_type = .{ | 4860 | .data = .{ .i_type = .{ |
| 4956 | .rd = .ra, | 4861 | .rd = .ra, |
| 4957 | .rs1 = .ra, | 4862 | .rs1 = .ra, |
| ... | @@ -4967,16 +4872,15 @@ fn genCall( | ... | @@ -4967,16 +4872,15 @@ fn genCall( |
| 4967 | const decl_name = owner_decl.name.toSlice(&zcu.intern_pool); | 4872 | const decl_name = owner_decl.name.toSlice(&zcu.intern_pool); |
| 4968 | const atom_index = try func.owner.getSymbolIndex(func); | 4873 | const atom_index = try func.owner.getSymbolIndex(func); |
| 4969 | 4874 | ||
| 4970 | if (func.bin_file.cast(link.File.Elf)) |elf_file| { | 4875 | const elf_file = func.bin_file.cast(link.File.Elf).?; |
| 4971 | _ = try func.addInst(.{ | 4876 | _ = try func.addInst(.{ |
| 4972 | .tag = .pseudo, | 4877 | .tag = .pseudo_extern_fn_reloc, |
| 4973 | .ops = .pseudo_extern_fn_reloc, | 4878 | .data = .{ .reloc = .{ |
| 4974 | .data = .{ .reloc = .{ | 4879 | .register = .ra, |
| 4975 | .atom_index = atom_index, | 4880 | .atom_index = atom_index, |
| 4976 | .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name), | 4881 | .sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name), |
| 4977 | } }, | 4882 | } }, |
| 4978 | }); | 4883 | }); |
| 4979 | } else unreachable; // not a valid riscv64 format | ||
| 4980 | }, | 4884 | }, |
| 4981 | else => return func.fail("TODO implement calling bitcasted functions", .{}), | 4885 | else => return func.fail("TODO implement calling bitcasted functions", .{}), |
| 4982 | } | 4886 | } |
| ... | @@ -4988,7 +4892,6 @@ fn genCall( | ... | @@ -4988,7 +4892,6 @@ fn genCall( |
| 4988 | 4892 | ||
| 4989 | _ = try func.addInst(.{ | 4893 | _ = try func.addInst(.{ |
| 4990 | .tag = .jalr, | 4894 | .tag = .jalr, |
| 4991 | .ops = .rri, | ||
| 4992 | .data = .{ .i_type = .{ | 4895 | .data = .{ .i_type = .{ |
| 4993 | .rd = .ra, | 4896 | .rd = .ra, |
| 4994 | .rs1 = addr_reg, | 4897 | .rs1 = addr_reg, |
| ... | @@ -5065,9 +4968,11 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -5065,9 +4968,11 @@ fn airRet(func: *Func, inst: Air.Inst.Index, safety: bool) !void { |
| 5065 | 4968 | ||
| 5066 | // Just add space for an instruction, reloced this later | 4969 | // Just add space for an instruction, reloced this later |
| 5067 | const index = try func.addInst(.{ | 4970 | const index = try func.addInst(.{ |
| 5068 | .tag = .pseudo, | 4971 | .tag = .pseudo_j, |
| 5069 | .ops = .pseudo_j, | 4972 | .data = .{ .j_type = .{ |
| 5070 | .data = .{ .inst = undefined }, | 4973 | .rd = .zero, |
| 4974 | .inst = undefined, | ||
| 4975 | } }, | ||
| 5071 | }); | 4976 | }); |
| 5072 | 4977 | ||
| 5073 | try func.exitlude_jump_relocs.append(func.gpa, index); | 4978 | try func.exitlude_jump_relocs.append(func.gpa, index); |
| ... | @@ -5089,9 +4994,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5089,9 +4994,11 @@ fn airRetLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 5089 | 4994 | ||
| 5090 | // Just add space for an instruction, reloced this later | 4995 | // Just add space for an instruction, reloced this later |
| 5091 | const index = try func.addInst(.{ | 4996 | const index = try func.addInst(.{ |
| 5092 | .tag = .pseudo, | 4997 | .tag = .pseudo_j, |
| 5093 | .ops = .pseudo_j, | 4998 | .data = .{ .j_type = .{ |
| 5094 | .data = .{ .inst = undefined }, | 4999 | .rd = .zero, |
| 5000 | .inst = undefined, | ||
| 5001 | } }, | ||
| 5095 | }); | 5002 | }); |
| 5096 | 5003 | ||
| 5097 | try func.exitlude_jump_relocs.append(func.gpa, index); | 5004 | try func.exitlude_jump_relocs.append(func.gpa, index); |
| ... | @@ -5171,8 +5078,7 @@ fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5171,8 +5078,7 @@ fn airDbgStmt(func: *Func, inst: Air.Inst.Index) !void { |
| 5171 | const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; | 5078 | const dbg_stmt = func.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt; |
| 5172 | 5079 | ||
| 5173 | _ = try func.addInst(.{ | 5080 | _ = try func.addInst(.{ |
| 5174 | .tag = .pseudo, | 5081 | .tag = .pseudo_dbg_line_column, |
| 5175 | .ops = .pseudo_dbg_line_column, | ||
| 5176 | .data = .{ .pseudo_dbg_line_column = .{ | 5082 | .data = .{ .pseudo_dbg_line_column = .{ |
| 5177 | .line = dbg_stmt.line, | 5083 | .line = dbg_stmt.line, |
| 5178 | .column = dbg_stmt.column, | 5084 | .column = dbg_stmt.column, |
| ... | @@ -5290,7 +5196,6 @@ fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index { | ... | @@ -5290,7 +5196,6 @@ fn condBr(func: *Func, cond_ty: Type, condition: MCValue) !Mir.Inst.Index { |
| 5290 | 5196 | ||
| 5291 | return try func.addInst(.{ | 5197 | return try func.addInst(.{ |
| 5292 | .tag = .beq, | 5198 | .tag = .beq, |
| 5293 | .ops = .rr_inst, | ||
| 5294 | .data = .{ | 5199 | .data = .{ |
| 5295 | .b_type = .{ | 5200 | .b_type = .{ |
| 5296 | .rs1 = cond_reg, | 5201 | .rs1 = cond_reg, |
| ... | @@ -5332,8 +5237,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -5332,8 +5237,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 5332 | .register => |opt_reg| { | 5237 | .register => |opt_reg| { |
| 5333 | if (some_info.off == 0) { | 5238 | if (some_info.off == 0) { |
| 5334 | _ = try func.addInst(.{ | 5239 | _ = try func.addInst(.{ |
| 5335 | .tag = .pseudo, | 5240 | .tag = .pseudo_compare, |
| 5336 | .ops = .pseudo_compare, | ||
| 5337 | .data = .{ | 5241 | .data = .{ |
| 5338 | .compare = .{ | 5242 | .compare = .{ |
| 5339 | .op = .eq, | 5243 | .op = .eq, |
| ... | @@ -5382,8 +5286,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -5382,8 +5286,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 5382 | defer func.register_manager.unlockReg(opt_reg_lock); | 5286 | defer func.register_manager.unlockReg(opt_reg_lock); |
| 5383 | 5287 | ||
| 5384 | _ = try func.addInst(.{ | 5288 | _ = try func.addInst(.{ |
| 5385 | .tag = .pseudo, | 5289 | .tag = .pseudo_compare, |
| 5386 | .ops = .pseudo_compare, | ||
| 5387 | .data = .{ | 5290 | .data = .{ |
| 5388 | .compare = .{ | 5291 | .compare = .{ |
| 5389 | .op = .eq, | 5292 | .op = .eq, |
| ... | @@ -5432,8 +5335,7 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5432,8 +5335,7 @@ fn airIsNonNull(func: *Func, inst: Air.Inst.Index) !void { |
| 5432 | assert(result == .register); | 5335 | assert(result == .register); |
| 5433 | 5336 | ||
| 5434 | _ = try func.addInst(.{ | 5337 | _ = try func.addInst(.{ |
| 5435 | .tag = .pseudo, | 5338 | .tag = .pseudo_not, |
| 5436 | .ops = .pseudo_not, | ||
| 5437 | .data = .{ | 5339 | .data = .{ |
| 5438 | .rr = .{ | 5340 | .rr = .{ |
| 5439 | .rd = result.register, | 5341 | .rd = result.register, |
| ... | @@ -5565,8 +5467,7 @@ fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC | ... | @@ -5565,8 +5467,7 @@ fn isNonErr(func: *Func, inst: Air.Inst.Index, eu_ty: Type, eu_mcv: MCValue) !MC |
| 5565 | switch (is_err_res) { | 5467 | switch (is_err_res) { |
| 5566 | .register => |reg| { | 5468 | .register => |reg| { |
| 5567 | _ = try func.addInst(.{ | 5469 | _ = try func.addInst(.{ |
| 5568 | .tag = .pseudo, | 5470 | .tag = .pseudo_not, |
| 5569 | .ops = .pseudo_not, | ||
| 5570 | .data = .{ | 5471 | .data = .{ |
| 5571 | .rr = .{ | 5472 | .rr = .{ |
| 5572 | .rd = reg, | 5473 | .rd = reg, |
| ... | @@ -5633,11 +5534,11 @@ fn airLoop(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5633,11 +5534,11 @@ fn airLoop(func: *Func, inst: Air.Inst.Index) !void { |
| 5633 | /// Send control flow to the `index` of `func.code`. | 5534 | /// Send control flow to the `index` of `func.code`. |
| 5634 | fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index { | 5535 | fn jump(func: *Func, index: Mir.Inst.Index) !Mir.Inst.Index { |
| 5635 | return func.addInst(.{ | 5536 | return func.addInst(.{ |
| 5636 | .tag = .pseudo, | 5537 | .tag = .pseudo_j, |
| 5637 | .ops = .pseudo_j, | 5538 | .data = .{ .j_type = .{ |
| 5638 | .data = .{ | 5539 | .rd = .zero, |
| 5639 | .inst = index, | 5540 | .inst = index, |
| 5640 | }, | 5541 | } }, |
| 5641 | }); | 5542 | }); |
| 5642 | } | 5543 | } |
| 5643 | 5544 | ||
| ... | @@ -5727,8 +5628,7 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5727,8 +5628,7 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void { |
| 5727 | 5628 | ||
| 5728 | if (!(i < relocs.len - 1)) { | 5629 | if (!(i < relocs.len - 1)) { |
| 5729 | _ = try func.addInst(.{ | 5630 | _ = try func.addInst(.{ |
| 5730 | .tag = .pseudo, | 5631 | .tag = .pseudo_not, |
| 5731 | .ops = .pseudo_not, | ||
| 5732 | .data = .{ .rr = .{ | 5632 | .data = .{ .rr = .{ |
| 5733 | .rd = cmp_reg, | 5633 | .rd = cmp_reg, |
| 5734 | .rs = cmp_reg, | 5634 | .rs = cmp_reg, |
| ... | @@ -5775,18 +5675,13 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5775,18 +5675,13 @@ fn airSwitchBr(func: *Func, inst: Air.Inst.Index) !void { |
| 5775 | 5675 | ||
| 5776 | fn performReloc(func: *Func, inst: Mir.Inst.Index) void { | 5676 | fn performReloc(func: *Func, inst: Mir.Inst.Index) void { |
| 5777 | const tag = func.mir_instructions.items(.tag)[inst]; | 5677 | const tag = func.mir_instructions.items(.tag)[inst]; |
| 5778 | const ops = func.mir_instructions.items(.ops)[inst]; | ||
| 5779 | const target: Mir.Inst.Index = @intCast(func.mir_instructions.len); | 5678 | const target: Mir.Inst.Index = @intCast(func.mir_instructions.len); |
| 5780 | 5679 | ||
| 5781 | switch (tag) { | 5680 | switch (tag) { |
| 5782 | .bne, | ||
| 5783 | .beq, | 5681 | .beq, |
| 5784 | => func.mir_instructions.items(.data)[inst].b_type.inst = target, | 5682 | => func.mir_instructions.items(.data)[inst].b_type.inst = target, |
| 5785 | .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target, | 5683 | .jal => func.mir_instructions.items(.data)[inst].j_type.inst = target, |
| 5786 | .pseudo => switch (ops) { | 5684 | .pseudo_j => func.mir_instructions.items(.data)[inst].j_type.inst = target, |
| 5787 | .pseudo_j => func.mir_instructions.items(.data)[inst].inst = target, | ||
| 5788 | else => std.debug.panic("TODO: performReloc {s}", .{@tagName(ops)}), | ||
| 5789 | }, | ||
| 5790 | else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}), | 5685 | else => std.debug.panic("TODO: performReloc {s}", .{@tagName(tag)}), |
| 5791 | } | 5686 | } |
| 5792 | } | 5687 | } |
| ... | @@ -5873,7 +5768,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5873,7 +5768,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { |
| 5873 | 5768 | ||
| 5874 | _ = try func.addInst(.{ | 5769 | _ = try func.addInst(.{ |
| 5875 | .tag = if (tag == .bool_or) .@"or" else .@"and", | 5770 | .tag = if (tag == .bool_or) .@"or" else .@"and", |
| 5876 | .ops = .rrr, | ||
| 5877 | .data = .{ .r_type = .{ | 5771 | .data = .{ .r_type = .{ |
| 5878 | .rd = result_reg, | 5772 | .rd = result_reg, |
| 5879 | .rs1 = lhs_reg, | 5773 | .rs1 = lhs_reg, |
| ... | @@ -5885,7 +5779,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5885,7 +5779,6 @@ fn airBoolOp(func: *Func, inst: Air.Inst.Index) !void { |
| 5885 | if (func.wantSafety()) { | 5779 | if (func.wantSafety()) { |
| 5886 | _ = try func.addInst(.{ | 5780 | _ = try func.addInst(.{ |
| 5887 | .tag = .andi, | 5781 | .tag = .andi, |
| 5888 | .ops = .rri, | ||
| 5889 | .data = .{ .i_type = .{ | 5782 | .data = .{ .i_type = .{ |
| 5890 | .rd = result_reg, | 5783 | .rd = result_reg, |
| 5891 | .rs1 = result_reg, | 5784 | .rs1 = result_reg, |
| ... | @@ -5970,11 +5863,10 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -5970,11 +5863,10 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 5970 | 5863 | ||
| 5971 | const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len]; | 5864 | const asm_source = std.mem.sliceAsBytes(func.air.extra[extra_i..])[0..extra.data.source_len]; |
| 5972 | 5865 | ||
| 5973 | if (std.meta.stringToEnum(Mir.Inst.Tag, asm_source)) |tag| { | 5866 | if (std.meta.stringToEnum(Mnemonic, asm_source)) |tag| { |
| 5974 | _ = try func.addInst(.{ | 5867 | _ = try func.addInst(.{ |
| 5975 | .tag = tag, | 5868 | .tag = tag, |
| 5976 | .ops = .none, | 5869 | .data = .none, |
| 5977 | .data = undefined, | ||
| 5978 | }); | 5870 | }); |
| 5979 | } else { | 5871 | } else { |
| 5980 | return func.fail("TODO: asm_source {s}", .{asm_source}); | 5872 | return func.fail("TODO: asm_source {s}", .{asm_source}); |
| ... | @@ -6116,7 +6008,6 @@ fn genInlineMemcpy( | ... | @@ -6116,7 +6008,6 @@ fn genInlineMemcpy( |
| 6116 | // if count is 0, there's nothing to copy | 6008 | // if count is 0, there's nothing to copy |
| 6117 | _ = try func.addInst(.{ | 6009 | _ = try func.addInst(.{ |
| 6118 | .tag = .beq, | 6010 | .tag = .beq, |
| 6119 | .ops = .rr_inst, | ||
| 6120 | .data = .{ .b_type = .{ | 6011 | .data = .{ .b_type = .{ |
| 6121 | .rs1 = count, | 6012 | .rs1 = count, |
| 6122 | .rs2 = .zero, | 6013 | .rs2 = .zero, |
| ... | @@ -6127,7 +6018,6 @@ fn genInlineMemcpy( | ... | @@ -6127,7 +6018,6 @@ fn genInlineMemcpy( |
| 6127 | // lb tmp, 0(src) | 6018 | // lb tmp, 0(src) |
| 6128 | const first_inst = try func.addInst(.{ | 6019 | const first_inst = try func.addInst(.{ |
| 6129 | .tag = .lb, | 6020 | .tag = .lb, |
| 6130 | .ops = .rri, | ||
| 6131 | .data = .{ | 6021 | .data = .{ |
| 6132 | .i_type = .{ | 6022 | .i_type = .{ |
| 6133 | .rd = tmp, | 6023 | .rd = tmp, |
| ... | @@ -6140,7 +6030,6 @@ fn genInlineMemcpy( | ... | @@ -6140,7 +6030,6 @@ fn genInlineMemcpy( |
| 6140 | // sb tmp, 0(dst) | 6030 | // sb tmp, 0(dst) |
| 6141 | _ = try func.addInst(.{ | 6031 | _ = try func.addInst(.{ |
| 6142 | .tag = .sb, | 6032 | .tag = .sb, |
| 6143 | .ops = .rri, | ||
| 6144 | .data = .{ | 6033 | .data = .{ |
| 6145 | .i_type = .{ | 6034 | .i_type = .{ |
| 6146 | .rd = dst, | 6035 | .rd = dst, |
| ... | @@ -6153,7 +6042,6 @@ fn genInlineMemcpy( | ... | @@ -6153,7 +6042,6 @@ fn genInlineMemcpy( |
| 6153 | // dec count by 1 | 6042 | // dec count by 1 |
| 6154 | _ = try func.addInst(.{ | 6043 | _ = try func.addInst(.{ |
| 6155 | .tag = .addi, | 6044 | .tag = .addi, |
| 6156 | .ops = .rri, | ||
| 6157 | .data = .{ | 6045 | .data = .{ |
| 6158 | .i_type = .{ | 6046 | .i_type = .{ |
| 6159 | .rd = count, | 6047 | .rd = count, |
| ... | @@ -6166,7 +6054,6 @@ fn genInlineMemcpy( | ... | @@ -6166,7 +6054,6 @@ fn genInlineMemcpy( |
| 6166 | // branch if count is 0 | 6054 | // branch if count is 0 |
| 6167 | _ = try func.addInst(.{ | 6055 | _ = try func.addInst(.{ |
| 6168 | .tag = .beq, | 6056 | .tag = .beq, |
| 6169 | .ops = .rr_inst, | ||
| 6170 | .data = .{ | 6057 | .data = .{ |
| 6171 | .b_type = .{ | 6058 | .b_type = .{ |
| 6172 | .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst | 6059 | .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst |
| ... | @@ -6179,7 +6066,6 @@ fn genInlineMemcpy( | ... | @@ -6179,7 +6066,6 @@ fn genInlineMemcpy( |
| 6179 | // increment the pointers | 6066 | // increment the pointers |
| 6180 | _ = try func.addInst(.{ | 6067 | _ = try func.addInst(.{ |
| 6181 | .tag = .addi, | 6068 | .tag = .addi, |
| 6182 | .ops = .rri, | ||
| 6183 | .data = .{ | 6069 | .data = .{ |
| 6184 | .i_type = .{ | 6070 | .i_type = .{ |
| 6185 | .rd = src, | 6071 | .rd = src, |
| ... | @@ -6191,7 +6077,6 @@ fn genInlineMemcpy( | ... | @@ -6191,7 +6077,6 @@ fn genInlineMemcpy( |
| 6191 | 6077 | ||
| 6192 | _ = try func.addInst(.{ | 6078 | _ = try func.addInst(.{ |
| 6193 | .tag = .addi, | 6079 | .tag = .addi, |
| 6194 | .ops = .rri, | ||
| 6195 | .data = .{ | 6080 | .data = .{ |
| 6196 | .i_type = .{ | 6081 | .i_type = .{ |
| 6197 | .rd = dst, | 6082 | .rd = dst, |
| ... | @@ -6203,9 +6088,11 @@ fn genInlineMemcpy( | ... | @@ -6203,9 +6088,11 @@ fn genInlineMemcpy( |
| 6203 | 6088 | ||
| 6204 | // jump back to start of loop | 6089 | // jump back to start of loop |
| 6205 | _ = try func.addInst(.{ | 6090 | _ = try func.addInst(.{ |
| 6206 | .tag = .pseudo, | 6091 | .tag = .pseudo_j, |
| 6207 | .ops = .pseudo_j, | 6092 | .data = .{ .j_type = .{ |
| 6208 | .data = .{ .inst = first_inst }, | 6093 | .rd = .zero, |
| 6094 | .inst = first_inst, | ||
| 6095 | } }, | ||
| 6209 | }); | 6096 | }); |
| 6210 | } | 6097 | } |
| 6211 | 6098 | ||
| ... | @@ -6230,7 +6117,6 @@ fn genInlineMemset( | ... | @@ -6230,7 +6117,6 @@ fn genInlineMemset( |
| 6230 | // sb src, 0(dst) | 6117 | // sb src, 0(dst) |
| 6231 | const first_inst = try func.addInst(.{ | 6118 | const first_inst = try func.addInst(.{ |
| 6232 | .tag = .sb, | 6119 | .tag = .sb, |
| 6233 | .ops = .rri, | ||
| 6234 | .data = .{ | 6120 | .data = .{ |
| 6235 | .i_type = .{ | 6121 | .i_type = .{ |
| 6236 | .rd = dst, | 6122 | .rd = dst, |
| ... | @@ -6243,7 +6129,6 @@ fn genInlineMemset( | ... | @@ -6243,7 +6129,6 @@ fn genInlineMemset( |
| 6243 | // dec count by 1 | 6129 | // dec count by 1 |
| 6244 | _ = try func.addInst(.{ | 6130 | _ = try func.addInst(.{ |
| 6245 | .tag = .addi, | 6131 | .tag = .addi, |
| 6246 | .ops = .rri, | ||
| 6247 | .data = .{ | 6132 | .data = .{ |
| 6248 | .i_type = .{ | 6133 | .i_type = .{ |
| 6249 | .rd = count, | 6134 | .rd = count, |
| ... | @@ -6256,7 +6141,6 @@ fn genInlineMemset( | ... | @@ -6256,7 +6141,6 @@ fn genInlineMemset( |
| 6256 | // branch if count is 0 | 6141 | // branch if count is 0 |
| 6257 | _ = try func.addInst(.{ | 6142 | _ = try func.addInst(.{ |
| 6258 | .tag = .beq, | 6143 | .tag = .beq, |
| 6259 | .ops = .rr_inst, | ||
| 6260 | .data = .{ | 6144 | .data = .{ |
| 6261 | .b_type = .{ | 6145 | .b_type = .{ |
| 6262 | .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst | 6146 | .inst = @intCast(func.mir_instructions.len + 4), // points after the last inst |
| ... | @@ -6269,7 +6153,6 @@ fn genInlineMemset( | ... | @@ -6269,7 +6153,6 @@ fn genInlineMemset( |
| 6269 | // increment the pointers | 6153 | // increment the pointers |
| 6270 | _ = try func.addInst(.{ | 6154 | _ = try func.addInst(.{ |
| 6271 | .tag = .addi, | 6155 | .tag = .addi, |
| 6272 | .ops = .rri, | ||
| 6273 | .data = .{ | 6156 | .data = .{ |
| 6274 | .i_type = .{ | 6157 | .i_type = .{ |
| 6275 | .rd = dst, | 6158 | .rd = dst, |
| ... | @@ -6281,11 +6164,11 @@ fn genInlineMemset( | ... | @@ -6281,11 +6164,11 @@ fn genInlineMemset( |
| 6281 | 6164 | ||
| 6282 | // jump back to start of loop | 6165 | // jump back to start of loop |
| 6283 | _ = try func.addInst(.{ | 6166 | _ = try func.addInst(.{ |
| 6284 | .tag = .pseudo, | 6167 | .tag = .pseudo_j, |
| 6285 | .ops = .pseudo_j, | 6168 | .data = .{ .j_type = .{ |
| 6286 | .data = .{ | 6169 | .rd = .zero, |
| 6287 | .inst = first_inst, | 6170 | .inst = first_inst, |
| 6288 | }, | 6171 | } }, |
| 6289 | }); | 6172 | }); |
| 6290 | } | 6173 | } |
| 6291 | 6174 | ||
| ... | @@ -6331,7 +6214,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6331,7 +6214,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6331 | if (math.minInt(i12) <= x and x <= math.maxInt(i12)) { | 6214 | if (math.minInt(i12) <= x and x <= math.maxInt(i12)) { |
| 6332 | _ = try func.addInst(.{ | 6215 | _ = try func.addInst(.{ |
| 6333 | .tag = .addi, | 6216 | .tag = .addi, |
| 6334 | .ops = .rri, | ||
| 6335 | .data = .{ .i_type = .{ | 6217 | .data = .{ .i_type = .{ |
| 6336 | .rd = reg, | 6218 | .rd = reg, |
| 6337 | .rs1 = .zero, | 6219 | .rs1 = .zero, |
| ... | @@ -6345,7 +6227,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6345,7 +6227,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6345 | 6227 | ||
| 6346 | _ = try func.addInst(.{ | 6228 | _ = try func.addInst(.{ |
| 6347 | .tag = .lui, | 6229 | .tag = .lui, |
| 6348 | .ops = .ri, | ||
| 6349 | .data = .{ .u_type = .{ | 6230 | .data = .{ .u_type = .{ |
| 6350 | .rd = reg, | 6231 | .rd = reg, |
| 6351 | .imm20 = Immediate.s(hi20), | 6232 | .imm20 = Immediate.s(hi20), |
| ... | @@ -6353,7 +6234,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6353,7 +6234,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6353 | }); | 6234 | }); |
| 6354 | _ = try func.addInst(.{ | 6235 | _ = try func.addInst(.{ |
| 6355 | .tag = .addi, | 6236 | .tag = .addi, |
| 6356 | .ops = .rri, | ||
| 6357 | .data = .{ .i_type = .{ | 6237 | .data = .{ .i_type = .{ |
| 6358 | .rd = reg, | 6238 | .rd = reg, |
| 6359 | .rs1 = reg, | 6239 | .rs1 = reg, |
| ... | @@ -6376,7 +6256,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6376,7 +6256,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6376 | 6256 | ||
| 6377 | _ = try func.addInst(.{ | 6257 | _ = try func.addInst(.{ |
| 6378 | .tag = .slli, | 6258 | .tag = .slli, |
| 6379 | .ops = .rri, | ||
| 6380 | .data = .{ .i_type = .{ | 6259 | .data = .{ .i_type = .{ |
| 6381 | .rd = reg, | 6260 | .rd = reg, |
| 6382 | .rs1 = reg, | 6261 | .rs1 = reg, |
| ... | @@ -6386,7 +6265,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6386,7 +6265,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6386 | 6265 | ||
| 6387 | _ = try func.addInst(.{ | 6266 | _ = try func.addInst(.{ |
| 6388 | .tag = .add, | 6267 | .tag = .add, |
| 6389 | .ops = .rrr, | ||
| 6390 | .data = .{ .r_type = .{ | 6268 | .data = .{ .r_type = .{ |
| 6391 | .rd = reg, | 6269 | .rd = reg, |
| 6392 | .rs1 = reg, | 6270 | .rs1 = reg, |
| ... | @@ -6423,8 +6301,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6423,8 +6301,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6423 | 6301 | ||
| 6424 | // mv reg, src_reg | 6302 | // mv reg, src_reg |
| 6425 | _ = try func.addInst(.{ | 6303 | _ = try func.addInst(.{ |
| 6426 | .tag = .pseudo, | 6304 | .tag = .pseudo_mv, |
| 6427 | .ops = .pseudo_mv, | ||
| 6428 | .data = .{ .rr = .{ | 6305 | .data = .{ .rr = .{ |
| 6429 | .rd = reg, | 6306 | .rd = reg, |
| 6430 | .rs = src_reg, | 6307 | .rs = src_reg, |
| ... | @@ -6445,8 +6322,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6445,8 +6322,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6445 | try func.genCopy(ty, .{ .register = reg }, .{ .indirect = .{ .reg = addr_reg } }); | 6322 | try func.genCopy(ty, .{ .register = reg }, .{ .indirect = .{ .reg = addr_reg } }); |
| 6446 | } else { | 6323 | } else { |
| 6447 | _ = try func.addInst(.{ | 6324 | _ = try func.addInst(.{ |
| 6448 | .tag = .pseudo, | 6325 | .tag = .pseudo_load_rm, |
| 6449 | .ops = .pseudo_load_rm, | ||
| 6450 | .data = .{ .rm = .{ | 6326 | .data = .{ .rm = .{ |
| 6451 | .r = reg, | 6327 | .r = reg, |
| 6452 | .m = .{ | 6328 | .m = .{ |
| ... | @@ -6466,7 +6342,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6466,7 +6342,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6466 | 6342 | ||
| 6467 | _ = try func.addInst(.{ | 6343 | _ = try func.addInst(.{ |
| 6468 | .tag = .ld, | 6344 | .tag = .ld, |
| 6469 | .ops = .rri, | ||
| 6470 | .data = .{ .i_type = .{ | 6345 | .data = .{ .i_type = .{ |
| 6471 | .rd = reg, | 6346 | .rd = reg, |
| 6472 | .rs1 = reg, | 6347 | .rs1 = reg, |
| ... | @@ -6476,8 +6351,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6476,8 +6351,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6476 | }, | 6351 | }, |
| 6477 | .lea_frame, .register_offset => { | 6352 | .lea_frame, .register_offset => { |
| 6478 | _ = try func.addInst(.{ | 6353 | _ = try func.addInst(.{ |
| 6479 | .tag = .pseudo, | 6354 | .tag = .pseudo_lea_rm, |
| 6480 | .ops = .pseudo_lea_rm, | ||
| 6481 | .data = .{ | 6355 | .data = .{ |
| 6482 | .rm = .{ | 6356 | .rm = .{ |
| 6483 | .r = reg, | 6357 | .r = reg, |
| ... | @@ -6505,7 +6379,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6505,7 +6379,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6505 | }); | 6379 | }); |
| 6506 | }, | 6380 | }, |
| 6507 | .indirect => |reg_off| { | 6381 | .indirect => |reg_off| { |
| 6508 | const load_tag: Mir.Inst.Tag = switch (reg.class()) { | 6382 | const load_tag: Mnemonic = switch (reg.class()) { |
| 6509 | .float => switch (abi_size) { | 6383 | .float => switch (abi_size) { |
| 6510 | 1 => unreachable, // Zig does not support 8-bit floats | 6384 | 1 => unreachable, // Zig does not support 8-bit floats |
| 6511 | 2 => return func.fail("TODO: genSetReg indirect 16-bit float", .{}), | 6385 | 2 => return func.fail("TODO: genSetReg indirect 16-bit float", .{}), |
| ... | @@ -6544,8 +6418,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6544,8 +6418,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6544 | }); | 6418 | }); |
| 6545 | 6419 | ||
| 6546 | _ = try func.addInst(.{ | 6420 | _ = try func.addInst(.{ |
| 6547 | .tag = .pseudo, | 6421 | .tag = .pseudo_load_rm, |
| 6548 | .ops = .pseudo_load_rm, | ||
| 6549 | .data = .{ .rm = .{ | 6422 | .data = .{ .rm = .{ |
| 6550 | .r = reg, | 6423 | .r = reg, |
| 6551 | .m = .{ | 6424 | .m = .{ |
| ... | @@ -6565,7 +6438,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6565,7 +6438,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6565 | 6438 | ||
| 6566 | _ = try func.addInst(.{ | 6439 | _ = try func.addInst(.{ |
| 6567 | .tag = load_tag, | 6440 | .tag = load_tag, |
| 6568 | .ops = .rri, | ||
| 6569 | .data = .{ .i_type = .{ | 6441 | .data = .{ .i_type = .{ |
| 6570 | .rd = reg, | 6442 | .rd = reg, |
| 6571 | .rs1 = reg_off.reg, | 6443 | .rs1 = reg_off.reg, |
| ... | @@ -6578,13 +6450,12 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -6578,13 +6450,12 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6578 | const atom_index = try func.owner.getSymbolIndex(func); | 6450 | const atom_index = try func.owner.getSymbolIndex(func); |
| 6579 | 6451 | ||
| 6580 | _ = try func.addInst(.{ | 6452 | _ = try func.addInst(.{ |
| 6581 | .tag = .pseudo, | 6453 | .tag = .pseudo_load_symbol, |
| 6582 | .ops = .pseudo_load_symbol, | 6454 | .data = .{ .reloc = .{ |
| 6583 | .data = .{ .payload = try func.addExtra(Mir.LoadSymbolPayload{ | 6455 | .register = reg, |
| 6584 | .register = reg.encodeId(), | ||
| 6585 | .atom_index = atom_index, | 6456 | .atom_index = atom_index, |
| 6586 | .sym_index = sym_off.sym, | 6457 | .sym_index = sym_off.sym, |
| 6587 | }) }, | 6458 | } }, |
| 6588 | }); | 6459 | }); |
| 6589 | }, | 6460 | }, |
| 6590 | .load_symbol => { | 6461 | .load_symbol => { |
| ... | @@ -6676,8 +6547,7 @@ fn genSetMem( | ... | @@ -6676,8 +6547,7 @@ fn genSetMem( |
| 6676 | }); | 6547 | }); |
| 6677 | 6548 | ||
| 6678 | _ = try func.addInst(.{ | 6549 | _ = try func.addInst(.{ |
| 6679 | .tag = .pseudo, | 6550 | .tag = .pseudo_store_rm, |
| 6680 | .ops = .pseudo_store_rm, | ||
| 6681 | .data = .{ .rm = .{ | 6551 | .data = .{ .rm = .{ |
| 6682 | .r = reg, | 6552 | .r = reg, |
| 6683 | .m = .{ | 6553 | .m = .{ |
| ... | @@ -6716,8 +6586,7 @@ fn genSetMem( | ... | @@ -6716,8 +6586,7 @@ fn genSetMem( |
| 6716 | })); | 6586 | })); |
| 6717 | const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } }; | 6587 | const frame_mcv: MCValue = .{ .load_frame = .{ .index = frame_index } }; |
| 6718 | _ = try func.addInst(.{ | 6588 | _ = try func.addInst(.{ |
| 6719 | .tag = .pseudo, | 6589 | .tag = .pseudo_store_rm, |
| 6720 | .ops = .pseudo_store_rm, | ||
| 6721 | .data = .{ .rm = .{ | 6590 | .data = .{ .rm = .{ |
| 6722 | .r = reg, | 6591 | .r = reg, |
| 6723 | .m = .{ | 6592 | .m = .{ |
| ... | @@ -6732,8 +6601,7 @@ fn genSetMem( | ... | @@ -6732,8 +6601,7 @@ fn genSetMem( |
| 6732 | try func.genSetMem(base, disp, ty, frame_mcv); | 6601 | try func.genSetMem(base, disp, ty, frame_mcv); |
| 6733 | try func.freeValue(frame_mcv); | 6602 | try func.freeValue(frame_mcv); |
| 6734 | } else _ = try func.addInst(.{ | 6603 | } else _ = try func.addInst(.{ |
| 6735 | .tag = .pseudo, | 6604 | .tag = .pseudo_store_rm, |
| 6736 | .ops = .pseudo_store_rm, | ||
| 6737 | .data = .{ .rm = .{ | 6605 | .data = .{ .rm = .{ |
| 6738 | .r = reg, | 6606 | .r = reg, |
| 6739 | .m = .{ | 6607 | .m = .{ |
| ... | @@ -6852,9 +6720,59 @@ fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6852,9 +6720,59 @@ fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void { |
| 6852 | 6720 | ||
| 6853 | fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { | 6721 | fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void { |
| 6854 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6722 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6855 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airIntFromFloat for {}", .{ | 6723 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 6856 | func.target.cpu.arch, | 6724 | const pt = func.pt; |
| 6857 | }); | 6725 | const zcu = pt.zcu; |
| 6726 | |||
| 6727 | const operand = try func.resolveInst(ty_op.operand); | ||
| 6728 | const src_ty = func.typeOf(ty_op.operand); | ||
| 6729 | const dst_ty = func.typeOfIndex(inst); | ||
| 6730 | |||
| 6731 | const is_unsigned = dst_ty.isUnsignedInt(zcu); | ||
| 6732 | const src_bits = src_ty.bitSize(pt); | ||
| 6733 | const dst_bits = dst_ty.bitSize(pt); | ||
| 6734 | |||
| 6735 | const float_mod: enum { s, d } = switch (src_bits) { | ||
| 6736 | 32 => .s, | ||
| 6737 | 64 => .d, | ||
| 6738 | else => return func.fail("TODO: airIntFromFloat src size {d}", .{src_bits}), | ||
| 6739 | }; | ||
| 6740 | |||
| 6741 | const int_mod: Mir.FcvtOp = switch (dst_bits) { | ||
| 6742 | 32 => if (is_unsigned) .wu else .w, | ||
| 6743 | 64 => if (is_unsigned) .lu else .l, | ||
| 6744 | else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}), | ||
| 6745 | }; | ||
| 6746 | |||
| 6747 | const src_reg, const src_lock = try func.promoteReg(src_ty, operand); | ||
| 6748 | defer if (src_lock) |lock| func.register_manager.unlockReg(lock); | ||
| 6749 | |||
| 6750 | const dst_reg, const dst_lock = try func.allocReg(.int); | ||
| 6751 | defer func.register_manager.unlockReg(dst_lock); | ||
| 6752 | |||
| 6753 | _ = try func.addInst(.{ | ||
| 6754 | .tag = switch (float_mod) { | ||
| 6755 | .s => switch (int_mod) { | ||
| 6756 | .l => .fcvtls, | ||
| 6757 | .lu => .fcvtlus, | ||
| 6758 | .w => .fcvtws, | ||
| 6759 | .wu => .fcvtwus, | ||
| 6760 | }, | ||
| 6761 | .d => switch (int_mod) { | ||
| 6762 | .l => .fcvtld, | ||
| 6763 | .lu => .fcvtlud, | ||
| 6764 | .w => .fcvtwd, | ||
| 6765 | .wu => .fcvtwud, | ||
| 6766 | }, | ||
| 6767 | }, | ||
| 6768 | .data = .{ .rr = .{ | ||
| 6769 | .rd = dst_reg, | ||
| 6770 | .rs = src_reg, | ||
| 6771 | } }, | ||
| 6772 | }); | ||
| 6773 | |||
| 6774 | break :result .{ .register = dst_reg }; | ||
| 6775 | }; | ||
| 6858 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 6776 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6859 | } | 6777 | } |
| 6860 | 6778 | ||
| ... | @@ -6917,8 +6835,7 @@ fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6917,8 +6835,7 @@ fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void { |
| 6917 | }; | 6835 | }; |
| 6918 | 6836 | ||
| 6919 | _ = try func.addInst(.{ | 6837 | _ = try func.addInst(.{ |
| 6920 | .tag = .pseudo, | 6838 | .tag = .pseudo_amo, |
| 6921 | .ops = .pseudo_amo, | ||
| 6922 | .data = .{ .amo = .{ | 6839 | .data = .{ .amo = .{ |
| 6923 | .rd = result_mcv.register, | 6840 | .rd = result_mcv.register, |
| 6924 | .rs1 = ptr_register, | 6841 | .rs1 = ptr_register, |
| ... | @@ -6961,15 +6878,12 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6961,15 +6878,12 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6961 | 6878 | ||
| 6962 | if (order == .seq_cst) { | 6879 | if (order == .seq_cst) { |
| 6963 | _ = try func.addInst(.{ | 6880 | _ = try func.addInst(.{ |
| 6964 | .tag = .pseudo, | 6881 | .tag = .pseudo_fence, |
| 6965 | .ops = .pseudo_fence, | 6882 | .data = .{ .fence = .{ |
| 6966 | .data = .{ | 6883 | .pred = .rw, |
| 6967 | .fence = .{ | 6884 | .succ = .rw, |
| 6968 | .pred = .rw, | 6885 | .fm = .none, |
| 6969 | .succ = .rw, | 6886 | } }, |
| 6970 | .fm = .none, | ||
| 6971 | }, | ||
| 6972 | }, | ||
| 6973 | }); | 6887 | }); |
| 6974 | } | 6888 | } |
| 6975 | 6889 | ||
| ... | @@ -6982,8 +6896,7 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -6982,8 +6896,7 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6982 | // Make sure all previous reads happen before any reading or writing accurs. | 6896 | // Make sure all previous reads happen before any reading or writing accurs. |
| 6983 | .seq_cst, .acquire => { | 6897 | .seq_cst, .acquire => { |
| 6984 | _ = try func.addInst(.{ | 6898 | _ = try func.addInst(.{ |
| 6985 | .tag = .pseudo, | 6899 | .tag = .pseudo_fence, |
| 6986 | .ops = .pseudo_fence, | ||
| 6987 | .data = .{ | 6900 | .data = .{ |
| 6988 | .fence = .{ | 6901 | .fence = .{ |
| 6989 | .pred = .r, | 6902 | .pred = .r, |
| ... | @@ -7015,8 +6928,7 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr | ... | @@ -7015,8 +6928,7 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 7015 | .unordered, .monotonic => {}, | 6928 | .unordered, .monotonic => {}, |
| 7016 | .release, .seq_cst => { | 6929 | .release, .seq_cst => { |
| 7017 | _ = try func.addInst(.{ | 6930 | _ = try func.addInst(.{ |
| 7018 | .tag = .pseudo, | 6931 | .tag = .pseudo_fence, |
| 7019 | .ops = .pseudo_fence, | ||
| 7020 | .data = .{ | 6932 | .data = .{ |
| 7021 | .fence = .{ | 6933 | .fence = .{ |
| 7022 | .pred = .rw, | 6934 | .pred = .rw, |
| ... | @@ -7183,7 +7095,6 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -7183,7 +7095,6 @@ fn airTagName(func: *Func, inst: Air.Inst.Index) !void { |
| 7183 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); | 7095 | try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym.esym_index } }); |
| 7184 | _ = try func.addInst(.{ | 7096 | _ = try func.addInst(.{ |
| 7185 | .tag = .jalr, | 7097 | .tag = .jalr, |
| 7186 | .ops = .rri, | ||
| 7187 | .data = .{ .i_type = .{ | 7098 | .data = .{ .i_type = .{ |
| 7188 | .rd = .ra, | 7099 | .rd = .ra, |
| 7189 | .rs1 = .ra, | 7100 | .rs1 = .ra, |
src/arch/riscv64/Emit.zig+71-77| ... | @@ -40,7 +40,7 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -40,7 +40,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 40 | .source = start_offset, | 40 | .source = start_offset, |
| 41 | .target = target, | 41 | .target = target, |
| 42 | .offset = 0, | 42 | .offset = 0, |
| 43 | .enc = std.meta.activeTag(lowered_inst.encoding.data), | 43 | .fmt = std.meta.activeTag(lowered_inst), |
| 44 | }), | 44 | }), |
| 45 | .load_symbol_reloc => |symbol| { | 45 | .load_symbol_reloc => |symbol| { |
| 46 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { | 46 | const is_obj_or_static_lib = switch (emit.lower.output_mode) { |
| ... | @@ -49,46 +49,45 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -49,46 +49,45 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 49 | .Lib => emit.lower.link_mode == .static, | 49 | .Lib => emit.lower.link_mode == .static, |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | if (emit.bin_file.cast(link.File.Elf)) |elf_file| { | 52 | const elf_file = emit.bin_file.cast(link.File.Elf).?; |
| 53 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | 53 | |
| 54 | const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index); | 54 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; |
| 55 | const sym = elf_file.symbol(sym_index); | 55 | const sym_index = elf_file.zigObjectPtr().?.symbol(symbol.sym_index); |
| 56 | 56 | const sym = elf_file.symbol(sym_index); | |
| 57 | var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20); | 57 | |
| 58 | var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I); | 58 | var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20); |
| 59 | 59 | var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I); | |
| 60 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { | 60 | |
| 61 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | 61 | if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { |
| 62 | 62 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | |
| 63 | hi_r_type = Elf.R_ZIG_GOT_HI20; | 63 | |
| 64 | lo_r_type = Elf.R_ZIG_GOT_LO12; | 64 | hi_r_type = Elf.R_ZIG_GOT_HI20; |
| 65 | } | 65 | lo_r_type = Elf.R_ZIG_GOT_LO12; |
| 66 | 66 | } | |
| 67 | try atom_ptr.addReloc(elf_file, .{ | 67 | |
| 68 | .r_offset = start_offset, | 68 | try atom_ptr.addReloc(elf_file, .{ |
| 69 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type, | 69 | .r_offset = start_offset, |
| 70 | .r_addend = 0, | 70 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type, |
| 71 | }); | 71 | .r_addend = 0, |
| 72 | 72 | }); | |
| 73 | try atom_ptr.addReloc(elf_file, .{ | 73 | |
| 74 | .r_offset = start_offset + 4, | 74 | try atom_ptr.addReloc(elf_file, .{ |
| 75 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type, | 75 | .r_offset = start_offset + 4, |
| 76 | .r_addend = 0, | 76 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type, |
| 77 | }); | 77 | .r_addend = 0, |
| 78 | } else unreachable; | 78 | }); |
| 79 | }, | 79 | }, |
| 80 | .call_extern_fn_reloc => |symbol| { | 80 | .call_extern_fn_reloc => |symbol| { |
| 81 | if (emit.bin_file.cast(link.File.Elf)) |elf_file| { | 81 | const elf_file = emit.bin_file.cast(link.File.Elf).?; |
| 82 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; | 82 | const atom_ptr = elf_file.symbol(symbol.atom_index).atom(elf_file).?; |
| 83 | 83 | ||
| 84 | const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT); | 84 | const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT); |
| 85 | 85 | ||
| 86 | try atom_ptr.addReloc(elf_file, .{ | 86 | try atom_ptr.addReloc(elf_file, .{ |
| 87 | .r_offset = start_offset, | 87 | .r_offset = start_offset, |
| 88 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, | 88 | .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type, |
| 89 | .r_addend = 0, | 89 | .r_addend = 0, |
| 90 | }); | 90 | }); |
| 91 | } else return emit.fail("TODO: call_extern_fn_reloc non-ELF", .{}); | ||
| 92 | }, | 91 | }, |
| 93 | }; | 92 | }; |
| 94 | } | 93 | } |
| ... | @@ -98,40 +97,37 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -98,40 +97,37 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 98 | const mir_inst = emit.lower.mir.instructions.get(mir_index); | 97 | const mir_inst = emit.lower.mir.instructions.get(mir_index); |
| 99 | switch (mir_inst.tag) { | 98 | switch (mir_inst.tag) { |
| 100 | else => unreachable, | 99 | else => unreachable, |
| 101 | .pseudo => switch (mir_inst.ops) { | 100 | .pseudo_dbg_prologue_end => { |
| 102 | else => unreachable, | 101 | switch (emit.debug_output) { |
| 103 | .pseudo_dbg_prologue_end => { | 102 | .dwarf => |dw| { |
| 104 | switch (emit.debug_output) { | 103 | try dw.setPrologueEnd(); |
| 105 | .dwarf => |dw| { | 104 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ |
| 106 | try dw.setPrologueEnd(); | 105 | emit.prev_di_line, emit.prev_di_column, |
| 107 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ | 106 | }); |
| 108 | emit.prev_di_line, emit.prev_di_column, | 107 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 109 | }); | 108 | }, |
| 110 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | 109 | .plan9 => {}, |
| 111 | }, | 110 | .none => {}, |
| 112 | .plan9 => {}, | 111 | } |
| 113 | .none => {}, | ||
| 114 | } | ||
| 115 | }, | ||
| 116 | .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine( | ||
| 117 | mir_inst.data.pseudo_dbg_line_column.line, | ||
| 118 | mir_inst.data.pseudo_dbg_line_column.column, | ||
| 119 | ), | ||
| 120 | .pseudo_dbg_epilogue_begin => { | ||
| 121 | switch (emit.debug_output) { | ||
| 122 | .dwarf => |dw| { | ||
| 123 | try dw.setEpilogueBegin(); | ||
| 124 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | ||
| 125 | emit.prev_di_line, emit.prev_di_column, | ||
| 126 | }); | ||
| 127 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 128 | }, | ||
| 129 | .plan9 => {}, | ||
| 130 | .none => {}, | ||
| 131 | } | ||
| 132 | }, | ||
| 133 | .pseudo_dead => {}, | ||
| 134 | }, | 112 | }, |
| 113 | .pseudo_dbg_line_column => try emit.dbgAdvancePCAndLine( | ||
| 114 | mir_inst.data.pseudo_dbg_line_column.line, | ||
| 115 | mir_inst.data.pseudo_dbg_line_column.column, | ||
| 116 | ), | ||
| 117 | .pseudo_dbg_epilogue_begin => { | ||
| 118 | switch (emit.debug_output) { | ||
| 119 | .dwarf => |dw| { | ||
| 120 | try dw.setEpilogueBegin(); | ||
| 121 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | ||
| 122 | emit.prev_di_line, emit.prev_di_column, | ||
| 123 | }); | ||
| 124 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 125 | }, | ||
| 126 | .plan9 => {}, | ||
| 127 | .none => {}, | ||
| 128 | } | ||
| 129 | }, | ||
| 130 | .pseudo_dead => {}, | ||
| 135 | } | 131 | } |
| 136 | } | 132 | } |
| 137 | } | 133 | } |
| ... | @@ -151,8 +147,8 @@ const Reloc = struct { | ... | @@ -151,8 +147,8 @@ const Reloc = struct { |
| 151 | target: Mir.Inst.Index, | 147 | target: Mir.Inst.Index, |
| 152 | /// Offset of the relocation within the instruction. | 148 | /// Offset of the relocation within the instruction. |
| 153 | offset: u32, | 149 | offset: u32, |
| 154 | /// Encoding of the instruction, used to determine how to modify it. | 150 | /// Format of the instruction, used to determine how to modify it. |
| 155 | enc: Encoding.InstEnc, | 151 | fmt: encoding.Lir.Format, |
| 156 | }; | 152 | }; |
| 157 | 153 | ||
| 158 | fn fixupRelocs(emit: *Emit) Error!void { | 154 | fn fixupRelocs(emit: *Emit) Error!void { |
| ... | @@ -164,12 +160,10 @@ fn fixupRelocs(emit: *Emit) Error!void { | ... | @@ -164,12 +160,10 @@ fn fixupRelocs(emit: *Emit) Error!void { |
| 164 | const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source)); | 160 | const disp = @as(i32, @intCast(target)) - @as(i32, @intCast(reloc.source)); |
| 165 | const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4]; | 161 | const code: *[4]u8 = emit.code.items[reloc.source + reloc.offset ..][0..4]; |
| 166 | 162 | ||
| 167 | log.debug("disp: {x}", .{disp}); | 163 | switch (reloc.fmt) { |
| 168 | |||
| 169 | switch (reloc.enc) { | ||
| 170 | .J => riscv_util.writeInstJ(code, @bitCast(disp)), | 164 | .J => riscv_util.writeInstJ(code, @bitCast(disp)), |
| 171 | .B => riscv_util.writeInstB(code, @bitCast(disp)), | 165 | .B => riscv_util.writeInstB(code, @bitCast(disp)), |
| 172 | else => return emit.fail("tried to reloc encoding type {s}", .{@tagName(reloc.enc)}), | 166 | else => return emit.fail("tried to reloc format type {s}", .{@tagName(reloc.fmt)}), |
| 173 | } | 167 | } |
| 174 | } | 168 | } |
| 175 | } | 169 | } |
| ... | @@ -209,5 +203,5 @@ const Emit = @This(); | ... | @@ -209,5 +203,5 @@ const Emit = @This(); |
| 209 | const Lower = @import("Lower.zig"); | 203 | const Lower = @import("Lower.zig"); |
| 210 | const Mir = @import("Mir.zig"); | 204 | const Mir = @import("Mir.zig"); |
| 211 | const riscv_util = @import("../../link/riscv.zig"); | 205 | const riscv_util = @import("../../link/riscv.zig"); |
| 212 | const Encoding = @import("Encoding.zig"); | ||
| 213 | const Elf = @import("../../link/Elf.zig"); | 206 | const Elf = @import("../../link/Elf.zig"); |
| 207 | const encoding = @import("encoding.zig"); |
src/arch/riscv64/Encoding.zig deleted-1136| ... | @@ -1,1136 +0,0 @@ | ||
| 1 | mnemonic: Mnemonic, | ||
| 2 | data: Data, | ||
| 3 | |||
| 4 | const OpCode = enum(u7) { | ||
| 5 | LOAD = 0b0000011, | ||
| 6 | LOAD_FP = 0b0000111, | ||
| 7 | MISC_MEM = 0b0001111, | ||
| 8 | OP_IMM = 0b0010011, | ||
| 9 | AUIPC = 0b0010111, | ||
| 10 | OP_IMM_32 = 0b0011011, | ||
| 11 | STORE = 0b0100011, | ||
| 12 | STORE_FP = 0b0100111, | ||
| 13 | AMO = 0b0101111, | ||
| 14 | OP_V = 0b1010111, | ||
| 15 | OP = 0b0110011, | ||
| 16 | OP_32 = 0b0111011, | ||
| 17 | LUI = 0b0110111, | ||
| 18 | MADD = 0b1000011, | ||
| 19 | MSUB = 0b1000111, | ||
| 20 | NMSUB = 0b1001011, | ||
| 21 | NMADD = 0b1001111, | ||
| 22 | OP_FP = 0b1010011, | ||
| 23 | OP_IMM_64 = 0b1011011, | ||
| 24 | BRANCH = 0b1100011, | ||
| 25 | JALR = 0b1100111, | ||
| 26 | JAL = 0b1101111, | ||
| 27 | SYSTEM = 0b1110011, | ||
| 28 | OP_64 = 0b1111011, | ||
| 29 | NONE = 0b00000000, | ||
| 30 | }; | ||
| 31 | |||
| 32 | const FpFmt = enum(u2) { | ||
| 33 | /// 32-bit single-precision | ||
| 34 | S = 0b00, | ||
| 35 | /// 64-bit double-precision | ||
| 36 | D = 0b01, | ||
| 37 | |||
| 38 | // H = 0b10, unused in the G extension | ||
| 39 | |||
| 40 | /// 128-bit quad-precision | ||
| 41 | Q = 0b11, | ||
| 42 | }; | ||
| 43 | |||
| 44 | const AmoWidth = enum(u3) { | ||
| 45 | W = 0b010, | ||
| 46 | D = 0b011, | ||
| 47 | }; | ||
| 48 | |||
| 49 | const FenceMode = enum(u4) { | ||
| 50 | none = 0b0000, | ||
| 51 | tso = 0b1000, | ||
| 52 | }; | ||
| 53 | |||
| 54 | const Enc = struct { | ||
| 55 | opcode: OpCode, | ||
| 56 | |||
| 57 | data: union(enum) { | ||
| 58 | /// funct3 + funct7 | ||
| 59 | ff: struct { | ||
| 60 | funct3: u3, | ||
| 61 | funct7: u7, | ||
| 62 | }, | ||
| 63 | amo: struct { | ||
| 64 | funct5: u5, | ||
| 65 | width: AmoWidth, | ||
| 66 | }, | ||
| 67 | fence: struct { | ||
| 68 | funct3: u3, | ||
| 69 | fm: FenceMode, | ||
| 70 | }, | ||
| 71 | /// funct5 + rm + fmt | ||
| 72 | fmt: struct { | ||
| 73 | funct5: u5, | ||
| 74 | rm: u3, | ||
| 75 | fmt: FpFmt, | ||
| 76 | }, | ||
| 77 | /// funct3 | ||
| 78 | f: struct { | ||
| 79 | funct3: u3, | ||
| 80 | }, | ||
| 81 | /// typ + funct3 + has_5 | ||
| 82 | sh: struct { | ||
| 83 | typ: u6, | ||
| 84 | funct3: u3, | ||
| 85 | has_5: bool, | ||
| 86 | }, | ||
| 87 | vecls: struct { | ||
| 88 | width: VecWidth, | ||
| 89 | umop: Umop, | ||
| 90 | vm: bool, | ||
| 91 | mop: Mop, | ||
| 92 | mew: bool, | ||
| 93 | nf: u3, | ||
| 94 | }, | ||
| 95 | vecmath: struct { | ||
| 96 | vm: bool, | ||
| 97 | funct6: u6, | ||
| 98 | funct3: VecType, | ||
| 99 | }, | ||
| 100 | /// U-type | ||
| 101 | none, | ||
| 102 | }, | ||
| 103 | |||
| 104 | const Mop = enum(u2) { | ||
| 105 | unit = 0b00, | ||
| 106 | unord = 0b01, | ||
| 107 | stride = 0b10, | ||
| 108 | ord = 0b11, | ||
| 109 | }; | ||
| 110 | |||
| 111 | const Umop = enum(u5) { | ||
| 112 | unit = 0b00000, | ||
| 113 | whole = 0b01000, | ||
| 114 | mask = 0b01011, | ||
| 115 | fault = 0b10000, | ||
| 116 | }; | ||
| 117 | |||
| 118 | const VecWidth = enum(u3) { | ||
| 119 | // zig fmt: off | ||
| 120 | @"8" = 0b000, | ||
| 121 | @"16" = 0b101, | ||
| 122 | @"32" = 0b110, | ||
| 123 | @"64" = 0b111, | ||
| 124 | // zig fmt: on | ||
| 125 | }; | ||
| 126 | |||
| 127 | const VecType = enum(u3) { | ||
| 128 | OPIVV = 0b000, | ||
| 129 | OPFVV = 0b001, | ||
| 130 | OPMVV = 0b010, | ||
| 131 | OPIVI = 0b011, | ||
| 132 | OPIVX = 0b100, | ||
| 133 | OPFVF = 0b101, | ||
| 134 | OPMVX = 0b110, | ||
| 135 | }; | ||
| 136 | }; | ||
| 137 | |||
| 138 | // TODO: this is basically a copy of the MIR table, we should be able to de-dupe them somehow. | ||
| 139 | pub const Mnemonic = enum { | ||
| 140 | // base mnemonics | ||
| 141 | |||
| 142 | // I Type | ||
| 143 | ld, | ||
| 144 | lw, | ||
| 145 | lwu, | ||
| 146 | lh, | ||
| 147 | lhu, | ||
| 148 | lb, | ||
| 149 | lbu, | ||
| 150 | |||
| 151 | sltiu, | ||
| 152 | xori, | ||
| 153 | andi, | ||
| 154 | |||
| 155 | slli, | ||
| 156 | srli, | ||
| 157 | srai, | ||
| 158 | |||
| 159 | slliw, | ||
| 160 | srliw, | ||
| 161 | sraiw, | ||
| 162 | |||
| 163 | addi, | ||
| 164 | jalr, | ||
| 165 | |||
| 166 | vsetivli, | ||
| 167 | vsetvli, | ||
| 168 | |||
| 169 | // U Type | ||
| 170 | lui, | ||
| 171 | auipc, | ||
| 172 | |||
| 173 | // S Type | ||
| 174 | sd, | ||
| 175 | sw, | ||
| 176 | sh, | ||
| 177 | sb, | ||
| 178 | |||
| 179 | // J Type | ||
| 180 | jal, | ||
| 181 | |||
| 182 | // B Type | ||
| 183 | beq, | ||
| 184 | |||
| 185 | // R Type | ||
| 186 | add, | ||
| 187 | addw, | ||
| 188 | sub, | ||
| 189 | subw, | ||
| 190 | @"and", | ||
| 191 | @"or", | ||
| 192 | slt, | ||
| 193 | sltu, | ||
| 194 | xor, | ||
| 195 | |||
| 196 | sll, | ||
| 197 | srl, | ||
| 198 | sra, | ||
| 199 | |||
| 200 | sllw, | ||
| 201 | srlw, | ||
| 202 | sraw, | ||
| 203 | |||
| 204 | // System | ||
| 205 | ecall, | ||
| 206 | ebreak, | ||
| 207 | unimp, | ||
| 208 | |||
| 209 | csrrs, | ||
| 210 | |||
| 211 | // M extension | ||
| 212 | mul, | ||
| 213 | mulw, | ||
| 214 | |||
| 215 | mulh, | ||
| 216 | mulhu, | ||
| 217 | mulhsu, | ||
| 218 | |||
| 219 | div, | ||
| 220 | divu, | ||
| 221 | |||
| 222 | divw, | ||
| 223 | divuw, | ||
| 224 | |||
| 225 | rem, | ||
| 226 | remu, | ||
| 227 | |||
| 228 | remw, | ||
| 229 | remuw, | ||
| 230 | |||
| 231 | // F extension (32-bit float) | ||
| 232 | fadds, | ||
| 233 | fsubs, | ||
| 234 | fmuls, | ||
| 235 | fdivs, | ||
| 236 | |||
| 237 | fmins, | ||
| 238 | fmaxs, | ||
| 239 | |||
| 240 | fsqrts, | ||
| 241 | |||
| 242 | flw, | ||
| 243 | fsw, | ||
| 244 | |||
| 245 | feqs, | ||
| 246 | flts, | ||
| 247 | fles, | ||
| 248 | |||
| 249 | fsgnjns, | ||
| 250 | fsgnjxs, | ||
| 251 | |||
| 252 | // D extension (64-bit float) | ||
| 253 | faddd, | ||
| 254 | fsubd, | ||
| 255 | fmuld, | ||
| 256 | fdivd, | ||
| 257 | |||
| 258 | fmind, | ||
| 259 | fmaxd, | ||
| 260 | |||
| 261 | fsqrtd, | ||
| 262 | |||
| 263 | fld, | ||
| 264 | fsd, | ||
| 265 | |||
| 266 | feqd, | ||
| 267 | fltd, | ||
| 268 | fled, | ||
| 269 | |||
| 270 | fsgnjnd, | ||
| 271 | fsgnjxd, | ||
| 272 | |||
| 273 | // V Extension | ||
| 274 | vle8v, | ||
| 275 | vle16v, | ||
| 276 | vle32v, | ||
| 277 | vle64v, | ||
| 278 | |||
| 279 | vse8v, | ||
| 280 | vse16v, | ||
| 281 | vse32v, | ||
| 282 | vse64v, | ||
| 283 | |||
| 284 | vsoxei8v, | ||
| 285 | |||
| 286 | vaddvv, | ||
| 287 | vsubvv, | ||
| 288 | |||
| 289 | vfaddvv, | ||
| 290 | vfsubvv, | ||
| 291 | |||
| 292 | vmulvv, | ||
| 293 | vfmulvv, | ||
| 294 | |||
| 295 | vadcvv, | ||
| 296 | |||
| 297 | vmvvx, | ||
| 298 | |||
| 299 | vslidedownvx, | ||
| 300 | |||
| 301 | // MISC | ||
| 302 | fence, | ||
| 303 | fencetso, | ||
| 304 | |||
| 305 | // AMO | ||
| 306 | amoswapw, | ||
| 307 | amoaddw, | ||
| 308 | amoandw, | ||
| 309 | amoorw, | ||
| 310 | amoxorw, | ||
| 311 | amomaxw, | ||
| 312 | amominw, | ||
| 313 | amomaxuw, | ||
| 314 | amominuw, | ||
| 315 | |||
| 316 | amoswapd, | ||
| 317 | amoaddd, | ||
| 318 | amoandd, | ||
| 319 | amoord, | ||
| 320 | amoxord, | ||
| 321 | amomaxd, | ||
| 322 | amomind, | ||
| 323 | amomaxud, | ||
| 324 | amominud, | ||
| 325 | |||
| 326 | // TODO: Q extension | ||
| 327 | |||
| 328 | // Zbb Extension | ||
| 329 | clz, | ||
| 330 | clzw, | ||
| 331 | |||
| 332 | pub fn encoding(mnem: Mnemonic) Enc { | ||
| 333 | return switch (mnem) { | ||
| 334 | // zig fmt: off | ||
| 335 | |||
| 336 | // OP | ||
| 337 | |||
| 338 | .add => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, | ||
| 339 | .sub => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, | ||
| 340 | |||
| 341 | .@"and" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } }, | ||
| 342 | .@"or" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } }, | ||
| 343 | .xor => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } }, | ||
| 344 | |||
| 345 | .sltu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } }, | ||
| 346 | .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } }, | ||
| 347 | |||
| 348 | .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, | ||
| 349 | .mulh => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000001 } } }, | ||
| 350 | .mulhsu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000001 } } }, | ||
| 351 | .mulhu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000001 } } }, | ||
| 352 | |||
| 353 | .div => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } }, | ||
| 354 | .divu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } }, | ||
| 355 | |||
| 356 | .rem => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } }, | ||
| 357 | .remu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } }, | ||
| 358 | |||
| 359 | .sll => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, | ||
| 360 | .srl => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } }, | ||
| 361 | .sra => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } }, | ||
| 362 | |||
| 363 | |||
| 364 | // OP_IMM | ||
| 365 | |||
| 366 | .addi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 367 | .andi => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 368 | .xori => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b100 } } }, | ||
| 369 | |||
| 370 | .sltiu => .{ .opcode = .OP_IMM, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 371 | |||
| 372 | .slli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = true } } }, | ||
| 373 | .srli => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = true } } }, | ||
| 374 | .srai => .{ .opcode = .OP_IMM, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = true } } }, | ||
| 375 | |||
| 376 | .clz => .{ .opcode = .OP_IMM, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } }, | ||
| 377 | |||
| 378 | // OP_IMM_32 | ||
| 379 | |||
| 380 | .slliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } }, | ||
| 381 | .srliw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } }, | ||
| 382 | .sraiw => .{ .opcode = .OP_IMM_32, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = false } } }, | ||
| 383 | |||
| 384 | .clzw => .{ .opcode = .OP_IMM_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } }, | ||
| 385 | |||
| 386 | // OP_32 | ||
| 387 | |||
| 388 | .addw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, | ||
| 389 | .subw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, | ||
| 390 | .mulw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, | ||
| 391 | |||
| 392 | .divw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } }, | ||
| 393 | .divuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } }, | ||
| 394 | |||
| 395 | .remw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } }, | ||
| 396 | .remuw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } }, | ||
| 397 | |||
| 398 | .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, | ||
| 399 | .srlw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } }, | ||
| 400 | .sraw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } }, | ||
| 401 | |||
| 402 | |||
| 403 | // OP_FP | ||
| 404 | |||
| 405 | .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, | ||
| 406 | .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, | ||
| 407 | |||
| 408 | .fsubs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } }, | ||
| 409 | .fsubd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } }, | ||
| 410 | |||
| 411 | .fmuls => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } }, | ||
| 412 | .fmuld => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } }, | ||
| 413 | |||
| 414 | .fdivs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } }, | ||
| 415 | .fdivd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } }, | ||
| 416 | |||
| 417 | .fmins => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } }, | ||
| 418 | .fmind => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } }, | ||
| 419 | |||
| 420 | .fmaxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } }, | ||
| 421 | .fmaxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } }, | ||
| 422 | |||
| 423 | .fsqrts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } }, | ||
| 424 | .fsqrtd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } }, | ||
| 425 | |||
| 426 | .fles => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } }, | ||
| 427 | .fled => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } }, | ||
| 428 | |||
| 429 | .flts => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } }, | ||
| 430 | .fltd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } }, | ||
| 431 | |||
| 432 | .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, | ||
| 433 | .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, | ||
| 434 | |||
| 435 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, | ||
| 436 | .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, | ||
| 437 | |||
| 438 | .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } }, | ||
| 439 | .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } }, | ||
| 440 | |||
| 441 | |||
| 442 | // LOAD | ||
| 443 | |||
| 444 | .lb => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 445 | .lh => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b001 } } }, | ||
| 446 | .lw => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 447 | .ld => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 448 | .lbu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b100 } } }, | ||
| 449 | .lhu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b101 } } }, | ||
| 450 | .lwu => .{ .opcode = .LOAD, .data = .{ .f = .{ .funct3 = 0b110 } } }, | ||
| 451 | |||
| 452 | |||
| 453 | // STORE | ||
| 454 | |||
| 455 | .sb => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 456 | .sh => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b001 } } }, | ||
| 457 | .sw => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 458 | .sd => .{ .opcode = .STORE, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 459 | |||
| 460 | |||
| 461 | // LOAD_FP | ||
| 462 | |||
| 463 | .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 464 | .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 465 | |||
| 466 | .vle8v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 467 | .vle16v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 468 | .vle32v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 469 | .vle64v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 470 | |||
| 471 | |||
| 472 | // STORE_FP | ||
| 473 | |||
| 474 | .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 475 | .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 476 | |||
| 477 | .vse8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 478 | .vse16v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 479 | .vse32v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 480 | .vse64v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 481 | |||
| 482 | .vsoxei8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .ord, .mew = false, .nf = 0b000 } } }, | ||
| 483 | |||
| 484 | // JALR | ||
| 485 | |||
| 486 | .jalr => .{ .opcode = .JALR, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 487 | |||
| 488 | |||
| 489 | // LUI | ||
| 490 | |||
| 491 | .lui => .{ .opcode = .LUI, .data = .{ .none = {} } }, | ||
| 492 | |||
| 493 | |||
| 494 | // AUIPC | ||
| 495 | |||
| 496 | .auipc => .{ .opcode = .AUIPC, .data = .{ .none = {} } }, | ||
| 497 | |||
| 498 | |||
| 499 | // JAL | ||
| 500 | |||
| 501 | .jal => .{ .opcode = .JAL, .data = .{ .none = {} } }, | ||
| 502 | |||
| 503 | |||
| 504 | // BRANCH | ||
| 505 | |||
| 506 | .beq => .{ .opcode = .BRANCH, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 507 | |||
| 508 | |||
| 509 | // SYSTEM | ||
| 510 | |||
| 511 | .ecall => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 512 | .ebreak => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 513 | |||
| 514 | .csrrs => .{ .opcode = .SYSTEM, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 515 | |||
| 516 | |||
| 517 | // NONE | ||
| 518 | |||
| 519 | .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 520 | |||
| 521 | |||
| 522 | // MISC_MEM | ||
| 523 | |||
| 524 | .fence => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .none } } }, | ||
| 525 | .fencetso => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .tso } } }, | ||
| 526 | |||
| 527 | |||
| 528 | // AMO | ||
| 529 | |||
| 530 | .amoaddw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00000 } } }, | ||
| 531 | .amoswapw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00001 } } }, | ||
| 532 | // LR.W | ||
| 533 | // SC.W | ||
| 534 | .amoxorw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00100 } } }, | ||
| 535 | .amoandw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01100 } } }, | ||
| 536 | .amoorw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01000 } } }, | ||
| 537 | .amominw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10000 } } }, | ||
| 538 | .amomaxw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10100 } } }, | ||
| 539 | .amominuw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11000 } } }, | ||
| 540 | .amomaxuw => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11100 } } }, | ||
| 541 | |||
| 542 | .amoaddd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00000 } } }, | ||
| 543 | .amoswapd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00001 } } }, | ||
| 544 | // LR.D | ||
| 545 | // SC.D | ||
| 546 | .amoxord => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00100 } } }, | ||
| 547 | .amoandd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01100 } } }, | ||
| 548 | .amoord => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01000 } } }, | ||
| 549 | .amomind => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10000 } } }, | ||
| 550 | .amomaxd => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10100 } } }, | ||
| 551 | .amominud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11000 } } }, | ||
| 552 | .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } }, | ||
| 553 | |||
| 554 | // OP_V | ||
| 555 | .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 556 | .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 557 | .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } }, | ||
| 558 | .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } }, | ||
| 559 | .vmulvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100101, .funct3 = .OPIVV } } }, | ||
| 560 | |||
| 561 | .vfaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } }, | ||
| 562 | .vfsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } }, | ||
| 563 | .vfmulvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100100, .funct3 = .OPFVV } } }, | ||
| 564 | |||
| 565 | .vadcvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } }, | ||
| 566 | .vmvvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } }, | ||
| 567 | |||
| 568 | .vslidedownvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b001111, .funct3 = .OPIVX } } }, | ||
| 569 | |||
| 570 | // zig fmt: on | ||
| 571 | }; | ||
| 572 | } | ||
| 573 | }; | ||
| 574 | |||
| 575 | pub const InstEnc = enum { | ||
| 576 | R, | ||
| 577 | R4, | ||
| 578 | I, | ||
| 579 | S, | ||
| 580 | B, | ||
| 581 | U, | ||
| 582 | J, | ||
| 583 | fence, | ||
| 584 | amo, | ||
| 585 | system, | ||
| 586 | |||
| 587 | pub fn fromMnemonic(mnem: Mnemonic) InstEnc { | ||
| 588 | return switch (mnem) { | ||
| 589 | .addi, | ||
| 590 | .jalr, | ||
| 591 | .sltiu, | ||
| 592 | .xori, | ||
| 593 | .andi, | ||
| 594 | |||
| 595 | .slli, | ||
| 596 | .srli, | ||
| 597 | .srai, | ||
| 598 | |||
| 599 | .slliw, | ||
| 600 | .srliw, | ||
| 601 | .sraiw, | ||
| 602 | |||
| 603 | .ld, | ||
| 604 | .lw, | ||
| 605 | .lwu, | ||
| 606 | .lh, | ||
| 607 | .lhu, | ||
| 608 | .lb, | ||
| 609 | .lbu, | ||
| 610 | |||
| 611 | .flw, | ||
| 612 | .fld, | ||
| 613 | |||
| 614 | .csrrs, | ||
| 615 | .vsetivli, | ||
| 616 | .vsetvli, | ||
| 617 | => .I, | ||
| 618 | |||
| 619 | .lui, | ||
| 620 | .auipc, | ||
| 621 | => .U, | ||
| 622 | |||
| 623 | .sd, | ||
| 624 | .sw, | ||
| 625 | .sh, | ||
| 626 | .sb, | ||
| 627 | |||
| 628 | .fsd, | ||
| 629 | .fsw, | ||
| 630 | => .S, | ||
| 631 | |||
| 632 | .jal, | ||
| 633 | => .J, | ||
| 634 | |||
| 635 | .beq, | ||
| 636 | => .B, | ||
| 637 | |||
| 638 | .slt, | ||
| 639 | .sltu, | ||
| 640 | |||
| 641 | .sll, | ||
| 642 | .srl, | ||
| 643 | .sra, | ||
| 644 | |||
| 645 | .sllw, | ||
| 646 | .srlw, | ||
| 647 | .sraw, | ||
| 648 | |||
| 649 | .div, | ||
| 650 | .divu, | ||
| 651 | .divw, | ||
| 652 | .divuw, | ||
| 653 | |||
| 654 | .rem, | ||
| 655 | .remu, | ||
| 656 | .remw, | ||
| 657 | .remuw, | ||
| 658 | |||
| 659 | .xor, | ||
| 660 | .@"and", | ||
| 661 | .@"or", | ||
| 662 | |||
| 663 | .add, | ||
| 664 | .addw, | ||
| 665 | |||
| 666 | .sub, | ||
| 667 | .subw, | ||
| 668 | |||
| 669 | .mul, | ||
| 670 | .mulw, | ||
| 671 | .mulh, | ||
| 672 | .mulhu, | ||
| 673 | .mulhsu, | ||
| 674 | |||
| 675 | .fadds, | ||
| 676 | .faddd, | ||
| 677 | |||
| 678 | .fsubs, | ||
| 679 | .fsubd, | ||
| 680 | |||
| 681 | .fmuls, | ||
| 682 | .fmuld, | ||
| 683 | |||
| 684 | .fdivs, | ||
| 685 | .fdivd, | ||
| 686 | |||
| 687 | .fmins, | ||
| 688 | .fmind, | ||
| 689 | |||
| 690 | .fmaxs, | ||
| 691 | .fmaxd, | ||
| 692 | |||
| 693 | .fsqrts, | ||
| 694 | .fsqrtd, | ||
| 695 | |||
| 696 | .fles, | ||
| 697 | .fled, | ||
| 698 | |||
| 699 | .flts, | ||
| 700 | .fltd, | ||
| 701 | |||
| 702 | .feqs, | ||
| 703 | .feqd, | ||
| 704 | |||
| 705 | .fsgnjns, | ||
| 706 | .fsgnjnd, | ||
| 707 | |||
| 708 | .fsgnjxs, | ||
| 709 | .fsgnjxd, | ||
| 710 | |||
| 711 | .vle8v, | ||
| 712 | .vle16v, | ||
| 713 | .vle32v, | ||
| 714 | .vle64v, | ||
| 715 | |||
| 716 | .vse8v, | ||
| 717 | .vse16v, | ||
| 718 | .vse32v, | ||
| 719 | .vse64v, | ||
| 720 | |||
| 721 | .vsoxei8v, | ||
| 722 | |||
| 723 | .vaddvv, | ||
| 724 | .vsubvv, | ||
| 725 | .vmulvv, | ||
| 726 | .vfaddvv, | ||
| 727 | .vfsubvv, | ||
| 728 | .vfmulvv, | ||
| 729 | .vadcvv, | ||
| 730 | .vmvvx, | ||
| 731 | .vslidedownvx, | ||
| 732 | |||
| 733 | .clz, | ||
| 734 | .clzw, | ||
| 735 | => .R, | ||
| 736 | |||
| 737 | .ecall, | ||
| 738 | .ebreak, | ||
| 739 | .unimp, | ||
| 740 | => .system, | ||
| 741 | |||
| 742 | .fence, | ||
| 743 | .fencetso, | ||
| 744 | => .fence, | ||
| 745 | |||
| 746 | .amoswapw, | ||
| 747 | .amoaddw, | ||
| 748 | .amoandw, | ||
| 749 | .amoorw, | ||
| 750 | .amoxorw, | ||
| 751 | .amomaxw, | ||
| 752 | .amominw, | ||
| 753 | .amomaxuw, | ||
| 754 | .amominuw, | ||
| 755 | |||
| 756 | .amoswapd, | ||
| 757 | .amoaddd, | ||
| 758 | .amoandd, | ||
| 759 | .amoord, | ||
| 760 | .amoxord, | ||
| 761 | .amomaxd, | ||
| 762 | .amomind, | ||
| 763 | .amomaxud, | ||
| 764 | .amominud, | ||
| 765 | => .amo, | ||
| 766 | }; | ||
| 767 | } | ||
| 768 | |||
| 769 | pub fn opsList(enc: InstEnc) [5]std.meta.FieldEnum(Operand) { | ||
| 770 | return switch (enc) { | ||
| 771 | // zig fmt: off | ||
| 772 | .R => .{ .reg, .reg, .reg, .none, .none, }, | ||
| 773 | .R4 => .{ .reg, .reg, .reg, .reg, .none, }, | ||
| 774 | .I => .{ .reg, .reg, .imm, .none, .none, }, | ||
| 775 | .S => .{ .reg, .reg, .imm, .none, .none, }, | ||
| 776 | .B => .{ .reg, .reg, .imm, .none, .none, }, | ||
| 777 | .U => .{ .reg, .imm, .none, .none, .none, }, | ||
| 778 | .J => .{ .reg, .imm, .none, .none, .none, }, | ||
| 779 | .system => .{ .none, .none, .none, .none, .none, }, | ||
| 780 | .fence => .{ .barrier, .barrier, .none, .none, .none, }, | ||
| 781 | .amo => .{ .reg, .reg, .reg, .barrier, .barrier }, | ||
| 782 | // zig fmt: on | ||
| 783 | }; | ||
| 784 | } | ||
| 785 | }; | ||
| 786 | |||
| 787 | pub const Data = union(InstEnc) { | ||
| 788 | R: packed struct { | ||
| 789 | opcode: u7, | ||
| 790 | rd: u5, | ||
| 791 | funct3: u3, | ||
| 792 | rs1: u5, | ||
| 793 | rs2: u5, | ||
| 794 | funct7: u7, | ||
| 795 | }, | ||
| 796 | R4: packed struct { | ||
| 797 | opcode: u7, | ||
| 798 | rd: u5, | ||
| 799 | funct3: u3, | ||
| 800 | rs1: u5, | ||
| 801 | rs2: u5, | ||
| 802 | funct2: u2, | ||
| 803 | rs3: u5, | ||
| 804 | }, | ||
| 805 | I: packed struct { | ||
| 806 | opcode: u7, | ||
| 807 | rd: u5, | ||
| 808 | funct3: u3, | ||
| 809 | rs1: u5, | ||
| 810 | imm0_11: u12, | ||
| 811 | }, | ||
| 812 | S: packed struct { | ||
| 813 | opcode: u7, | ||
| 814 | imm0_4: u5, | ||
| 815 | funct3: u3, | ||
| 816 | rs1: u5, | ||
| 817 | rs2: u5, | ||
| 818 | imm5_11: u7, | ||
| 819 | }, | ||
| 820 | B: packed struct { | ||
| 821 | opcode: u7, | ||
| 822 | imm11: u1, | ||
| 823 | imm1_4: u4, | ||
| 824 | funct3: u3, | ||
| 825 | rs1: u5, | ||
| 826 | rs2: u5, | ||
| 827 | imm5_10: u6, | ||
| 828 | imm12: u1, | ||
| 829 | }, | ||
| 830 | U: packed struct { | ||
| 831 | opcode: u7, | ||
| 832 | rd: u5, | ||
| 833 | imm12_31: u20, | ||
| 834 | }, | ||
| 835 | J: packed struct { | ||
| 836 | opcode: u7, | ||
| 837 | rd: u5, | ||
| 838 | imm12_19: u8, | ||
| 839 | imm11: u1, | ||
| 840 | imm1_10: u10, | ||
| 841 | imm20: u1, | ||
| 842 | }, | ||
| 843 | fence: packed struct { | ||
| 844 | opcode: u7, | ||
| 845 | rd: u5 = 0, | ||
| 846 | funct3: u3, | ||
| 847 | rs1: u5 = 0, | ||
| 848 | succ: u4, | ||
| 849 | pred: u4, | ||
| 850 | fm: u4, | ||
| 851 | }, | ||
| 852 | amo: packed struct { | ||
| 853 | opcode: u7, | ||
| 854 | rd: u5, | ||
| 855 | funct3: u3, | ||
| 856 | rs1: u5, | ||
| 857 | rs2: u5, | ||
| 858 | rl: bool, | ||
| 859 | aq: bool, | ||
| 860 | funct5: u5, | ||
| 861 | }, | ||
| 862 | system: u32, | ||
| 863 | |||
| 864 | comptime { | ||
| 865 | for (std.meta.fields(Data)) |field| { | ||
| 866 | assert(@bitSizeOf(field.type) == 32); | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | pub fn toU32(self: Data) u32 { | ||
| 871 | return switch (self) { | ||
| 872 | .fence => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.rd)) << 7) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.succ)) << 20) + (@as(u32, @intCast(v.pred)) << 24) + (@as(u32, @intCast(v.fm)) << 28), | ||
| 873 | inline else => |v| @bitCast(v), | ||
| 874 | .system => unreachable, | ||
| 875 | }; | ||
| 876 | } | ||
| 877 | |||
| 878 | pub fn construct(mnem: Mnemonic, ops: []const Operand) !Data { | ||
| 879 | const inst_enc = InstEnc.fromMnemonic(mnem); | ||
| 880 | const enc = mnem.encoding(); | ||
| 881 | |||
| 882 | // special mnemonics | ||
| 883 | switch (mnem) { | ||
| 884 | .ecall, | ||
| 885 | .ebreak, | ||
| 886 | .unimp, | ||
| 887 | => { | ||
| 888 | assert(ops.len == 0); | ||
| 889 | return .{ | ||
| 890 | .I = .{ | ||
| 891 | .rd = Register.zero.encodeId(), | ||
| 892 | .rs1 = Register.zero.encodeId(), | ||
| 893 | .imm0_11 = switch (mnem) { | ||
| 894 | .ecall => 0x000, | ||
| 895 | .ebreak => 0x001, | ||
| 896 | .unimp => 0x000, | ||
| 897 | else => unreachable, | ||
| 898 | }, | ||
| 899 | |||
| 900 | .opcode = @intFromEnum(enc.opcode), | ||
| 901 | .funct3 = enc.data.f.funct3, | ||
| 902 | }, | ||
| 903 | }; | ||
| 904 | }, | ||
| 905 | .csrrs => { | ||
| 906 | assert(ops.len == 3); | ||
| 907 | |||
| 908 | const csr = ops[0].csr; | ||
| 909 | const rs1 = ops[1].reg; | ||
| 910 | const rd = ops[2].reg; | ||
| 911 | |||
| 912 | return .{ | ||
| 913 | .I = .{ | ||
| 914 | .rd = rd.encodeId(), | ||
| 915 | .rs1 = rs1.encodeId(), | ||
| 916 | |||
| 917 | .imm0_11 = @intFromEnum(csr), | ||
| 918 | |||
| 919 | .opcode = @intFromEnum(enc.opcode), | ||
| 920 | .funct3 = enc.data.f.funct3, | ||
| 921 | }, | ||
| 922 | }; | ||
| 923 | }, | ||
| 924 | else => {}, | ||
| 925 | } | ||
| 926 | |||
| 927 | switch (inst_enc) { | ||
| 928 | .R => { | ||
| 929 | assert(ops.len == 3); | ||
| 930 | return .{ | ||
| 931 | .R = switch (enc.data) { | ||
| 932 | .ff => |ff| .{ | ||
| 933 | .rd = ops[0].reg.encodeId(), | ||
| 934 | .rs1 = ops[1].reg.encodeId(), | ||
| 935 | .rs2 = ops[2].reg.encodeId(), | ||
| 936 | |||
| 937 | .opcode = @intFromEnum(enc.opcode), | ||
| 938 | .funct3 = ff.funct3, | ||
| 939 | .funct7 = ff.funct7, | ||
| 940 | }, | ||
| 941 | .fmt => |fmt| .{ | ||
| 942 | .rd = ops[0].reg.encodeId(), | ||
| 943 | .rs1 = ops[1].reg.encodeId(), | ||
| 944 | .rs2 = ops[2].reg.encodeId(), | ||
| 945 | |||
| 946 | .opcode = @intFromEnum(enc.opcode), | ||
| 947 | .funct3 = fmt.rm, | ||
| 948 | .funct7 = (@as(u7, fmt.funct5) << 2) | @intFromEnum(fmt.fmt), | ||
| 949 | }, | ||
| 950 | .vecls => |vec| .{ | ||
| 951 | .rd = ops[0].reg.encodeId(), | ||
| 952 | .rs1 = ops[1].reg.encodeId(), | ||
| 953 | |||
| 954 | .rs2 = @intFromEnum(vec.umop), | ||
| 955 | |||
| 956 | .opcode = @intFromEnum(enc.opcode), | ||
| 957 | .funct3 = @intFromEnum(vec.width), | ||
| 958 | .funct7 = (@as(u7, vec.nf) << 4) | (@as(u7, @intFromBool(vec.mew)) << 3) | (@as(u7, @intFromEnum(vec.mop)) << 1) | @intFromBool(vec.vm), | ||
| 959 | }, | ||
| 960 | .vecmath => |vec| .{ | ||
| 961 | .rd = ops[0].reg.encodeId(), | ||
| 962 | .rs1 = ops[1].reg.encodeId(), | ||
| 963 | .rs2 = ops[2].reg.encodeId(), | ||
| 964 | |||
| 965 | .opcode = @intFromEnum(enc.opcode), | ||
| 966 | .funct3 = @intFromEnum(vec.funct3), | ||
| 967 | .funct7 = (@as(u7, vec.funct6) << 1) | @intFromBool(vec.vm), | ||
| 968 | }, | ||
| 969 | else => unreachable, | ||
| 970 | }, | ||
| 971 | }; | ||
| 972 | }, | ||
| 973 | .S => { | ||
| 974 | assert(ops.len == 3); | ||
| 975 | const umm = ops[2].imm.asBits(u12); | ||
| 976 | |||
| 977 | return .{ | ||
| 978 | .S = .{ | ||
| 979 | .imm0_4 = @truncate(umm), | ||
| 980 | .rs1 = ops[0].reg.encodeId(), | ||
| 981 | .rs2 = ops[1].reg.encodeId(), | ||
| 982 | .imm5_11 = @truncate(umm >> 5), | ||
| 983 | |||
| 984 | .opcode = @intFromEnum(enc.opcode), | ||
| 985 | .funct3 = enc.data.f.funct3, | ||
| 986 | }, | ||
| 987 | }; | ||
| 988 | }, | ||
| 989 | .I => { | ||
| 990 | assert(ops.len == 3); | ||
| 991 | return .{ | ||
| 992 | .I = switch (enc.data) { | ||
| 993 | .f => |f| .{ | ||
| 994 | .rd = ops[0].reg.encodeId(), | ||
| 995 | .rs1 = ops[1].reg.encodeId(), | ||
| 996 | .imm0_11 = ops[2].imm.asBits(u12), | ||
| 997 | |||
| 998 | .opcode = @intFromEnum(enc.opcode), | ||
| 999 | .funct3 = f.funct3, | ||
| 1000 | }, | ||
| 1001 | .sh => |sh| .{ | ||
| 1002 | .rd = ops[0].reg.encodeId(), | ||
| 1003 | .rs1 = ops[1].reg.encodeId(), | ||
| 1004 | .imm0_11 = (@as(u12, sh.typ) << 6) | | ||
| 1005 | if (sh.has_5) ops[2].imm.asBits(u6) else (@as(u6, 0) | ops[2].imm.asBits(u5)), | ||
| 1006 | |||
| 1007 | .opcode = @intFromEnum(enc.opcode), | ||
| 1008 | .funct3 = sh.funct3, | ||
| 1009 | }, | ||
| 1010 | else => unreachable, | ||
| 1011 | }, | ||
| 1012 | }; | ||
| 1013 | }, | ||
| 1014 | .U => { | ||
| 1015 | assert(ops.len == 2); | ||
| 1016 | return .{ | ||
| 1017 | .U = .{ | ||
| 1018 | .rd = ops[0].reg.encodeId(), | ||
| 1019 | .imm12_31 = ops[1].imm.asBits(u20), | ||
| 1020 | |||
| 1021 | .opcode = @intFromEnum(enc.opcode), | ||
| 1022 | }, | ||
| 1023 | }; | ||
| 1024 | }, | ||
| 1025 | .J => { | ||
| 1026 | assert(ops.len == 2); | ||
| 1027 | |||
| 1028 | const umm = ops[1].imm.asBits(u21); | ||
| 1029 | assert(umm % 4 == 0); // misaligned jump target | ||
| 1030 | |||
| 1031 | return .{ | ||
| 1032 | .J = .{ | ||
| 1033 | .rd = ops[0].reg.encodeId(), | ||
| 1034 | .imm1_10 = @truncate(umm >> 1), | ||
| 1035 | .imm11 = @truncate(umm >> 11), | ||
| 1036 | .imm12_19 = @truncate(umm >> 12), | ||
| 1037 | .imm20 = @truncate(umm >> 20), | ||
| 1038 | |||
| 1039 | .opcode = @intFromEnum(enc.opcode), | ||
| 1040 | }, | ||
| 1041 | }; | ||
| 1042 | }, | ||
| 1043 | .B => { | ||
| 1044 | assert(ops.len == 3); | ||
| 1045 | |||
| 1046 | const umm = ops[2].imm.asBits(u13); | ||
| 1047 | assert(umm % 4 == 0); // misaligned branch target | ||
| 1048 | |||
| 1049 | return .{ | ||
| 1050 | .B = .{ | ||
| 1051 | .rs1 = ops[0].reg.encodeId(), | ||
| 1052 | .rs2 = ops[1].reg.encodeId(), | ||
| 1053 | .imm1_4 = @truncate(umm >> 1), | ||
| 1054 | .imm5_10 = @truncate(umm >> 5), | ||
| 1055 | .imm11 = @truncate(umm >> 11), | ||
| 1056 | .imm12 = @truncate(umm >> 12), | ||
| 1057 | |||
| 1058 | .opcode = @intFromEnum(enc.opcode), | ||
| 1059 | .funct3 = enc.data.f.funct3, | ||
| 1060 | }, | ||
| 1061 | }; | ||
| 1062 | }, | ||
| 1063 | .fence => { | ||
| 1064 | assert(ops.len == 2); | ||
| 1065 | |||
| 1066 | const succ = ops[0].barrier; | ||
| 1067 | const pred = ops[1].barrier; | ||
| 1068 | |||
| 1069 | return .{ | ||
| 1070 | .fence = .{ | ||
| 1071 | .succ = @intFromEnum(succ), | ||
| 1072 | .pred = @intFromEnum(pred), | ||
| 1073 | |||
| 1074 | .opcode = @intFromEnum(enc.opcode), | ||
| 1075 | .funct3 = enc.data.fence.funct3, | ||
| 1076 | .fm = @intFromEnum(enc.data.fence.fm), | ||
| 1077 | }, | ||
| 1078 | }; | ||
| 1079 | }, | ||
| 1080 | .amo => { | ||
| 1081 | assert(ops.len == 5); | ||
| 1082 | |||
| 1083 | const rd = ops[0].reg; | ||
| 1084 | const rs1 = ops[1].reg; | ||
| 1085 | const rs2 = ops[2].reg; | ||
| 1086 | const rl = ops[3].barrier; | ||
| 1087 | const aq = ops[4].barrier; | ||
| 1088 | |||
| 1089 | return .{ | ||
| 1090 | .amo = .{ | ||
| 1091 | .rd = rd.encodeId(), | ||
| 1092 | .rs1 = rs1.encodeId(), | ||
| 1093 | .rs2 = rs2.encodeId(), | ||
| 1094 | |||
| 1095 | // TODO: https://github.com/ziglang/zig/issues/20113 | ||
| 1096 | .rl = if (rl == .rl) true else false, | ||
| 1097 | .aq = if (aq == .aq) true else false, | ||
| 1098 | |||
| 1099 | .opcode = @intFromEnum(enc.opcode), | ||
| 1100 | .funct3 = @intFromEnum(enc.data.amo.width), | ||
| 1101 | .funct5 = enc.data.amo.funct5, | ||
| 1102 | }, | ||
| 1103 | }; | ||
| 1104 | }, | ||
| 1105 | else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}), | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | }; | ||
| 1109 | |||
| 1110 | pub fn findByMnemonic(mnem: Mnemonic, ops: []const Operand) !?Encoding { | ||
| 1111 | if (!verifyOps(mnem, ops)) return null; | ||
| 1112 | |||
| 1113 | return .{ | ||
| 1114 | .mnemonic = mnem, | ||
| 1115 | .data = try Data.construct(mnem, ops), | ||
| 1116 | }; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | fn verifyOps(mnem: Mnemonic, ops: []const Operand) bool { | ||
| 1120 | const inst_enc = InstEnc.fromMnemonic(mnem); | ||
| 1121 | const list = std.mem.sliceTo(&inst_enc.opsList(), .none); | ||
| 1122 | for (list, ops) |l, o| if (l != std.meta.activeTag(o)) return false; | ||
| 1123 | return true; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | const std = @import("std"); | ||
| 1127 | const assert = std.debug.assert; | ||
| 1128 | const log = std.log.scoped(.encoding); | ||
| 1129 | |||
| 1130 | const Encoding = @This(); | ||
| 1131 | const bits = @import("bits.zig"); | ||
| 1132 | const Register = bits.Register; | ||
| 1133 | const encoder = @import("encoder.zig"); | ||
| 1134 | const Instruction = encoder.Instruction; | ||
| 1135 | const Operand = Instruction.Operand; | ||
| 1136 | const OperandEnum = std.meta.FieldEnum(Operand); | ||
src/arch/riscv64/Lower.zig+447-472| ... | @@ -61,451 +61,427 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { | ... | @@ -61,451 +61,427 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { |
| 61 | log.debug("lowerMir {}", .{inst}); | 61 | log.debug("lowerMir {}", .{inst}); |
| 62 | switch (inst.tag) { | 62 | switch (inst.tag) { |
| 63 | else => try lower.generic(inst), | 63 | else => try lower.generic(inst), |
| 64 | .pseudo => switch (inst.ops) { | 64 | .pseudo_dbg_line_column, |
| 65 | .pseudo_dbg_line_column, | 65 | .pseudo_dbg_epilogue_begin, |
| 66 | .pseudo_dbg_epilogue_begin, | 66 | .pseudo_dbg_prologue_end, |
| 67 | .pseudo_dbg_prologue_end, | 67 | .pseudo_dead, |
| 68 | .pseudo_dead, | 68 | => {}, |
| 69 | => {}, | 69 | |
| 70 | 70 | .pseudo_load_rm, .pseudo_store_rm => { | |
| 71 | .pseudo_load_rm, .pseudo_store_rm => { | 71 | const rm = inst.data.rm; |
| 72 | const rm = inst.data.rm; | 72 | |
| 73 | 73 | const frame_loc: Mir.FrameLoc = if (options.allow_frame_locs) | |
| 74 | const frame_loc: Mir.FrameLoc = if (options.allow_frame_locs) | 74 | rm.m.toFrameLoc(lower.mir) |
| 75 | rm.m.toFrameLoc(lower.mir) | 75 | else |
| 76 | else | 76 | .{ .base = .s0, .disp = 0 }; |
| 77 | .{ .base = .s0, .disp = 0 }; | 77 | |
| 78 | 78 | switch (inst.tag) { | |
| 79 | switch (inst.ops) { | 79 | .pseudo_load_rm => { |
| 80 | .pseudo_load_rm => { | 80 | const dest_reg = rm.r; |
| 81 | const dest_reg = rm.r; | 81 | const dest_reg_class = dest_reg.class(); |
| 82 | const dest_reg_class = dest_reg.class(); | 82 | |
| 83 | 83 | const src_size = rm.m.mod.size; | |
| 84 | const src_size = rm.m.mod.size; | 84 | const unsigned = rm.m.mod.unsigned; |
| 85 | const unsigned = rm.m.mod.unsigned; | 85 | |
| 86 | 86 | const mnem: Mnemonic = switch (dest_reg_class) { | |
| 87 | const tag: Encoding.Mnemonic = switch (dest_reg_class) { | 87 | .int => switch (src_size) { |
| 88 | .int => switch (src_size) { | 88 | .byte => if (unsigned) .lbu else .lb, |
| 89 | .byte => if (unsigned) .lbu else .lb, | 89 | .hword => if (unsigned) .lhu else .lh, |
| 90 | .hword => if (unsigned) .lhu else .lh, | 90 | .word => if (unsigned) .lwu else .lw, |
| 91 | .word => if (unsigned) .lwu else .lw, | 91 | .dword => .ld, |
| 92 | .dword => .ld, | ||
| 93 | }, | ||
| 94 | .float => switch (src_size) { | ||
| 95 | .byte => unreachable, // Zig does not support 8-bit floats | ||
| 96 | .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}), | ||
| 97 | .word => .flw, | ||
| 98 | .dword => .fld, | ||
| 99 | }, | ||
| 100 | .vector => switch (src_size) { | ||
| 101 | .byte => .vle8v, | ||
| 102 | .hword => .vle32v, | ||
| 103 | .word => .vle32v, | ||
| 104 | .dword => .vle64v, | ||
| 105 | }, | ||
| 106 | }; | ||
| 107 | |||
| 108 | switch (dest_reg_class) { | ||
| 109 | .int, .float => { | ||
| 110 | try lower.emit(tag, &.{ | ||
| 111 | .{ .reg = rm.r }, | ||
| 112 | .{ .reg = frame_loc.base }, | ||
| 113 | .{ .imm = Immediate.s(frame_loc.disp) }, | ||
| 114 | }); | ||
| 115 | }, | ||
| 116 | .vector => { | ||
| 117 | assert(frame_loc.disp == 0); | ||
| 118 | try lower.emit(tag, &.{ | ||
| 119 | .{ .reg = rm.r }, | ||
| 120 | .{ .reg = frame_loc.base }, | ||
| 121 | .{ .reg = .zero }, | ||
| 122 | }); | ||
| 123 | }, | ||
| 124 | } | ||
| 125 | }, | ||
| 126 | .pseudo_store_rm => { | ||
| 127 | const src_reg = rm.r; | ||
| 128 | const src_reg_class = src_reg.class(); | ||
| 129 | |||
| 130 | const dest_size = rm.m.mod.size; | ||
| 131 | |||
| 132 | const tag: Encoding.Mnemonic = switch (src_reg_class) { | ||
| 133 | .int => switch (dest_size) { | ||
| 134 | .byte => .sb, | ||
| 135 | .hword => .sh, | ||
| 136 | .word => .sw, | ||
| 137 | .dword => .sd, | ||
| 138 | }, | ||
| 139 | .float => switch (dest_size) { | ||
| 140 | .byte => unreachable, // Zig does not support 8-bit floats | ||
| 141 | .hword => return lower.fail("TODO: lowerMir pseudo_store_rm support 16-bit floats", .{}), | ||
| 142 | .word => .fsw, | ||
| 143 | .dword => .fsd, | ||
| 144 | }, | ||
| 145 | .vector => switch (dest_size) { | ||
| 146 | .byte => .vse8v, | ||
| 147 | .hword => .vse16v, | ||
| 148 | .word => .vse32v, | ||
| 149 | .dword => .vse64v, | ||
| 150 | }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | switch (src_reg_class) { | ||
| 154 | .int, .float => { | ||
| 155 | try lower.emit(tag, &.{ | ||
| 156 | .{ .reg = frame_loc.base }, | ||
| 157 | .{ .reg = rm.r }, | ||
| 158 | .{ .imm = Immediate.s(frame_loc.disp) }, | ||
| 159 | }); | ||
| 160 | }, | ||
| 161 | .vector => { | ||
| 162 | assert(frame_loc.disp == 0); | ||
| 163 | try lower.emit(tag, &.{ | ||
| 164 | .{ .reg = rm.r }, | ||
| 165 | .{ .reg = frame_loc.base }, | ||
| 166 | .{ .reg = .zero }, | ||
| 167 | }); | ||
| 168 | }, | ||
| 169 | } | ||
| 170 | }, | ||
| 171 | else => unreachable, | ||
| 172 | } | ||
| 173 | }, | ||
| 174 | |||
| 175 | .pseudo_mv => { | ||
| 176 | const rr = inst.data.rr; | ||
| 177 | |||
| 178 | const dst_class = rr.rd.class(); | ||
| 179 | const src_class = rr.rs.class(); | ||
| 180 | |||
| 181 | switch (src_class) { | ||
| 182 | .float => switch (dst_class) { | ||
| 183 | .float => { | ||
| 184 | try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{ | ||
| 185 | .{ .reg = rr.rd }, | ||
| 186 | .{ .reg = rr.rs }, | ||
| 187 | .{ .reg = rr.rs }, | ||
| 188 | }); | ||
| 189 | }, | 92 | }, |
| 190 | .int, .vector => return lower.fail("TODO: lowerMir pseudo_mv float -> {s}", .{@tagName(dst_class)}), | 93 | .float => switch (src_size) { |
| 191 | }, | 94 | .byte => unreachable, // Zig does not support 8-bit floats |
| 192 | .int => switch (dst_class) { | 95 | .hword => return lower.fail("TODO: lowerMir pseudo_load_rm support 16-bit floats", .{}), |
| 193 | .int => { | 96 | .word => .flw, |
| 194 | try lower.emit(.addi, &.{ | 97 | .dword => .fld, |
| 195 | .{ .reg = rr.rd }, | ||
| 196 | .{ .reg = rr.rs }, | ||
| 197 | .{ .imm = Immediate.s(0) }, | ||
| 198 | }); | ||
| 199 | }, | 98 | }, |
| 200 | .vector => { | 99 | .vector => switch (src_size) { |
| 201 | try lower.emit(.vmvvx, &.{ | 100 | .byte => .vle8v, |
| 202 | .{ .reg = rr.rd }, | 101 | .hword => .vle32v, |
| 203 | .{ .reg = rr.rs }, | 102 | .word => .vle32v, |
| 204 | .{ .reg = .x0 }, | 103 | .dword => .vle64v, |
| 104 | }, | ||
| 105 | }; | ||
| 106 | |||
| 107 | switch (dest_reg_class) { | ||
| 108 | .int, .float => { | ||
| 109 | try lower.emit(mnem, &.{ | ||
| 110 | .{ .reg = rm.r }, | ||
| 111 | .{ .reg = frame_loc.base }, | ||
| 112 | .{ .imm = Immediate.s(frame_loc.disp) }, | ||
| 205 | }); | 113 | }); |
| 206 | }, | 114 | }, |
| 207 | .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}), | 115 | .vector => { |
| 208 | }, | 116 | assert(frame_loc.disp == 0); |
| 209 | .vector => switch (dst_class) { | 117 | try lower.emit(mnem, &.{ |
| 210 | .int => { | 118 | .{ .reg = rm.r }, |
| 211 | try lower.emit(.vadcvv, &.{ | 119 | .{ .reg = frame_loc.base }, |
| 212 | .{ .reg = rr.rd }, | ||
| 213 | .{ .reg = .zero }, | 120 | .{ .reg = .zero }, |
| 214 | .{ .reg = rr.rs }, | ||
| 215 | }); | 121 | }); |
| 216 | }, | 122 | }, |
| 217 | .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}), | 123 | } |
| 218 | }, | 124 | }, |
| 219 | } | 125 | .pseudo_store_rm => { |
| 220 | }, | 126 | const src_reg = rm.r; |
| 221 | 127 | const src_reg_class = src_reg.class(); | |
| 222 | .pseudo_j => { | 128 | |
| 223 | try lower.emit(.jal, &.{ | 129 | const dest_size = rm.m.mod.size; |
| 224 | .{ .reg = .zero }, | 130 | |
| 225 | .{ .imm = lower.reloc(.{ .inst = inst.data.inst }) }, | 131 | const mnem: Mnemonic = switch (src_reg_class) { |
| 226 | }); | 132 | .int => switch (dest_size) { |
| 227 | }, | 133 | .byte => .sb, |
| 228 | 134 | .hword => .sh, | |
| 229 | .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list), | 135 | .word => .sw, |
| 230 | .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list), | 136 | .dword => .sd, |
| 231 | |||
| 232 | .pseudo_load_symbol => { | ||
| 233 | const payload = inst.data.payload; | ||
| 234 | const data = lower.mir.extraData(Mir.LoadSymbolPayload, payload).data; | ||
| 235 | const dst_reg: bits.Register = @enumFromInt(data.register); | ||
| 236 | assert(dst_reg.class() == .int); | ||
| 237 | |||
| 238 | try lower.emit(.lui, &.{ | ||
| 239 | .{ .reg = dst_reg }, | ||
| 240 | .{ .imm = lower.reloc(.{ | ||
| 241 | .load_symbol_reloc = .{ | ||
| 242 | .atom_index = data.atom_index, | ||
| 243 | .sym_index = data.sym_index, | ||
| 244 | }, | ||
| 245 | }) }, | ||
| 246 | }); | ||
| 247 | |||
| 248 | // the above reloc implies this one | ||
| 249 | try lower.emit(.addi, &.{ | ||
| 250 | .{ .reg = dst_reg }, | ||
| 251 | .{ .reg = dst_reg }, | ||
| 252 | .{ .imm = Immediate.s(0) }, | ||
| 253 | }); | ||
| 254 | }, | ||
| 255 | |||
| 256 | .pseudo_lea_rm => { | ||
| 257 | const rm = inst.data.rm; | ||
| 258 | assert(rm.r.class() == .int); | ||
| 259 | |||
| 260 | const frame: Mir.FrameLoc = if (options.allow_frame_locs) | ||
| 261 | rm.m.toFrameLoc(lower.mir) | ||
| 262 | else | ||
| 263 | .{ .base = .s0, .disp = 0 }; | ||
| 264 | |||
| 265 | try lower.emit(.addi, &.{ | ||
| 266 | .{ .reg = rm.r }, | ||
| 267 | .{ .reg = frame.base }, | ||
| 268 | .{ .imm = Immediate.s(frame.disp) }, | ||
| 269 | }); | ||
| 270 | }, | ||
| 271 | |||
| 272 | .pseudo_fabs => { | ||
| 273 | const fabs = inst.data.fabs; | ||
| 274 | assert(fabs.rs.class() == .float and fabs.rd.class() == .float); | ||
| 275 | |||
| 276 | const mnem: Encoding.Mnemonic = switch (fabs.bits) { | ||
| 277 | 16 => return lower.fail("TODO: airAbs Float 16", .{}), | ||
| 278 | 32 => .fsgnjxs, | ||
| 279 | 64 => .fsgnjxd, | ||
| 280 | 80 => return lower.fail("TODO: airAbs Float 80", .{}), | ||
| 281 | 128 => return lower.fail("TODO: airAbs Float 128", .{}), | ||
| 282 | else => unreachable, | ||
| 283 | }; | ||
| 284 | |||
| 285 | try lower.emit(mnem, &.{ | ||
| 286 | .{ .reg = fabs.rs }, | ||
| 287 | .{ .reg = fabs.rd }, | ||
| 288 | .{ .reg = fabs.rd }, | ||
| 289 | }); | ||
| 290 | }, | ||
| 291 | |||
| 292 | .pseudo_compare => { | ||
| 293 | const compare = inst.data.compare; | ||
| 294 | const op = compare.op; | ||
| 295 | |||
| 296 | const rd = compare.rd; | ||
| 297 | const rs1 = compare.rs1; | ||
| 298 | const rs2 = compare.rs2; | ||
| 299 | |||
| 300 | const class = rs1.class(); | ||
| 301 | const ty = compare.ty; | ||
| 302 | const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(pt)) catch { | ||
| 303 | return lower.fail("pseudo_compare size {}", .{ty.bitSize(pt)}); | ||
| 304 | }; | ||
| 305 | |||
| 306 | const is_unsigned = ty.isUnsignedInt(pt.zcu); | ||
| 307 | const less_than: Encoding.Mnemonic = if (is_unsigned) .sltu else .slt; | ||
| 308 | |||
| 309 | switch (class) { | ||
| 310 | .int => switch (op) { | ||
| 311 | .eq => { | ||
| 312 | try lower.emit(.xor, &.{ | ||
| 313 | .{ .reg = rd }, | ||
| 314 | .{ .reg = rs1 }, | ||
| 315 | .{ .reg = rs2 }, | ||
| 316 | }); | ||
| 317 | |||
| 318 | try lower.emit(.sltiu, &.{ | ||
| 319 | .{ .reg = rd }, | ||
| 320 | .{ .reg = rd }, | ||
| 321 | .{ .imm = Immediate.s(1) }, | ||
| 322 | }); | ||
| 323 | }, | 137 | }, |
| 324 | .neq => { | 138 | .float => switch (dest_size) { |
| 325 | try lower.emit(.xor, &.{ | 139 | .byte => unreachable, // Zig does not support 8-bit floats |
| 326 | .{ .reg = rd }, | 140 | .hword => return lower.fail("TODO: lowerMir pseudo_store_rm support 16-bit floats", .{}), |
| 327 | .{ .reg = rs1 }, | 141 | .word => .fsw, |
| 328 | .{ .reg = rs2 }, | 142 | .dword => .fsd, |
| 329 | }); | ||
| 330 | |||
| 331 | try lower.emit(.sltu, &.{ | ||
| 332 | .{ .reg = rd }, | ||
| 333 | .{ .reg = .zero }, | ||
| 334 | .{ .reg = rd }, | ||
| 335 | }); | ||
| 336 | }, | 143 | }, |
| 337 | .gt => { | 144 | .vector => switch (dest_size) { |
| 338 | try lower.emit(less_than, &.{ | 145 | .byte => .vse8v, |
| 339 | .{ .reg = rd }, | 146 | .hword => .vse16v, |
| 340 | .{ .reg = rs2 }, | 147 | .word => .vse32v, |
| 341 | .{ .reg = rs1 }, | 148 | .dword => .vse64v, |
| 342 | }); | ||
| 343 | }, | 149 | }, |
| 344 | .gte => { | 150 | }; |
| 345 | try lower.emit(less_than, &.{ | 151 | |
| 346 | .{ .reg = rd }, | 152 | switch (src_reg_class) { |
| 347 | .{ .reg = rs1 }, | 153 | .int, .float => { |
| 348 | .{ .reg = rs2 }, | 154 | try lower.emit(mnem, &.{ |
| 349 | }); | 155 | .{ .reg = frame_loc.base }, |
| 350 | try lower.emit(.xori, &.{ | 156 | .{ .reg = rm.r }, |
| 351 | .{ .reg = rd }, | 157 | .{ .imm = Immediate.s(frame_loc.disp) }, |
| 352 | .{ .reg = rd }, | ||
| 353 | .{ .imm = Immediate.s(1) }, | ||
| 354 | }); | 158 | }); |
| 355 | }, | 159 | }, |
| 356 | .lt => { | 160 | .vector => { |
| 357 | try lower.emit(less_than, &.{ | 161 | assert(frame_loc.disp == 0); |
| 358 | .{ .reg = rd }, | 162 | try lower.emit(mnem, &.{ |
| 359 | .{ .reg = rs1 }, | 163 | .{ .reg = rm.r }, |
| 360 | .{ .reg = rs2 }, | 164 | .{ .reg = frame_loc.base }, |
| 165 | .{ .reg = .zero }, | ||
| 361 | }); | 166 | }); |
| 362 | }, | 167 | }, |
| 363 | .lte => { | 168 | } |
| 364 | try lower.emit(less_than, &.{ | 169 | }, |
| 365 | .{ .reg = rd }, | 170 | else => unreachable, |
| 366 | .{ .reg = rs2 }, | 171 | } |
| 367 | .{ .reg = rs1 }, | 172 | }, |
| 368 | }); | ||
| 369 | 173 | ||
| 370 | try lower.emit(.xori, &.{ | 174 | .pseudo_mv => { |
| 371 | .{ .reg = rd }, | 175 | const rr = inst.data.rr; |
| 372 | .{ .reg = rd }, | 176 | |
| 373 | .{ .imm = Immediate.s(1) }, | 177 | const dst_class = rr.rd.class(); |
| 374 | }); | 178 | const src_class = rr.rs.class(); |
| 375 | }, | 179 | |
| 180 | switch (src_class) { | ||
| 181 | .float => switch (dst_class) { | ||
| 182 | .float => { | ||
| 183 | try lower.emit(if (lower.hasFeature(.d)) .fsgnjnd else .fsgnjns, &.{ | ||
| 184 | .{ .reg = rr.rd }, | ||
| 185 | .{ .reg = rr.rs }, | ||
| 186 | .{ .reg = rr.rs }, | ||
| 187 | }); | ||
| 376 | }, | 188 | }, |
| 377 | .float => switch (op) { | 189 | .int, .vector => return lower.fail("TODO: lowerMir pseudo_mv float -> {s}", .{@tagName(dst_class)}), |
| 378 | // eq | 190 | }, |
| 379 | .eq => { | 191 | .int => switch (dst_class) { |
| 380 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ | 192 | .int => { |
| 381 | .{ .reg = rd }, | 193 | try lower.emit(.addi, &.{ |
| 382 | .{ .reg = rs1 }, | 194 | .{ .reg = rr.rd }, |
| 383 | .{ .reg = rs2 }, | 195 | .{ .reg = rr.rs }, |
| 384 | }); | 196 | .{ .imm = Immediate.s(0) }, |
| 385 | }, | 197 | }); |
| 386 | // !(eq) | 198 | }, |
| 387 | .neq => { | 199 | .vector => { |
| 388 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ | 200 | try lower.emit(.vmvvx, &.{ |
| 389 | .{ .reg = rd }, | 201 | .{ .reg = rr.rd }, |
| 390 | .{ .reg = rs1 }, | 202 | .{ .reg = rr.rs }, |
| 391 | .{ .reg = rs2 }, | 203 | .{ .reg = .x0 }, |
| 392 | }); | 204 | }); |
| 393 | try lower.emit(.xori, &.{ | 205 | }, |
| 394 | .{ .reg = rd }, | 206 | .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}), |
| 395 | .{ .reg = rd }, | 207 | }, |
| 396 | .{ .imm = Immediate.s(1) }, | 208 | .vector => switch (dst_class) { |
| 397 | }); | 209 | .int => { |
| 398 | }, | 210 | try lower.emit(.vadcvv, &.{ |
| 399 | .lt => { | 211 | .{ .reg = rr.rd }, |
| 400 | try lower.emit(if (size == 64) .fltd else .flts, &.{ | 212 | .{ .reg = .zero }, |
| 401 | .{ .reg = rd }, | 213 | .{ .reg = rr.rs }, |
| 402 | .{ .reg = rs1 }, | 214 | }); |
| 403 | .{ .reg = rs2 }, | 215 | }, |
| 404 | }); | 216 | .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}), |
| 405 | }, | 217 | }, |
| 406 | .lte => { | 218 | } |
| 407 | try lower.emit(if (size == 64) .fled else .fles, &.{ | 219 | }, |
| 408 | .{ .reg = rd }, | 220 | |
| 409 | .{ .reg = rs1 }, | 221 | .pseudo_j => { |
| 410 | .{ .reg = rs2 }, | 222 | const j_type = inst.data.j_type; |
| 411 | }); | 223 | try lower.emit(.jal, &.{ |
| 412 | }, | 224 | .{ .reg = j_type.rd }, |
| 413 | .gt => { | 225 | .{ .imm = lower.reloc(.{ .inst = j_type.inst }) }, |
| 414 | try lower.emit(if (size == 64) .fltd else .flts, &.{ | 226 | }); |
| 415 | .{ .reg = rd }, | 227 | }, |
| 416 | .{ .reg = rs2 }, | 228 | |
| 417 | .{ .reg = rs1 }, | 229 | .pseudo_spill_regs => try lower.pushPopRegList(true, inst.data.reg_list), |
| 418 | }); | 230 | .pseudo_restore_regs => try lower.pushPopRegList(false, inst.data.reg_list), |
| 419 | }, | 231 | |
| 420 | .gte => { | 232 | .pseudo_load_symbol => { |
| 421 | try lower.emit(if (size == 64) .fled else .fles, &.{ | 233 | const payload = inst.data.reloc; |
| 422 | .{ .reg = rd }, | 234 | const dst_reg = payload.register; |
| 423 | .{ .reg = rs2 }, | 235 | assert(dst_reg.class() == .int); |
| 424 | .{ .reg = rs1 }, | 236 | |
| 425 | }); | 237 | try lower.emit(.lui, &.{ |
| 426 | }, | 238 | .{ .reg = dst_reg }, |
| 239 | .{ .imm = lower.reloc(.{ | ||
| 240 | .load_symbol_reloc = .{ | ||
| 241 | .atom_index = payload.atom_index, | ||
| 242 | .sym_index = payload.sym_index, | ||
| 243 | }, | ||
| 244 | }) }, | ||
| 245 | }); | ||
| 246 | |||
| 247 | // the reloc above implies this one | ||
| 248 | try lower.emit(.addi, &.{ | ||
| 249 | .{ .reg = dst_reg }, | ||
| 250 | .{ .reg = dst_reg }, | ||
| 251 | .{ .imm = Immediate.s(0) }, | ||
| 252 | }); | ||
| 253 | }, | ||
| 254 | |||
| 255 | .pseudo_lea_rm => { | ||
| 256 | const rm = inst.data.rm; | ||
| 257 | assert(rm.r.class() == .int); | ||
| 258 | |||
| 259 | const frame: Mir.FrameLoc = if (options.allow_frame_locs) | ||
| 260 | rm.m.toFrameLoc(lower.mir) | ||
| 261 | else | ||
| 262 | .{ .base = .s0, .disp = 0 }; | ||
| 263 | |||
| 264 | try lower.emit(.addi, &.{ | ||
| 265 | .{ .reg = rm.r }, | ||
| 266 | .{ .reg = frame.base }, | ||
| 267 | .{ .imm = Immediate.s(frame.disp) }, | ||
| 268 | }); | ||
| 269 | }, | ||
| 270 | |||
| 271 | .pseudo_compare => { | ||
| 272 | const compare = inst.data.compare; | ||
| 273 | const op = compare.op; | ||
| 274 | |||
| 275 | const rd = compare.rd; | ||
| 276 | const rs1 = compare.rs1; | ||
| 277 | const rs2 = compare.rs2; | ||
| 278 | |||
| 279 | const class = rs1.class(); | ||
| 280 | const ty = compare.ty; | ||
| 281 | const size = std.math.ceilPowerOfTwo(u64, ty.bitSize(pt)) catch { | ||
| 282 | return lower.fail("pseudo_compare size {}", .{ty.bitSize(pt)}); | ||
| 283 | }; | ||
| 284 | |||
| 285 | const is_unsigned = ty.isUnsignedInt(pt.zcu); | ||
| 286 | const less_than: Mnemonic = if (is_unsigned) .sltu else .slt; | ||
| 287 | |||
| 288 | switch (class) { | ||
| 289 | .int => switch (op) { | ||
| 290 | .eq => { | ||
| 291 | try lower.emit(.xor, &.{ | ||
| 292 | .{ .reg = rd }, | ||
| 293 | .{ .reg = rs1 }, | ||
| 294 | .{ .reg = rs2 }, | ||
| 295 | }); | ||
| 296 | |||
| 297 | try lower.emit(.sltiu, &.{ | ||
| 298 | .{ .reg = rd }, | ||
| 299 | .{ .reg = rd }, | ||
| 300 | .{ .imm = Immediate.s(1) }, | ||
| 301 | }); | ||
| 302 | }, | ||
| 303 | .neq => { | ||
| 304 | try lower.emit(.xor, &.{ | ||
| 305 | .{ .reg = rd }, | ||
| 306 | .{ .reg = rs1 }, | ||
| 307 | .{ .reg = rs2 }, | ||
| 308 | }); | ||
| 309 | |||
| 310 | try lower.emit(.sltu, &.{ | ||
| 311 | .{ .reg = rd }, | ||
| 312 | .{ .reg = .zero }, | ||
| 313 | .{ .reg = rd }, | ||
| 314 | }); | ||
| 315 | }, | ||
| 316 | .gt => { | ||
| 317 | try lower.emit(less_than, &.{ | ||
| 318 | .{ .reg = rd }, | ||
| 319 | .{ .reg = rs2 }, | ||
| 320 | .{ .reg = rs1 }, | ||
| 321 | }); | ||
| 322 | }, | ||
| 323 | .gte => { | ||
| 324 | try lower.emit(less_than, &.{ | ||
| 325 | .{ .reg = rd }, | ||
| 326 | .{ .reg = rs1 }, | ||
| 327 | .{ .reg = rs2 }, | ||
| 328 | }); | ||
| 329 | try lower.emit(.xori, &.{ | ||
| 330 | .{ .reg = rd }, | ||
| 331 | .{ .reg = rd }, | ||
| 332 | .{ .imm = Immediate.s(1) }, | ||
| 333 | }); | ||
| 334 | }, | ||
| 335 | .lt => { | ||
| 336 | try lower.emit(less_than, &.{ | ||
| 337 | .{ .reg = rd }, | ||
| 338 | .{ .reg = rs1 }, | ||
| 339 | .{ .reg = rs2 }, | ||
| 340 | }); | ||
| 341 | }, | ||
| 342 | .lte => { | ||
| 343 | try lower.emit(less_than, &.{ | ||
| 344 | .{ .reg = rd }, | ||
| 345 | .{ .reg = rs2 }, | ||
| 346 | .{ .reg = rs1 }, | ||
| 347 | }); | ||
| 348 | |||
| 349 | try lower.emit(.xori, &.{ | ||
| 350 | .{ .reg = rd }, | ||
| 351 | .{ .reg = rd }, | ||
| 352 | .{ .imm = Immediate.s(1) }, | ||
| 353 | }); | ||
| 354 | }, | ||
| 355 | }, | ||
| 356 | .float => switch (op) { | ||
| 357 | // eq | ||
| 358 | .eq => { | ||
| 359 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ | ||
| 360 | .{ .reg = rd }, | ||
| 361 | .{ .reg = rs1 }, | ||
| 362 | .{ .reg = rs2 }, | ||
| 363 | }); | ||
| 427 | }, | 364 | }, |
| 428 | .vector => return lower.fail("TODO: lowerMir pseudo_cmp vector", .{}), | 365 | // !(eq) |
| 429 | } | 366 | .neq => { |
| 430 | }, | 367 | try lower.emit(if (size == 64) .feqd else .feqs, &.{ |
| 431 | 368 | .{ .reg = rd }, | |
| 432 | .pseudo_not => { | 369 | .{ .reg = rs1 }, |
| 433 | const rr = inst.data.rr; | 370 | .{ .reg = rs2 }, |
| 434 | assert(rr.rs.class() == .int and rr.rd.class() == .int); | 371 | }); |
| 435 | 372 | try lower.emit(.xori, &.{ | |
| 436 | // mask out any other bits that aren't the boolean | 373 | .{ .reg = rd }, |
| 437 | try lower.emit(.andi, &.{ | 374 | .{ .reg = rd }, |
| 438 | .{ .reg = rr.rs }, | 375 | .{ .imm = Immediate.s(1) }, |
| 439 | .{ .reg = rr.rs }, | 376 | }); |
| 440 | .{ .imm = Immediate.s(1) }, | 377 | }, |
| 441 | }); | 378 | .lt => { |
| 442 | 379 | try lower.emit(if (size == 64) .fltd else .flts, &.{ | |
| 443 | try lower.emit(.sltiu, &.{ | 380 | .{ .reg = rd }, |
| 444 | .{ .reg = rr.rd }, | 381 | .{ .reg = rs1 }, |
| 445 | .{ .reg = rr.rs }, | 382 | .{ .reg = rs2 }, |
| 446 | .{ .imm = Immediate.s(1) }, | 383 | }); |
| 447 | }); | 384 | }, |
| 448 | }, | 385 | .lte => { |
| 449 | 386 | try lower.emit(if (size == 64) .fled else .fles, &.{ | |
| 450 | .pseudo_extern_fn_reloc => { | 387 | .{ .reg = rd }, |
| 451 | const inst_reloc = inst.data.reloc; | 388 | .{ .reg = rs1 }, |
| 452 | 389 | .{ .reg = rs2 }, | |
| 453 | try lower.emit(.auipc, &.{ | 390 | }); |
| 454 | .{ .reg = .ra }, | 391 | }, |
| 455 | .{ .imm = lower.reloc( | 392 | .gt => { |
| 456 | .{ .call_extern_fn_reloc = .{ | 393 | try lower.emit(if (size == 64) .fltd else .flts, &.{ |
| 457 | .atom_index = inst_reloc.atom_index, | 394 | .{ .reg = rd }, |
| 458 | .sym_index = inst_reloc.sym_index, | 395 | .{ .reg = rs2 }, |
| 459 | } }, | 396 | .{ .reg = rs1 }, |
| 460 | ) }, | 397 | }); |
| 461 | }); | 398 | }, |
| 462 | 399 | .gte => { | |
| 463 | try lower.emit(.jalr, &.{ | 400 | try lower.emit(if (size == 64) .fled else .fles, &.{ |
| 464 | .{ .reg = .ra }, | 401 | .{ .reg = rd }, |
| 465 | .{ .reg = .ra }, | 402 | .{ .reg = rs2 }, |
| 466 | .{ .imm = Immediate.s(0) }, | 403 | .{ .reg = rs1 }, |
| 467 | }); | 404 | }); |
| 468 | }, | 405 | }, |
| 469 | 406 | }, | |
| 470 | .pseudo_amo => { | 407 | .vector => return lower.fail("TODO: lowerMir pseudo_cmp vector", .{}), |
| 471 | const amo = inst.data.amo; | 408 | } |
| 472 | const is_d = amo.ty.abiSize(pt) == 8; | 409 | }, |
| 473 | const is_un = amo.ty.isUnsignedInt(pt.zcu); | 410 | |
| 474 | 411 | .pseudo_not => { | |
| 475 | const mnem: Encoding.Mnemonic = switch (amo.op) { | 412 | const rr = inst.data.rr; |
| 476 | // zig fmt: off | 413 | assert(rr.rs.class() == .int and rr.rd.class() == .int); |
| 477 | .SWAP => if (is_d) .amoswapd else .amoswapw, | 414 | |
| 478 | .ADD => if (is_d) .amoaddd else .amoaddw, | 415 | // mask out any other bits that aren't the boolean |
| 479 | .AND => if (is_d) .amoandd else .amoandw, | 416 | try lower.emit(.andi, &.{ |
| 480 | .OR => if (is_d) .amoord else .amoorw, | 417 | .{ .reg = rr.rs }, |
| 481 | .XOR => if (is_d) .amoxord else .amoxorw, | 418 | .{ .reg = rr.rs }, |
| 482 | .MAX => if (is_d) if (is_un) .amomaxud else .amomaxd else if (is_un) .amomaxuw else .amomaxw, | 419 | .{ .imm = Immediate.s(1) }, |
| 483 | .MIN => if (is_d) if (is_un) .amominud else .amomind else if (is_un) .amominuw else .amominw, | 420 | }); |
| 484 | // zig fmt: on | 421 | |
| 485 | }; | 422 | try lower.emit(.sltiu, &.{ |
| 486 | 423 | .{ .reg = rr.rd }, | |
| 487 | try lower.emit(mnem, &.{ | 424 | .{ .reg = rr.rs }, |
| 488 | .{ .reg = inst.data.amo.rd }, | 425 | .{ .imm = Immediate.s(1) }, |
| 489 | .{ .reg = inst.data.amo.rs1 }, | 426 | }); |
| 490 | .{ .reg = inst.data.amo.rs2 }, | 427 | }, |
| 491 | .{ .barrier = inst.data.amo.rl }, | 428 | |
| 492 | .{ .barrier = inst.data.amo.aq }, | 429 | .pseudo_extern_fn_reloc => { |
| 493 | }); | 430 | const inst_reloc = inst.data.reloc; |
| 494 | }, | 431 | |
| 495 | 432 | try lower.emit(.auipc, &.{ | |
| 496 | .pseudo_fence => { | 433 | .{ .reg = .ra }, |
| 497 | const fence = inst.data.fence; | 434 | .{ .imm = lower.reloc( |
| 498 | 435 | .{ .call_extern_fn_reloc = .{ | |
| 499 | try lower.emit(switch (fence.fm) { | 436 | .atom_index = inst_reloc.atom_index, |
| 500 | .tso => .fencetso, | 437 | .sym_index = inst_reloc.sym_index, |
| 501 | .none => .fence, | 438 | } }, |
| 502 | }, &.{ | 439 | ) }, |
| 503 | .{ .barrier = fence.succ }, | 440 | }); |
| 504 | .{ .barrier = fence.pred }, | 441 | |
| 505 | }); | 442 | try lower.emit(.jalr, &.{ |
| 506 | }, | 443 | .{ .reg = .ra }, |
| 507 | 444 | .{ .reg = .ra }, | |
| 508 | else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}), | 445 | .{ .imm = Immediate.s(0) }, |
| 446 | }); | ||
| 447 | }, | ||
| 448 | |||
| 449 | .pseudo_amo => { | ||
| 450 | const amo = inst.data.amo; | ||
| 451 | const is_d = amo.ty.abiSize(pt) == 8; | ||
| 452 | const is_un = amo.ty.isUnsignedInt(pt.zcu); | ||
| 453 | |||
| 454 | const mnem: Mnemonic = switch (amo.op) { | ||
| 455 | // zig fmt: off | ||
| 456 | .SWAP => if (is_d) .amoswapd else .amoswapw, | ||
| 457 | .ADD => if (is_d) .amoaddd else .amoaddw, | ||
| 458 | .AND => if (is_d) .amoandd else .amoandw, | ||
| 459 | .OR => if (is_d) .amoord else .amoorw, | ||
| 460 | .XOR => if (is_d) .amoxord else .amoxorw, | ||
| 461 | .MAX => if (is_d) if (is_un) .amomaxud else .amomaxd else if (is_un) .amomaxuw else .amomaxw, | ||
| 462 | .MIN => if (is_d) if (is_un) .amominud else .amomind else if (is_un) .amominuw else .amominw, | ||
| 463 | // zig fmt: on | ||
| 464 | }; | ||
| 465 | |||
| 466 | try lower.emit(mnem, &.{ | ||
| 467 | .{ .reg = inst.data.amo.rd }, | ||
| 468 | .{ .reg = inst.data.amo.rs1 }, | ||
| 469 | .{ .reg = inst.data.amo.rs2 }, | ||
| 470 | .{ .barrier = inst.data.amo.rl }, | ||
| 471 | .{ .barrier = inst.data.amo.aq }, | ||
| 472 | }); | ||
| 473 | }, | ||
| 474 | |||
| 475 | .pseudo_fence => { | ||
| 476 | const fence = inst.data.fence; | ||
| 477 | |||
| 478 | try lower.emit(switch (fence.fm) { | ||
| 479 | .tso => .fencetso, | ||
| 480 | .none => .fence, | ||
| 481 | }, &.{ | ||
| 482 | .{ .barrier = fence.succ }, | ||
| 483 | .{ .barrier = fence.pred }, | ||
| 484 | }); | ||
| 509 | }, | 485 | }, |
| 510 | } | 486 | } |
| 511 | 487 | ||
| ... | @@ -516,49 +492,46 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { | ... | @@ -516,49 +492,46 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { |
| 516 | } | 492 | } |
| 517 | 493 | ||
| 518 | fn generic(lower: *Lower, inst: Mir.Inst) Error!void { | 494 | fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 519 | const mnemonic = std.meta.stringToEnum(Encoding.Mnemonic, @tagName(inst.tag)) orelse { | 495 | const mnemonic = inst.tag; |
| 520 | return lower.fail("generic inst name '{s}' with op {s} doesn't match with a mnemonic", .{ | 496 | try lower.emit(mnemonic, switch (inst.data) { |
| 521 | @tagName(inst.tag), | ||
| 522 | @tagName(inst.ops), | ||
| 523 | }); | ||
| 524 | }; | ||
| 525 | try lower.emit(mnemonic, switch (inst.ops) { | ||
| 526 | .none => &.{}, | 497 | .none => &.{}, |
| 527 | .ri => &.{ | 498 | .u_type => |u| &.{ |
| 528 | .{ .reg = inst.data.u_type.rd }, | 499 | .{ .reg = u.rd }, |
| 529 | .{ .imm = inst.data.u_type.imm20 }, | 500 | .{ .imm = u.imm20 }, |
| 530 | }, | 501 | }, |
| 531 | .rr => &.{ | 502 | .i_type => |i| &.{ |
| 532 | .{ .reg = inst.data.rr.rd }, | 503 | .{ .reg = i.rd }, |
| 533 | .{ .reg = inst.data.rr.rs }, | 504 | .{ .reg = i.rs1 }, |
| 505 | .{ .imm = i.imm12 }, | ||
| 534 | }, | 506 | }, |
| 535 | .rri => &.{ | 507 | .rr => |rr| &.{ |
| 536 | .{ .reg = inst.data.i_type.rd }, | 508 | .{ .reg = rr.rd }, |
| 537 | .{ .reg = inst.data.i_type.rs1 }, | 509 | .{ .reg = rr.rs }, |
| 538 | .{ .imm = inst.data.i_type.imm12 }, | ||
| 539 | }, | 510 | }, |
| 540 | .rr_inst => &.{ | 511 | .b_type => |b| &.{ |
| 541 | .{ .reg = inst.data.b_type.rs1 }, | 512 | .{ .reg = b.rs1 }, |
| 542 | .{ .reg = inst.data.b_type.rs2 }, | 513 | .{ .reg = b.rs2 }, |
| 543 | .{ .imm = lower.reloc(.{ .inst = inst.data.b_type.inst }) }, | 514 | .{ .imm = lower.reloc(.{ .inst = b.inst }) }, |
| 544 | }, | 515 | }, |
| 545 | .rrr => &.{ | 516 | .r_type => |r| &.{ |
| 546 | .{ .reg = inst.data.r_type.rd }, | 517 | .{ .reg = r.rd }, |
| 547 | .{ .reg = inst.data.r_type.rs1 }, | 518 | .{ .reg = r.rs1 }, |
| 548 | .{ .reg = inst.data.r_type.rs2 }, | 519 | .{ .reg = r.rs2 }, |
| 549 | }, | 520 | }, |
| 550 | .csr => &.{ | 521 | .csr => |csr| &.{ |
| 551 | .{ .csr = inst.data.csr.csr }, | 522 | .{ .csr = csr.csr }, |
| 552 | .{ .reg = inst.data.csr.rs1 }, | 523 | .{ .reg = csr.rs1 }, |
| 553 | .{ .reg = inst.data.csr.rd }, | 524 | .{ .reg = csr.rd }, |
| 554 | }, | 525 | }, |
| 555 | else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}), | 526 | else => return lower.fail("TODO: generic lower {s}", .{@tagName(mnemonic)}), |
| 556 | }); | 527 | }); |
| 557 | } | 528 | } |
| 558 | 529 | ||
| 559 | fn emit(lower: *Lower, mnemonic: Encoding.Mnemonic, ops: []const Instruction.Operand) !void { | 530 | fn emit(lower: *Lower, mnemonic: Mnemonic, ops: []const Instruction.Operand) !void { |
| 560 | lower.result_insts[lower.result_insts_len] = | 531 | const lir = encoding.Lir.fromMnem(mnemonic); |
| 561 | try Instruction.new(mnemonic, ops); | 532 | const inst = Instruction.fromLir(lir, ops); |
| 533 | |||
| 534 | lower.result_insts[lower.result_insts_len] = inst; | ||
| 562 | lower.result_insts_len += 1; | 535 | lower.result_insts_len += 1; |
| 563 | } | 536 | } |
| 564 | 537 | ||
| ... | @@ -580,7 +553,7 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register | ... | @@ -580,7 +553,7 @@ fn pushPopRegList(lower: *Lower, comptime spilling: bool, reg_list: Mir.Register |
| 580 | const reg = abi.Registers.all_preserved[i]; | 553 | const reg = abi.Registers.all_preserved[i]; |
| 581 | 554 | ||
| 582 | const reg_class = reg.class(); | 555 | const reg_class = reg.class(); |
| 583 | const load_inst: Encoding.Mnemonic, const store_inst: Encoding.Mnemonic = switch (reg_class) { | 556 | const load_inst: Mnemonic, const store_inst: Mnemonic = switch (reg_class) { |
| 584 | .int => .{ .ld, .sd }, | 557 | .int => .{ .ld, .sd }, |
| 585 | .float => .{ .fld, .fsd }, | 558 | .float => .{ .fld, .fsd }, |
| 586 | .vector => unreachable, | 559 | .vector => unreachable, |
| ... | @@ -618,20 +591,22 @@ fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool { | ... | @@ -618,20 +591,22 @@ fn hasFeature(lower: *Lower, feature: std.Target.riscv.Feature) bool { |
| 618 | } | 591 | } |
| 619 | 592 | ||
| 620 | const Lower = @This(); | 593 | const Lower = @This(); |
| 621 | |||
| 622 | const abi = @import("abi.zig"); | ||
| 623 | const assert = std.debug.assert; | ||
| 624 | const bits = @import("bits.zig"); | ||
| 625 | const encoder = @import("encoder.zig"); | ||
| 626 | const link = @import("../../link.zig"); | ||
| 627 | const Encoding = @import("Encoding.zig"); | ||
| 628 | const std = @import("std"); | 594 | const std = @import("std"); |
| 595 | const assert = std.debug.assert; | ||
| 629 | const log = std.log.scoped(.lower); | 596 | const log = std.log.scoped(.lower); |
| 630 | 597 | ||
| 631 | const Air = @import("../../Air.zig"); | ||
| 632 | const Allocator = std.mem.Allocator; | 598 | const Allocator = std.mem.Allocator; |
| 633 | const ErrorMsg = Zcu.ErrorMsg; | 599 | const ErrorMsg = Zcu.ErrorMsg; |
| 634 | const Mir = @import("Mir.zig"); | 600 | |
| 601 | const link = @import("../../link.zig"); | ||
| 602 | const Air = @import("../../Air.zig"); | ||
| 635 | const Zcu = @import("../../Zcu.zig"); | 603 | const Zcu = @import("../../Zcu.zig"); |
| 636 | const Instruction = encoder.Instruction; | 604 | |
| 605 | const Mir = @import("Mir.zig"); | ||
| 606 | const abi = @import("abi.zig"); | ||
| 607 | const bits = @import("bits.zig"); | ||
| 608 | const encoding = @import("encoding.zig"); | ||
| 609 | |||
| 610 | const Mnemonic = @import("mnem.zig").Mnemonic; | ||
| 637 | const Immediate = bits.Immediate; | 611 | const Immediate = bits.Immediate; |
| 612 | const Instruction = encoding.Instruction; |
src/arch/riscv64/Mir.zig+19-281| ... | @@ -1,170 +1,17 @@ | ... | @@ -1,170 +1,17 @@ |
| 1 | //! Machine Intermediate Representation. | 1 | //! Machine Intermediate Representation. |
| 2 | //! This data is produced by RISCV64 Codegen or RISCV64 assembly parsing | 2 | //! This data is produced by CodeGen.zig |
| 3 | //! These instructions have a 1:1 correspondence with machine code instructions | ||
| 4 | //! for the target. MIR can be lowered to source-annotated textual assembly code | ||
| 5 | //! instructions, or it can be lowered to machine code. | ||
| 6 | //! The main purpose of MIR is to postpone the assignment of offsets until Isel, | ||
| 7 | //! so that, for example, the smaller encodings of jump instructions can be used. | ||
| 8 | 3 | ||
| 9 | instructions: std.MultiArrayList(Inst).Slice, | 4 | instructions: std.MultiArrayList(Inst).Slice, |
| 10 | /// The meaning of this data is determined by `Inst.Tag` value. | ||
| 11 | extra: []const u32, | ||
| 12 | frame_locs: std.MultiArrayList(FrameLoc).Slice, | 5 | frame_locs: std.MultiArrayList(FrameLoc).Slice, |
| 13 | 6 | ||
| 14 | pub const Inst = struct { | 7 | pub const Inst = struct { |
| 15 | tag: Tag, | 8 | tag: Mnemonic, |
| 16 | data: Data, | 9 | data: Data, |
| 17 | ops: Ops, | ||
| 18 | 10 | ||
| 19 | /// The position of an MIR instruction within the `Mir` instructions array. | ||
| 20 | pub const Index = u32; | 11 | pub const Index = u32; |
| 21 | 12 | ||
| 22 | pub const Tag = enum(u16) { | 13 | pub const Data = union(enum) { |
| 23 | 14 | none: void, | |
| 24 | // base extension | ||
| 25 | addi, | ||
| 26 | addiw, | ||
| 27 | |||
| 28 | jalr, | ||
| 29 | lui, | ||
| 30 | |||
| 31 | @"and", | ||
| 32 | andi, | ||
| 33 | |||
| 34 | xori, | ||
| 35 | xor, | ||
| 36 | @"or", | ||
| 37 | |||
| 38 | ebreak, | ||
| 39 | ecall, | ||
| 40 | unimp, | ||
| 41 | |||
| 42 | add, | ||
| 43 | addw, | ||
| 44 | sub, | ||
| 45 | subw, | ||
| 46 | |||
| 47 | sltu, | ||
| 48 | slt, | ||
| 49 | |||
| 50 | slli, | ||
| 51 | srli, | ||
| 52 | srai, | ||
| 53 | |||
| 54 | slliw, | ||
| 55 | srliw, | ||
| 56 | sraiw, | ||
| 57 | |||
| 58 | sll, | ||
| 59 | srl, | ||
| 60 | sra, | ||
| 61 | |||
| 62 | sllw, | ||
| 63 | srlw, | ||
| 64 | sraw, | ||
| 65 | |||
| 66 | jal, | ||
| 67 | |||
| 68 | beq, | ||
| 69 | bne, | ||
| 70 | |||
| 71 | nop, | ||
| 72 | |||
| 73 | ld, | ||
| 74 | lw, | ||
| 75 | lh, | ||
| 76 | lb, | ||
| 77 | |||
| 78 | sd, | ||
| 79 | sw, | ||
| 80 | sh, | ||
| 81 | sb, | ||
| 82 | |||
| 83 | // M extension | ||
| 84 | mul, | ||
| 85 | mulw, | ||
| 86 | |||
| 87 | div, | ||
| 88 | divu, | ||
| 89 | divw, | ||
| 90 | divuw, | ||
| 91 | |||
| 92 | rem, | ||
| 93 | remu, | ||
| 94 | remw, | ||
| 95 | remuw, | ||
| 96 | |||
| 97 | // F extension (32-bit float) | ||
| 98 | fadds, | ||
| 99 | fsubs, | ||
| 100 | fmuls, | ||
| 101 | fdivs, | ||
| 102 | |||
| 103 | fabss, | ||
| 104 | |||
| 105 | fmins, | ||
| 106 | fmaxs, | ||
| 107 | |||
| 108 | fsqrts, | ||
| 109 | |||
| 110 | flw, | ||
| 111 | fsw, | ||
| 112 | |||
| 113 | feqs, | ||
| 114 | flts, | ||
| 115 | fles, | ||
| 116 | |||
| 117 | // D extension (64-bit float) | ||
| 118 | faddd, | ||
| 119 | fsubd, | ||
| 120 | fmuld, | ||
| 121 | fdivd, | ||
| 122 | |||
| 123 | fabsd, | ||
| 124 | |||
| 125 | fmind, | ||
| 126 | fmaxd, | ||
| 127 | |||
| 128 | fsqrtd, | ||
| 129 | |||
| 130 | fld, | ||
| 131 | fsd, | ||
| 132 | |||
| 133 | feqd, | ||
| 134 | fltd, | ||
| 135 | fled, | ||
| 136 | |||
| 137 | // Zicsr Extension Instructions | ||
| 138 | csrrs, | ||
| 139 | |||
| 140 | // V Extension Instructions | ||
| 141 | vsetvli, | ||
| 142 | vsetivli, | ||
| 143 | vsetvl, | ||
| 144 | vaddvv, | ||
| 145 | vfaddvv, | ||
| 146 | vsubvv, | ||
| 147 | vfsubvv, | ||
| 148 | vmulvv, | ||
| 149 | vfmulvv, | ||
| 150 | vslidedownvx, | ||
| 151 | |||
| 152 | // Zbb Extension Instructions | ||
| 153 | clz, | ||
| 154 | clzw, | ||
| 155 | |||
| 156 | /// A pseudo-instruction. Used for anything that isn't 1:1 with an | ||
| 157 | /// assembly instruction. | ||
| 158 | pseudo, | ||
| 159 | }; | ||
| 160 | |||
| 161 | /// All instructions have a 4-byte payload, which is contained within | ||
| 162 | /// this union. `Ops` determines which union field is active, as well as | ||
| 163 | /// how to interpret the data within. | ||
| 164 | pub const Data = union { | ||
| 165 | nop: void, | ||
| 166 | inst: Index, | ||
| 167 | payload: u32, | ||
| 168 | r_type: struct { | 15 | r_type: struct { |
| 169 | rd: Register, | 16 | rd: Register, |
| 170 | rs1: Register, | 17 | rs1: Register, |
| ... | @@ -194,10 +41,6 @@ pub const Inst = struct { | ... | @@ -194,10 +41,6 @@ pub const Inst = struct { |
| 194 | rd: Register, | 41 | rd: Register, |
| 195 | inst: Inst.Index, | 42 | inst: Inst.Index, |
| 196 | }, | 43 | }, |
| 197 | pseudo_dbg_line_column: struct { | ||
| 198 | line: u32, | ||
| 199 | column: u32, | ||
| 200 | }, | ||
| 201 | rm: struct { | 44 | rm: struct { |
| 202 | r: Register, | 45 | r: Register, |
| 203 | m: Memory, | 46 | m: Memory, |
| ... | @@ -208,11 +51,6 @@ pub const Inst = struct { | ... | @@ -208,11 +51,6 @@ pub const Inst = struct { |
| 208 | rd: Register, | 51 | rd: Register, |
| 209 | rs: Register, | 52 | rs: Register, |
| 210 | }, | 53 | }, |
| 211 | fabs: struct { | ||
| 212 | rd: Register, | ||
| 213 | rs: Register, | ||
| 214 | bits: u16, | ||
| 215 | }, | ||
| 216 | compare: struct { | 54 | compare: struct { |
| 217 | rd: Register, | 55 | rd: Register, |
| 218 | rs1: Register, | 56 | rs1: Register, |
| ... | @@ -228,6 +66,7 @@ pub const Inst = struct { | ... | @@ -228,6 +66,7 @@ pub const Inst = struct { |
| 228 | ty: Type, | 66 | ty: Type, |
| 229 | }, | 67 | }, |
| 230 | reloc: struct { | 68 | reloc: struct { |
| 69 | register: Register, | ||
| 231 | atom_index: u32, | 70 | atom_index: u32, |
| 232 | sym_index: u32, | 71 | sym_index: u32, |
| 233 | }, | 72 | }, |
| ... | @@ -253,115 +92,26 @@ pub const Inst = struct { | ... | @@ -253,115 +92,26 @@ pub const Inst = struct { |
| 253 | rs1: Register, | 92 | rs1: Register, |
| 254 | rd: Register, | 93 | rd: Register, |
| 255 | }, | 94 | }, |
| 256 | }; | 95 | pseudo_dbg_line_column: struct { |
| 257 | 96 | line: u32, | |
| 258 | pub const Ops = enum { | 97 | column: u32, |
| 259 | /// No data associated with this instruction (only mnemonic is used). | 98 | }, |
| 260 | none, | ||
| 261 | /// Two registers | ||
| 262 | rr, | ||
| 263 | /// Three registers | ||
| 264 | rrr, | ||
| 265 | |||
| 266 | /// Two registers + immediate, uses the i_type payload. | ||
| 267 | rri, | ||
| 268 | //extern_fn_reloc/ Two registers + another instruction. | ||
| 269 | rr_inst, | ||
| 270 | |||
| 271 | /// Register + Memory | ||
| 272 | rm, | ||
| 273 | |||
| 274 | /// Register + Immediate | ||
| 275 | ri, | ||
| 276 | |||
| 277 | /// Another instruction. | ||
| 278 | inst, | ||
| 279 | |||
| 280 | /// Control and Status Register Instruction. | ||
| 281 | csr, | ||
| 282 | |||
| 283 | /// Pseudo-instruction that will generate a backpatched | ||
| 284 | /// function prologue. | ||
| 285 | pseudo_prologue, | ||
| 286 | /// Pseudo-instruction that will generate a backpatched | ||
| 287 | /// function epilogue | ||
| 288 | pseudo_epilogue, | ||
| 289 | |||
| 290 | /// Pseudo-instruction: End of prologue | ||
| 291 | pseudo_dbg_prologue_end, | ||
| 292 | /// Pseudo-instruction: Beginning of epilogue | ||
| 293 | pseudo_dbg_epilogue_begin, | ||
| 294 | /// Pseudo-instruction: Update debug line | ||
| 295 | pseudo_dbg_line_column, | ||
| 296 | |||
| 297 | /// Pseudo-instruction that loads from memory into a register. | ||
| 298 | /// | ||
| 299 | /// Uses `rm` payload. | ||
| 300 | pseudo_load_rm, | ||
| 301 | /// Pseudo-instruction that stores from a register into memory | ||
| 302 | /// | ||
| 303 | /// Uses `rm` payload. | ||
| 304 | pseudo_store_rm, | ||
| 305 | |||
| 306 | /// Pseudo-instruction that loads the address of memory into a register. | ||
| 307 | /// | ||
| 308 | /// Uses `rm` payload. | ||
| 309 | pseudo_lea_rm, | ||
| 310 | |||
| 311 | /// Jumps. Uses `inst` payload. | ||
| 312 | pseudo_j, | ||
| 313 | |||
| 314 | /// Floating point absolute value. | ||
| 315 | pseudo_fabs, | ||
| 316 | |||
| 317 | /// Dead inst, ignored by the emitter. | ||
| 318 | pseudo_dead, | ||
| 319 | |||
| 320 | /// Loads the address of a value that hasn't yet been allocated in memory. | ||
| 321 | /// | ||
| 322 | /// uses the Mir.LoadSymbolPayload payload. | ||
| 323 | pseudo_load_symbol, | ||
| 324 | |||
| 325 | /// Moves the value of rs1 to rd. | ||
| 326 | /// | ||
| 327 | /// uses the `rr` payload. | ||
| 328 | pseudo_mv, | ||
| 329 | |||
| 330 | pseudo_restore_regs, | ||
| 331 | pseudo_spill_regs, | ||
| 332 | |||
| 333 | pseudo_compare, | ||
| 334 | |||
| 335 | /// NOT operation on booleans. Does an `andi reg, reg, 1` to mask out any other bits from the boolean. | ||
| 336 | pseudo_not, | ||
| 337 | |||
| 338 | /// Generates an auipc + jalr pair, with a R_RISCV_CALL_PLT reloc | ||
| 339 | pseudo_extern_fn_reloc, | ||
| 340 | |||
| 341 | /// IORW, IORW | ||
| 342 | pseudo_fence, | ||
| 343 | |||
| 344 | /// Ordering, Src, Addr, Dest | ||
| 345 | pseudo_amo, | ||
| 346 | }; | 99 | }; |
| 347 | 100 | ||
| 348 | pub fn format( | 101 | pub fn format( |
| 349 | inst: Inst, | 102 | inst: Inst, |
| 350 | comptime fmt: []const u8, | 103 | comptime fmt: []const u8, |
| 351 | options: std.fmt.FormatOptions, | 104 | _: std.fmt.FormatOptions, |
| 352 | writer: anytype, | 105 | writer: anytype, |
| 353 | ) !void { | 106 | ) !void { |
| 354 | assert(fmt.len == 0); | 107 | assert(fmt.len == 0); |
| 355 | _ = options; | 108 | try writer.print("Tag: {s}, Data: {s}", .{ @tagName(inst.tag), @tagName(inst.data) }); |
| 356 | |||
| 357 | try writer.print("Tag: {s}, Ops: {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }); | ||
| 358 | } | 109 | } |
| 359 | }; | 110 | }; |
| 360 | 111 | ||
| 361 | pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { | 112 | pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { |
| 362 | mir.instructions.deinit(gpa); | 113 | mir.instructions.deinit(gpa); |
| 363 | mir.frame_locs.deinit(gpa); | 114 | mir.frame_locs.deinit(gpa); |
| 364 | gpa.free(mir.extra); | ||
| 365 | mir.* = undefined; | 115 | mir.* = undefined; |
| 366 | } | 116 | } |
| 367 | 117 | ||
| ... | @@ -392,25 +142,12 @@ pub const AmoOp = enum(u5) { | ... | @@ -392,25 +142,12 @@ pub const AmoOp = enum(u5) { |
| 392 | MIN, | 142 | MIN, |
| 393 | }; | 143 | }; |
| 394 | 144 | ||
| 395 | /// Returns the requested data, as well as the new index which is at the start of the | 145 | pub const FcvtOp = enum(u5) { |
| 396 | /// trailers for the object. | 146 | w = 0b00000, |
| 397 | pub fn extraData(mir: Mir, comptime T: type, index: usize) struct { data: T, end: usize } { | 147 | wu = 0b00001, |
| 398 | const fields = std.meta.fields(T); | 148 | l = 0b00010, |
| 399 | var i: usize = index; | 149 | lu = 0b00011, |
| 400 | var result: T = undefined; | 150 | }; |
| 401 | inline for (fields) |field| { | ||
| 402 | @field(result, field.name) = switch (field.type) { | ||
| 403 | u32 => mir.extra[i], | ||
| 404 | i32 => @as(i32, @bitCast(mir.extra[i])), | ||
| 405 | else => @compileError("bad field type"), | ||
| 406 | }; | ||
| 407 | i += 1; | ||
| 408 | } | ||
| 409 | return .{ | ||
| 410 | .data = result, | ||
| 411 | .end = i, | ||
| 412 | }; | ||
| 413 | } | ||
| 414 | 151 | ||
| 415 | pub const LoadSymbolPayload = struct { | 152 | pub const LoadSymbolPayload = struct { |
| 416 | register: u32, | 153 | register: u32, |
| ... | @@ -459,10 +196,10 @@ const Mir = @This(); | ... | @@ -459,10 +196,10 @@ const Mir = @This(); |
| 459 | const std = @import("std"); | 196 | const std = @import("std"); |
| 460 | const builtin = @import("builtin"); | 197 | const builtin = @import("builtin"); |
| 461 | const Type = @import("../../Type.zig"); | 198 | const Type = @import("../../Type.zig"); |
| 199 | const bits = @import("bits.zig"); | ||
| 462 | 200 | ||
| 463 | const assert = std.debug.assert; | 201 | const assert = std.debug.assert; |
| 464 | 202 | ||
| 465 | const bits = @import("bits.zig"); | ||
| 466 | const Register = bits.Register; | 203 | const Register = bits.Register; |
| 467 | const CSR = bits.CSR; | 204 | const CSR = bits.CSR; |
| 468 | const Immediate = bits.Immediate; | 205 | const Immediate = bits.Immediate; |
| ... | @@ -470,3 +207,4 @@ const Memory = bits.Memory; | ... | @@ -470,3 +207,4 @@ const Memory = bits.Memory; |
| 470 | const FrameIndex = bits.FrameIndex; | 207 | const FrameIndex = bits.FrameIndex; |
| 471 | const FrameAddr = @import("CodeGen.zig").FrameAddr; | 208 | const FrameAddr = @import("CodeGen.zig").FrameAddr; |
| 472 | const IntegerBitSet = std.bit_set.IntegerBitSet; | 209 | const IntegerBitSet = std.bit_set.IntegerBitSet; |
| 210 | const Mnemonic = @import("mnem.zig").Mnemonic; |
src/arch/riscv64/bits.zig+1-2| ... | @@ -5,7 +5,6 @@ const testing = std.testing; | ... | @@ -5,7 +5,6 @@ const testing = std.testing; |
| 5 | const Target = std.Target; | 5 | const Target = std.Target; |
| 6 | 6 | ||
| 7 | const Zcu = @import("../../Zcu.zig"); | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | const Encoding = @import("Encoding.zig"); | ||
| 9 | const Mir = @import("Mir.zig"); | 8 | const Mir = @import("Mir.zig"); |
| 10 | const abi = @import("abi.zig"); | 9 | const abi = @import("abi.zig"); |
| 11 | 10 | ||
| ... | @@ -193,7 +192,7 @@ pub const Register = enum(u8) { | ... | @@ -193,7 +192,7 @@ pub const Register = enum(u8) { |
| 193 | /// The goal of this function is to return the same ID for `zero` and `x0` but two | 192 | /// The goal of this function is to return the same ID for `zero` and `x0` but two |
| 194 | /// seperate IDs for `x0` and `f0`. We will assume that each register set has 32 registers | 193 | /// seperate IDs for `x0` and `f0`. We will assume that each register set has 32 registers |
| 195 | /// and is repeated twice, once for the named version, once for the number version. | 194 | /// and is repeated twice, once for the named version, once for the number version. |
| 196 | pub fn id(reg: Register) u8 { | 195 | pub fn id(reg: Register) std.math.IntFittingRange(0, @typeInfo(Register).Enum.fields.len) { |
| 197 | const base = switch (@intFromEnum(reg)) { | 196 | const base = switch (@intFromEnum(reg)) { |
| 198 | // zig fmt: off | 197 | // zig fmt: off |
| 199 | @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => @intFromEnum(Register.zero), | 198 | @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => @intFromEnum(Register.zero), |
src/arch/riscv64/encoder.zig deleted-80| ... | @@ -1,80 +0,0 @@ | ||
| 1 | pub const Instruction = struct { | ||
| 2 | encoding: Encoding, | ||
| 3 | ops: [5]Operand = .{.none} ** 5, | ||
| 4 | |||
| 5 | pub const Operand = union(enum) { | ||
| 6 | none, | ||
| 7 | reg: Register, | ||
| 8 | csr: CSR, | ||
| 9 | mem: Memory, | ||
| 10 | imm: Immediate, | ||
| 11 | barrier: Mir.Barrier, | ||
| 12 | }; | ||
| 13 | |||
| 14 | pub fn new(mnemonic: Encoding.Mnemonic, ops: []const Operand) !Instruction { | ||
| 15 | const encoding = (try Encoding.findByMnemonic(mnemonic, ops)) orelse { | ||
| 16 | std.log.err("no encoding found for: {s} [{s} {s} {s} {s} {s}]", .{ | ||
| 17 | @tagName(mnemonic), | ||
| 18 | @tagName(if (ops.len > 0) ops[0] else .none), | ||
| 19 | @tagName(if (ops.len > 1) ops[1] else .none), | ||
| 20 | @tagName(if (ops.len > 2) ops[2] else .none), | ||
| 21 | @tagName(if (ops.len > 3) ops[3] else .none), | ||
| 22 | @tagName(if (ops.len > 4) ops[4] else .none), | ||
| 23 | }); | ||
| 24 | return error.InvalidInstruction; | ||
| 25 | }; | ||
| 26 | |||
| 27 | var result_ops: [5]Operand = .{.none} ** 5; | ||
| 28 | @memcpy(result_ops[0..ops.len], ops); | ||
| 29 | |||
| 30 | return .{ | ||
| 31 | .encoding = encoding, | ||
| 32 | .ops = result_ops, | ||
| 33 | }; | ||
| 34 | } | ||
| 35 | |||
| 36 | pub fn encode(inst: Instruction, writer: anytype) !void { | ||
| 37 | try writer.writeInt(u32, inst.encoding.data.toU32(), .little); | ||
| 38 | } | ||
| 39 | |||
| 40 | pub fn format( | ||
| 41 | inst: Instruction, | ||
| 42 | comptime fmt: []const u8, | ||
| 43 | _: std.fmt.FormatOptions, | ||
| 44 | writer: anytype, | ||
| 45 | ) !void { | ||
| 46 | std.debug.assert(fmt.len == 0); | ||
| 47 | |||
| 48 | const encoding = inst.encoding; | ||
| 49 | |||
| 50 | try writer.print("{s} ", .{@tagName(encoding.mnemonic)}); | ||
| 51 | |||
| 52 | var i: u32 = 0; | ||
| 53 | while (i < inst.ops.len and inst.ops[i] != .none) : (i += 1) { | ||
| 54 | if (i != inst.ops.len and i != 0) try writer.writeAll(", "); | ||
| 55 | |||
| 56 | switch (@as(Instruction.Operand, inst.ops[i])) { | ||
| 57 | .none => unreachable, // it's sliced out above | ||
| 58 | .reg => |reg| try writer.writeAll(@tagName(reg)), | ||
| 59 | .imm => |imm| try writer.print("{d}", .{imm.asSigned(64)}), | ||
| 60 | .mem => try writer.writeAll("mem"), | ||
| 61 | .barrier => |barrier| try writer.writeAll(@tagName(barrier)), | ||
| 62 | .csr => |csr| try writer.writeAll(@tagName(csr)), | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | }; | ||
| 67 | |||
| 68 | const std = @import("std"); | ||
| 69 | |||
| 70 | const Lower = @import("Lower.zig"); | ||
| 71 | const Mir = @import("Mir.zig"); | ||
| 72 | const bits = @import("bits.zig"); | ||
| 73 | const Encoding = @import("Encoding.zig"); | ||
| 74 | |||
| 75 | const Register = bits.Register; | ||
| 76 | const CSR = bits.CSR; | ||
| 77 | const Memory = bits.Memory; | ||
| 78 | const Immediate = bits.Immediate; | ||
| 79 | |||
| 80 | const log = std.log.scoped(.encode); | ||
src/arch/riscv64/encoding.zig created+716| ... | @@ -0,0 +1,716 @@ | ||
| 1 | //! This file is responsible for going from MIR, which is emitted by CodeGen | ||
| 2 | //! and converting it into Instructions, which can be used as needed. | ||
| 3 | //! | ||
| 4 | //! Here we encode how mnemonics relate to opcodes and where their operands go. | ||
| 5 | |||
| 6 | /// Lower Instruction Representation | ||
| 7 | /// | ||
| 8 | /// This format encodes a specific instruction, however it's still abstracted | ||
| 9 | /// away from the true encoding it'll be in. It's meant to make the process of | ||
| 10 | /// indicating unique encoding data easier. | ||
| 11 | pub const Lir = struct { | ||
| 12 | opcode: OpCode, | ||
| 13 | format: Format, | ||
| 14 | data: Data, | ||
| 15 | |||
| 16 | pub const Format = enum { | ||
| 17 | R, | ||
| 18 | I, | ||
| 19 | S, | ||
| 20 | B, | ||
| 21 | U, | ||
| 22 | J, | ||
| 23 | extra, | ||
| 24 | }; | ||
| 25 | |||
| 26 | const Data = union(enum) { | ||
| 27 | none, | ||
| 28 | f: struct { funct3: u3 }, | ||
| 29 | ff: struct { | ||
| 30 | funct3: u3, | ||
| 31 | funct7: u7, | ||
| 32 | }, | ||
| 33 | sh: struct { | ||
| 34 | typ: u6, | ||
| 35 | funct3: u3, | ||
| 36 | has_5: bool, | ||
| 37 | }, | ||
| 38 | |||
| 39 | fmt: struct { | ||
| 40 | funct5: u5, | ||
| 41 | rm: u3, | ||
| 42 | fmt: FpFmt, | ||
| 43 | }, | ||
| 44 | fcvt: struct { | ||
| 45 | funct5: u5, | ||
| 46 | rm: u3, | ||
| 47 | fmt: FpFmt, | ||
| 48 | width: Mir.FcvtOp, | ||
| 49 | }, | ||
| 50 | |||
| 51 | vecls: struct { | ||
| 52 | width: VecWidth, | ||
| 53 | umop: Umop, | ||
| 54 | vm: bool, | ||
| 55 | mop: Mop, | ||
| 56 | mew: bool, | ||
| 57 | nf: u3, | ||
| 58 | }, | ||
| 59 | vecmath: struct { | ||
| 60 | vm: bool, | ||
| 61 | funct6: u6, | ||
| 62 | funct3: VecType, | ||
| 63 | }, | ||
| 64 | |||
| 65 | amo: struct { | ||
| 66 | funct5: u5, | ||
| 67 | width: AmoWidth, | ||
| 68 | }, | ||
| 69 | fence: struct { | ||
| 70 | funct3: u3, | ||
| 71 | fm: FenceMode, | ||
| 72 | }, | ||
| 73 | |||
| 74 | /// the mnemonic has some special properities that can't be handled in a generic fashion | ||
| 75 | extra: Mnemonic, | ||
| 76 | }; | ||
| 77 | |||
| 78 | const OpCode = enum(u7) { | ||
| 79 | LOAD = 0b0000011, | ||
| 80 | LOAD_FP = 0b0000111, | ||
| 81 | MISC_MEM = 0b0001111, | ||
| 82 | OP_IMM = 0b0010011, | ||
| 83 | AUIPC = 0b0010111, | ||
| 84 | OP_IMM_32 = 0b0011011, | ||
| 85 | STORE = 0b0100011, | ||
| 86 | STORE_FP = 0b0100111, | ||
| 87 | AMO = 0b0101111, | ||
| 88 | OP_V = 0b1010111, | ||
| 89 | OP = 0b0110011, | ||
| 90 | OP_32 = 0b0111011, | ||
| 91 | LUI = 0b0110111, | ||
| 92 | MADD = 0b1000011, | ||
| 93 | MSUB = 0b1000111, | ||
| 94 | NMSUB = 0b1001011, | ||
| 95 | NMADD = 0b1001111, | ||
| 96 | OP_FP = 0b1010011, | ||
| 97 | OP_IMM_64 = 0b1011011, | ||
| 98 | BRANCH = 0b1100011, | ||
| 99 | JALR = 0b1100111, | ||
| 100 | JAL = 0b1101111, | ||
| 101 | SYSTEM = 0b1110011, | ||
| 102 | OP_64 = 0b1111011, | ||
| 103 | NONE = 0b00000000, | ||
| 104 | }; | ||
| 105 | |||
| 106 | const FpFmt = enum(u2) { | ||
| 107 | /// 32-bit single-precision | ||
| 108 | S = 0b00, | ||
| 109 | /// 64-bit double-precision | ||
| 110 | D = 0b01, | ||
| 111 | |||
| 112 | // H = 0b10, unused in the G extension | ||
| 113 | |||
| 114 | /// 128-bit quad-precision | ||
| 115 | Q = 0b11, | ||
| 116 | }; | ||
| 117 | |||
| 118 | const AmoWidth = enum(u3) { | ||
| 119 | W = 0b010, | ||
| 120 | D = 0b011, | ||
| 121 | }; | ||
| 122 | |||
| 123 | const FenceMode = enum(u4) { | ||
| 124 | none = 0b0000, | ||
| 125 | tso = 0b1000, | ||
| 126 | }; | ||
| 127 | |||
| 128 | const Mop = enum(u2) { | ||
| 129 | // zig fmt: off | ||
| 130 | unit = 0b00, | ||
| 131 | unord = 0b01, | ||
| 132 | stride = 0b10, | ||
| 133 | ord = 0b11, | ||
| 134 | // zig fmt: on | ||
| 135 | }; | ||
| 136 | |||
| 137 | const Umop = enum(u5) { | ||
| 138 | // zig fmt: off | ||
| 139 | unit = 0b00000, | ||
| 140 | whole = 0b01000, | ||
| 141 | mask = 0b01011, | ||
| 142 | fault = 0b10000, | ||
| 143 | // zig fmt: on | ||
| 144 | }; | ||
| 145 | |||
| 146 | const VecWidth = enum(u3) { | ||
| 147 | // zig fmt: off | ||
| 148 | @"8" = 0b000, | ||
| 149 | @"16" = 0b101, | ||
| 150 | @"32" = 0b110, | ||
| 151 | @"64" = 0b111, | ||
| 152 | // zig fmt: on | ||
| 153 | }; | ||
| 154 | |||
| 155 | const VecType = enum(u3) { | ||
| 156 | OPIVV = 0b000, | ||
| 157 | OPFVV = 0b001, | ||
| 158 | OPMVV = 0b010, | ||
| 159 | OPIVI = 0b011, | ||
| 160 | OPIVX = 0b100, | ||
| 161 | OPFVF = 0b101, | ||
| 162 | OPMVX = 0b110, | ||
| 163 | }; | ||
| 164 | |||
| 165 | pub fn fromMnem(mnem: Mnemonic) Lir { | ||
| 166 | return switch (mnem) { | ||
| 167 | // zig fmt: off | ||
| 168 | |||
| 169 | // OP | ||
| 170 | .add => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, | ||
| 171 | .sub => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, | ||
| 172 | |||
| 173 | .@"and" => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } }, | ||
| 174 | .@"or" => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } }, | ||
| 175 | .xor => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } }, | ||
| 176 | |||
| 177 | .sltu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } }, | ||
| 178 | .slt => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } }, | ||
| 179 | |||
| 180 | .mul => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, | ||
| 181 | .mulh => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000001 } } }, | ||
| 182 | .mulhsu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000001 } } }, | ||
| 183 | .mulhu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000001 } } }, | ||
| 184 | |||
| 185 | .div => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } }, | ||
| 186 | .divu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } }, | ||
| 187 | |||
| 188 | .rem => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } }, | ||
| 189 | .remu => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } }, | ||
| 190 | |||
| 191 | .sll => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, | ||
| 192 | .srl => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } }, | ||
| 193 | .sra => .{ .opcode = .OP, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } }, | ||
| 194 | |||
| 195 | |||
| 196 | // OP_IMM | ||
| 197 | |||
| 198 | .addi => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 199 | .andi => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 200 | .xori => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b100 } } }, | ||
| 201 | |||
| 202 | .sltiu => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 203 | |||
| 204 | .slli => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = true } } }, | ||
| 205 | .srli => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = true } } }, | ||
| 206 | .srai => .{ .opcode = .OP_IMM, .format = .I, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = true } } }, | ||
| 207 | |||
| 208 | .clz => .{ .opcode = .OP_IMM, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } }, | ||
| 209 | |||
| 210 | // OP_IMM_32 | ||
| 211 | |||
| 212 | .slliw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b001, .has_5 = false } } }, | ||
| 213 | .srliw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b000000, .funct3 = 0b101, .has_5 = false } } }, | ||
| 214 | .sraiw => .{ .opcode = .OP_IMM_32, .format = .I, .data = .{ .sh = .{ .typ = 0b010000, .funct3 = 0b101, .has_5 = false } } }, | ||
| 215 | |||
| 216 | .clzw => .{ .opcode = .OP_IMM_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0110000 } } }, | ||
| 217 | |||
| 218 | // OP_32 | ||
| 219 | |||
| 220 | .addw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, | ||
| 221 | .subw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, | ||
| 222 | .mulw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, | ||
| 223 | |||
| 224 | .divw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000001 } } }, | ||
| 225 | .divuw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000001 } } }, | ||
| 226 | |||
| 227 | .remw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000001 } } }, | ||
| 228 | .remuw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000001 } } }, | ||
| 229 | |||
| 230 | .sllw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, | ||
| 231 | .srlw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0000000 } } }, | ||
| 232 | .sraw => .{ .opcode = .OP_32, .format = .R, .data = .{ .ff = .{ .funct3 = 0b101, .funct7 = 0b0100000 } } }, | ||
| 233 | |||
| 234 | |||
| 235 | // OP_FP | ||
| 236 | |||
| 237 | .fadds => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, | ||
| 238 | .faddd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, | ||
| 239 | |||
| 240 | .fsubs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .S, .rm = 0b111 } } }, | ||
| 241 | .fsubd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00001, .fmt = .D, .rm = 0b111 } } }, | ||
| 242 | |||
| 243 | .fmuls => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .S, .rm = 0b111 } } }, | ||
| 244 | .fmuld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00010, .fmt = .D, .rm = 0b111 } } }, | ||
| 245 | |||
| 246 | .fdivs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .S, .rm = 0b111 } } }, | ||
| 247 | .fdivd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00011, .fmt = .D, .rm = 0b111 } } }, | ||
| 248 | |||
| 249 | .fmins => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b000 } } }, | ||
| 250 | .fmind => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b000 } } }, | ||
| 251 | |||
| 252 | .fmaxs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .S, .rm = 0b001 } } }, | ||
| 253 | .fmaxd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00101, .fmt = .D, .rm = 0b001 } } }, | ||
| 254 | |||
| 255 | .fsqrts => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .S, .rm = 0b111 } } }, | ||
| 256 | .fsqrtd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b01011, .fmt = .D, .rm = 0b111 } } }, | ||
| 257 | |||
| 258 | .fles => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b000 } } }, | ||
| 259 | .fled => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b000 } } }, | ||
| 260 | |||
| 261 | .flts => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b001 } } }, | ||
| 262 | .fltd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b001 } } }, | ||
| 263 | |||
| 264 | .feqs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, | ||
| 265 | .feqd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, | ||
| 266 | |||
| 267 | .fsgnjns => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, | ||
| 268 | .fsgnjnd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, | ||
| 269 | |||
| 270 | .fsgnjxs => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b010 } } }, | ||
| 271 | .fsgnjxd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b010 } } }, | ||
| 272 | |||
| 273 | .fcvtws => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .w } } }, | ||
| 274 | .fcvtwus => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .wu } } }, | ||
| 275 | .fcvtls => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .l } } }, | ||
| 276 | .fcvtlus => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .S, .rm = 0b111, .width = .lu } } }, | ||
| 277 | |||
| 278 | .fcvtwd => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .w } } }, | ||
| 279 | .fcvtwud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .wu } } }, | ||
| 280 | .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } }, | ||
| 281 | .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } }, | ||
| 282 | |||
| 283 | // LOAD | ||
| 284 | |||
| 285 | .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 286 | .lh => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b001 } } }, | ||
| 287 | .lw => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 288 | .ld => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 289 | .lbu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b100 } } }, | ||
| 290 | .lhu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b101 } } }, | ||
| 291 | .lwu => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b110 } } }, | ||
| 292 | |||
| 293 | |||
| 294 | // STORE | ||
| 295 | |||
| 296 | .sb => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 297 | .sh => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b001 } } }, | ||
| 298 | .sw => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 299 | .sd => .{ .opcode = .STORE, .format = .S, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 300 | |||
| 301 | |||
| 302 | // LOAD_FP | ||
| 303 | |||
| 304 | .flw => .{ .opcode = .LOAD_FP, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 305 | .fld => .{ .opcode = .LOAD_FP, .format = .I, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 306 | |||
| 307 | .vle8v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 308 | .vle16v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 309 | .vle32v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 310 | .vle64v => .{ .opcode = .LOAD_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 311 | |||
| 312 | |||
| 313 | // STORE_FP | ||
| 314 | |||
| 315 | .fsw => .{ .opcode = .STORE_FP, .format = .S, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 316 | .fsd => .{ .opcode = .STORE_FP, .format = .S, .data = .{ .f = .{ .funct3 = 0b011 } } }, | ||
| 317 | |||
| 318 | .vse8v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 319 | .vse16v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 320 | .vse32v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 321 | .vse64v => .{ .opcode = .STORE_FP, .format = .R, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } }, | ||
| 322 | |||
| 323 | // JALR | ||
| 324 | |||
| 325 | .jalr => .{ .opcode = .JALR, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 326 | |||
| 327 | |||
| 328 | // LUI | ||
| 329 | |||
| 330 | .lui => .{ .opcode = .LUI, .format = .U, .data = .{ .none = {} } }, | ||
| 331 | |||
| 332 | |||
| 333 | // AUIPC | ||
| 334 | |||
| 335 | .auipc => .{ .opcode = .AUIPC, .format = .U, .data = .{ .none = {} } }, | ||
| 336 | |||
| 337 | |||
| 338 | // JAL | ||
| 339 | |||
| 340 | .jal => .{ .opcode = .JAL, .format = .J, .data = .{ .none = {} } }, | ||
| 341 | |||
| 342 | |||
| 343 | // BRANCH | ||
| 344 | |||
| 345 | .beq => .{ .opcode = .BRANCH, .format = .B, .data = .{ .f = .{ .funct3 = 0b000 } } }, | ||
| 346 | |||
| 347 | |||
| 348 | // SYSTEM | ||
| 349 | |||
| 350 | .ecall => .{ .opcode = .SYSTEM, .format = .extra, .data = .{ .extra = .ecall } }, | ||
| 351 | .ebreak => .{ .opcode = .SYSTEM, .format = .extra, .data = .{ .extra = .ebreak } }, | ||
| 352 | |||
| 353 | .csrrs => .{ .opcode = .SYSTEM, .format = .I, .data = .{ .f = .{ .funct3 = 0b010 } } }, | ||
| 354 | |||
| 355 | |||
| 356 | // NONE | ||
| 357 | |||
| 358 | .unimp => .{ .opcode = .NONE, .format = .extra, .data = .{ .extra = .unimp } }, | ||
| 359 | |||
| 360 | |||
| 361 | // MISC_MEM | ||
| 362 | |||
| 363 | .fence => .{ .opcode = .MISC_MEM, .format = .I, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .none } } }, | ||
| 364 | .fencetso => .{ .opcode = .MISC_MEM, .format = .I, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .tso } } }, | ||
| 365 | |||
| 366 | |||
| 367 | // AMO | ||
| 368 | |||
| 369 | .amoaddw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00000 } } }, | ||
| 370 | .amoswapw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00001 } } }, | ||
| 371 | // LR.W | ||
| 372 | // SC.W | ||
| 373 | .amoxorw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b00100 } } }, | ||
| 374 | .amoandw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01100 } } }, | ||
| 375 | .amoorw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b01000 } } }, | ||
| 376 | .amominw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10000 } } }, | ||
| 377 | .amomaxw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b10100 } } }, | ||
| 378 | .amominuw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11000 } } }, | ||
| 379 | .amomaxuw => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .W, .funct5 = 0b11100 } } }, | ||
| 380 | |||
| 381 | .amoaddd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00000 } } }, | ||
| 382 | .amoswapd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00001 } } }, | ||
| 383 | // LR.D | ||
| 384 | // SC.D | ||
| 385 | .amoxord => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b00100 } } }, | ||
| 386 | .amoandd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01100 } } }, | ||
| 387 | .amoord => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b01000 } } }, | ||
| 388 | .amomind => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10000 } } }, | ||
| 389 | .amomaxd => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b10100 } } }, | ||
| 390 | .amominud => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11000 } } }, | ||
| 391 | .amomaxud => .{ .opcode = .AMO, .format = .R, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } }, | ||
| 392 | |||
| 393 | // OP_V | ||
| 394 | .vsetivli => .{ .opcode = .OP_V, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 395 | .vsetvli => .{ .opcode = .OP_V, .format = .I, .data = .{ .f = .{ .funct3 = 0b111 } } }, | ||
| 396 | .vaddvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } }, | ||
| 397 | .vsubvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } }, | ||
| 398 | .vmulvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100101, .funct3 = .OPIVV } } }, | ||
| 399 | |||
| 400 | .vfaddvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } }, | ||
| 401 | .vfsubvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } }, | ||
| 402 | .vfmulvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100100, .funct3 = .OPFVV } } }, | ||
| 403 | |||
| 404 | .vadcvv => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } }, | ||
| 405 | .vmvvx => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } }, | ||
| 406 | |||
| 407 | .vslidedownvx => .{ .opcode = .OP_V, .format = .R, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b001111, .funct3 = .OPIVX } } }, | ||
| 408 | |||
| 409 | |||
| 410 | .pseudo_prologue, | ||
| 411 | .pseudo_epilogue, | ||
| 412 | .pseudo_dbg_prologue_end, | ||
| 413 | .pseudo_dbg_epilogue_begin, | ||
| 414 | .pseudo_dbg_line_column, | ||
| 415 | .pseudo_load_rm, | ||
| 416 | .pseudo_store_rm, | ||
| 417 | .pseudo_lea_rm, | ||
| 418 | .pseudo_j, | ||
| 419 | .pseudo_dead, | ||
| 420 | .pseudo_load_symbol, | ||
| 421 | .pseudo_mv, | ||
| 422 | .pseudo_restore_regs, | ||
| 423 | .pseudo_spill_regs, | ||
| 424 | .pseudo_compare, | ||
| 425 | .pseudo_not, | ||
| 426 | .pseudo_extern_fn_reloc, | ||
| 427 | .pseudo_fence, | ||
| 428 | .pseudo_amo, | ||
| 429 | .nop, | ||
| 430 | => std.debug.panic("lir: didn't catch pseudo {s}", .{@tagName(mnem)}), | ||
| 431 | // zig fmt: on | ||
| 432 | }; | ||
| 433 | } | ||
| 434 | }; | ||
| 435 | |||
| 436 | /// This is the final form of the instruction. Lir is transformed into | ||
| 437 | /// this, which is then bitcast into a u32. | ||
| 438 | pub const Instruction = union(Lir.Format) { | ||
| 439 | R: packed struct(u32) { | ||
| 440 | opcode: u7, | ||
| 441 | rd: u5, | ||
| 442 | funct3: u3, | ||
| 443 | rs1: u5, | ||
| 444 | rs2: u5, | ||
| 445 | funct7: u7, | ||
| 446 | }, | ||
| 447 | I: packed struct(u32) { | ||
| 448 | opcode: u7, | ||
| 449 | rd: u5, | ||
| 450 | funct3: u3, | ||
| 451 | rs1: u5, | ||
| 452 | imm0_11: u12, | ||
| 453 | }, | ||
| 454 | S: packed struct(u32) { | ||
| 455 | opcode: u7, | ||
| 456 | imm0_4: u5, | ||
| 457 | funct3: u3, | ||
| 458 | rs1: u5, | ||
| 459 | rs2: u5, | ||
| 460 | imm5_11: u7, | ||
| 461 | }, | ||
| 462 | B: packed struct(u32) { | ||
| 463 | opcode: u7, | ||
| 464 | imm11: u1, | ||
| 465 | imm1_4: u4, | ||
| 466 | funct3: u3, | ||
| 467 | rs1: u5, | ||
| 468 | rs2: u5, | ||
| 469 | imm5_10: u6, | ||
| 470 | imm12: u1, | ||
| 471 | }, | ||
| 472 | U: packed struct(u32) { | ||
| 473 | opcode: u7, | ||
| 474 | rd: u5, | ||
| 475 | imm12_31: u20, | ||
| 476 | }, | ||
| 477 | J: packed struct(u32) { | ||
| 478 | opcode: u7, | ||
| 479 | rd: u5, | ||
| 480 | imm12_19: u8, | ||
| 481 | imm11: u1, | ||
| 482 | imm1_10: u10, | ||
| 483 | imm20: u1, | ||
| 484 | }, | ||
| 485 | extra: u32, | ||
| 486 | |||
| 487 | comptime { | ||
| 488 | for (std.meta.fields(Instruction)) |field| { | ||
| 489 | assert(@bitSizeOf(field.type) == 32); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | pub const Operand = union(enum) { | ||
| 494 | none, | ||
| 495 | reg: Register, | ||
| 496 | csr: CSR, | ||
| 497 | mem: Memory, | ||
| 498 | imm: Immediate, | ||
| 499 | barrier: Mir.Barrier, | ||
| 500 | }; | ||
| 501 | |||
| 502 | pub fn toU32(inst: Instruction) u32 { | ||
| 503 | return switch (inst) { | ||
| 504 | inline else => |v| @bitCast(v), | ||
| 505 | }; | ||
| 506 | } | ||
| 507 | |||
| 508 | pub fn encode(inst: Instruction, writer: anytype) !void { | ||
| 509 | try writer.writeInt(u32, inst.toU32(), .little); | ||
| 510 | } | ||
| 511 | |||
| 512 | pub fn fromLir(lir: Lir, ops: []const Operand) Instruction { | ||
| 513 | const opcode: u7 = @intFromEnum(lir.opcode); | ||
| 514 | |||
| 515 | switch (lir.format) { | ||
| 516 | .R => { | ||
| 517 | return .{ | ||
| 518 | .R = switch (lir.data) { | ||
| 519 | .ff => |ff| .{ | ||
| 520 | .rd = ops[0].reg.encodeId(), | ||
| 521 | .rs1 = ops[1].reg.encodeId(), | ||
| 522 | .rs2 = ops[2].reg.encodeId(), | ||
| 523 | |||
| 524 | .opcode = opcode, | ||
| 525 | .funct3 = ff.funct3, | ||
| 526 | .funct7 = ff.funct7, | ||
| 527 | }, | ||
| 528 | .fmt => |fmt| .{ | ||
| 529 | .rd = ops[0].reg.encodeId(), | ||
| 530 | .rs1 = ops[1].reg.encodeId(), | ||
| 531 | .rs2 = ops[2].reg.encodeId(), | ||
| 532 | |||
| 533 | .opcode = opcode, | ||
| 534 | .funct3 = fmt.rm, | ||
| 535 | .funct7 = (@as(u7, fmt.funct5) << 2) | @intFromEnum(fmt.fmt), | ||
| 536 | }, | ||
| 537 | .fcvt => |fcvt| .{ | ||
| 538 | .rd = ops[0].reg.encodeId(), | ||
| 539 | .rs1 = ops[1].reg.encodeId(), | ||
| 540 | .rs2 = @intFromEnum(fcvt.width), | ||
| 541 | |||
| 542 | .opcode = opcode, | ||
| 543 | .funct3 = fcvt.rm, | ||
| 544 | .funct7 = (@as(u7, fcvt.funct5) << 2) | @intFromEnum(fcvt.fmt), | ||
| 545 | }, | ||
| 546 | .vecls => |vec| .{ | ||
| 547 | .rd = ops[0].reg.encodeId(), | ||
| 548 | .rs1 = ops[1].reg.encodeId(), | ||
| 549 | |||
| 550 | .rs2 = @intFromEnum(vec.umop), | ||
| 551 | |||
| 552 | .opcode = opcode, | ||
| 553 | .funct3 = @intFromEnum(vec.width), | ||
| 554 | .funct7 = (@as(u7, vec.nf) << 4) | (@as(u7, @intFromBool(vec.mew)) << 3) | (@as(u7, @intFromEnum(vec.mop)) << 1) | @intFromBool(vec.vm), | ||
| 555 | }, | ||
| 556 | .vecmath => |vec| .{ | ||
| 557 | .rd = ops[0].reg.encodeId(), | ||
| 558 | .rs1 = ops[1].reg.encodeId(), | ||
| 559 | .rs2 = ops[2].reg.encodeId(), | ||
| 560 | |||
| 561 | .opcode = opcode, | ||
| 562 | .funct3 = @intFromEnum(vec.funct3), | ||
| 563 | .funct7 = (@as(u7, vec.funct6) << 1) | @intFromBool(vec.vm), | ||
| 564 | }, | ||
| 565 | .amo => |amo| .{ | ||
| 566 | .rd = ops[0].reg.encodeId(), | ||
| 567 | .rs1 = ops[1].reg.encodeId(), | ||
| 568 | .rs2 = ops[2].reg.encodeId(), | ||
| 569 | |||
| 570 | .opcode = opcode, | ||
| 571 | .funct3 = @intFromEnum(amo.width), | ||
| 572 | .funct7 = @as(u7, amo.funct5) << 2 | | ||
| 573 | @as(u7, @intFromBool(ops[3].barrier == .rl)) << 1 | | ||
| 574 | @as(u7, @intFromBool(ops[4].barrier == .aq)), | ||
| 575 | }, | ||
| 576 | else => unreachable, | ||
| 577 | }, | ||
| 578 | }; | ||
| 579 | }, | ||
| 580 | .S => { | ||
| 581 | assert(ops.len == 3); | ||
| 582 | const umm = ops[2].imm.asBits(u12); | ||
| 583 | return .{ | ||
| 584 | .S = .{ | ||
| 585 | .imm0_4 = @truncate(umm), | ||
| 586 | .rs1 = ops[0].reg.encodeId(), | ||
| 587 | .rs2 = ops[1].reg.encodeId(), | ||
| 588 | .imm5_11 = @truncate(umm >> 5), | ||
| 589 | |||
| 590 | .opcode = opcode, | ||
| 591 | .funct3 = lir.data.f.funct3, | ||
| 592 | }, | ||
| 593 | }; | ||
| 594 | }, | ||
| 595 | .I => { | ||
| 596 | return .{ | ||
| 597 | .I = switch (lir.data) { | ||
| 598 | .f => |f| .{ | ||
| 599 | .rd = ops[0].reg.encodeId(), | ||
| 600 | .rs1 = ops[1].reg.encodeId(), | ||
| 601 | .imm0_11 = ops[2].imm.asBits(u12), | ||
| 602 | |||
| 603 | .opcode = opcode, | ||
| 604 | .funct3 = f.funct3, | ||
| 605 | }, | ||
| 606 | .sh => |sh| .{ | ||
| 607 | .rd = ops[0].reg.encodeId(), | ||
| 608 | .rs1 = ops[1].reg.encodeId(), | ||
| 609 | .imm0_11 = (@as(u12, sh.typ) << 6) | | ||
| 610 | if (sh.has_5) ops[2].imm.asBits(u6) else (@as(u6, 0) | ops[2].imm.asBits(u5)), | ||
| 611 | |||
| 612 | .opcode = opcode, | ||
| 613 | .funct3 = sh.funct3, | ||
| 614 | }, | ||
| 615 | .fence => |fence| .{ | ||
| 616 | .rd = 0, | ||
| 617 | .rs1 = 0, | ||
| 618 | .funct3 = 0, | ||
| 619 | .imm0_11 = (@as(u12, @intFromEnum(fence.fm)) << 8) | | ||
| 620 | (@as(u12, @intFromEnum(ops[1].barrier)) << 4) | | ||
| 621 | @as(u12, @intFromEnum(ops[0].barrier)), | ||
| 622 | .opcode = opcode, | ||
| 623 | }, | ||
| 624 | else => unreachable, | ||
| 625 | }, | ||
| 626 | }; | ||
| 627 | }, | ||
| 628 | .U => { | ||
| 629 | assert(ops.len == 2); | ||
| 630 | return .{ | ||
| 631 | .U = .{ | ||
| 632 | .rd = ops[0].reg.encodeId(), | ||
| 633 | .imm12_31 = ops[1].imm.asBits(u20), | ||
| 634 | |||
| 635 | .opcode = opcode, | ||
| 636 | }, | ||
| 637 | }; | ||
| 638 | }, | ||
| 639 | .J => { | ||
| 640 | assert(ops.len == 2); | ||
| 641 | |||
| 642 | const umm = ops[1].imm.asBits(u21); | ||
| 643 | // the RISC-V spec says the target index of a jump | ||
| 644 | // must be a multiple of 2 | ||
| 645 | assert(umm % 2 == 0); | ||
| 646 | |||
| 647 | return .{ | ||
| 648 | .J = .{ | ||
| 649 | .rd = ops[0].reg.encodeId(), | ||
| 650 | .imm1_10 = @truncate(umm >> 1), | ||
| 651 | .imm11 = @truncate(umm >> 11), | ||
| 652 | .imm12_19 = @truncate(umm >> 12), | ||
| 653 | .imm20 = @truncate(umm >> 20), | ||
| 654 | |||
| 655 | .opcode = opcode, | ||
| 656 | }, | ||
| 657 | }; | ||
| 658 | }, | ||
| 659 | .B => { | ||
| 660 | assert(ops.len == 3); | ||
| 661 | |||
| 662 | const umm = ops[2].imm.asBits(u13); | ||
| 663 | // the RISC-V spec says the target index of a branch | ||
| 664 | // must be a multiple of 2 | ||
| 665 | assert(umm % 2 == 0); | ||
| 666 | |||
| 667 | return .{ | ||
| 668 | .B = .{ | ||
| 669 | .rs1 = ops[0].reg.encodeId(), | ||
| 670 | .rs2 = ops[1].reg.encodeId(), | ||
| 671 | .imm1_4 = @truncate(umm >> 1), | ||
| 672 | .imm5_10 = @truncate(umm >> 5), | ||
| 673 | .imm11 = @truncate(umm >> 11), | ||
| 674 | .imm12 = @truncate(umm >> 12), | ||
| 675 | |||
| 676 | .opcode = opcode, | ||
| 677 | .funct3 = lir.data.f.funct3, | ||
| 678 | }, | ||
| 679 | }; | ||
| 680 | }, | ||
| 681 | .extra => { | ||
| 682 | assert(ops.len == 0); | ||
| 683 | |||
| 684 | return .{ | ||
| 685 | .I = .{ | ||
| 686 | .rd = Register.zero.encodeId(), | ||
| 687 | .rs1 = Register.zero.encodeId(), | ||
| 688 | .imm0_11 = switch (lir.data.extra) { | ||
| 689 | .ecall => 0x000, | ||
| 690 | .ebreak => 0x001, | ||
| 691 | .unimp => 0x000, | ||
| 692 | else => unreachable, | ||
| 693 | }, | ||
| 694 | |||
| 695 | .opcode = opcode, | ||
| 696 | .funct3 = 0b000, | ||
| 697 | }, | ||
| 698 | }; | ||
| 699 | }, | ||
| 700 | } | ||
| 701 | } | ||
| 702 | }; | ||
| 703 | |||
| 704 | const std = @import("std"); | ||
| 705 | const assert = std.debug.assert; | ||
| 706 | const log = std.log.scoped(.format); | ||
| 707 | |||
| 708 | const bits = @import("bits.zig"); | ||
| 709 | const Mir = @import("Mir.zig"); | ||
| 710 | const Mnemonic = @import("mnem.zig").Mnemonic; | ||
| 711 | const Lower = @import("Lower.zig"); | ||
| 712 | |||
| 713 | const Register = bits.Register; | ||
| 714 | const CSR = bits.CSR; | ||
| 715 | const Memory = bits.Memory; | ||
| 716 | const Immediate = bits.Immediate; | ||
src/arch/riscv64/mnem.zig created+232| ... | @@ -0,0 +1,232 @@ | ||
| 1 | pub const Mnemonic = enum(u16) { | ||
| 2 | // Arithmetics | ||
| 3 | addi, | ||
| 4 | add, | ||
| 5 | addw, | ||
| 6 | |||
| 7 | sub, | ||
| 8 | subw, | ||
| 9 | |||
| 10 | // Bits | ||
| 11 | xori, | ||
| 12 | xor, | ||
| 13 | @"or", | ||
| 14 | |||
| 15 | @"and", | ||
| 16 | andi, | ||
| 17 | |||
| 18 | slt, | ||
| 19 | sltu, | ||
| 20 | sltiu, | ||
| 21 | |||
| 22 | slli, | ||
| 23 | srli, | ||
| 24 | srai, | ||
| 25 | |||
| 26 | slliw, | ||
| 27 | srliw, | ||
| 28 | sraiw, | ||
| 29 | |||
| 30 | sll, | ||
| 31 | srl, | ||
| 32 | sra, | ||
| 33 | |||
| 34 | sllw, | ||
| 35 | srlw, | ||
| 36 | sraw, | ||
| 37 | |||
| 38 | // Control Flow | ||
| 39 | jalr, | ||
| 40 | jal, | ||
| 41 | |||
| 42 | beq, | ||
| 43 | |||
| 44 | // Memory | ||
| 45 | lui, | ||
| 46 | auipc, | ||
| 47 | |||
| 48 | ld, | ||
| 49 | lw, | ||
| 50 | lh, | ||
| 51 | lb, | ||
| 52 | lbu, | ||
| 53 | lhu, | ||
| 54 | lwu, | ||
| 55 | |||
| 56 | sd, | ||
| 57 | sw, | ||
| 58 | sh, | ||
| 59 | sb, | ||
| 60 | |||
| 61 | // System | ||
| 62 | ebreak, | ||
| 63 | ecall, | ||
| 64 | unimp, | ||
| 65 | nop, | ||
| 66 | |||
| 67 | // M extension | ||
| 68 | mul, | ||
| 69 | mulh, | ||
| 70 | mulhu, | ||
| 71 | mulhsu, | ||
| 72 | mulw, | ||
| 73 | |||
| 74 | div, | ||
| 75 | divu, | ||
| 76 | divw, | ||
| 77 | divuw, | ||
| 78 | |||
| 79 | rem, | ||
| 80 | remu, | ||
| 81 | remw, | ||
| 82 | remuw, | ||
| 83 | |||
| 84 | // F extension (32-bit float) | ||
| 85 | fadds, | ||
| 86 | fsubs, | ||
| 87 | fmuls, | ||
| 88 | fdivs, | ||
| 89 | |||
| 90 | fmins, | ||
| 91 | fmaxs, | ||
| 92 | |||
| 93 | fsqrts, | ||
| 94 | |||
| 95 | flw, | ||
| 96 | fsw, | ||
| 97 | |||
| 98 | feqs, | ||
| 99 | flts, | ||
| 100 | fles, | ||
| 101 | |||
| 102 | // D extension (64-bit float) | ||
| 103 | faddd, | ||
| 104 | fsubd, | ||
| 105 | fmuld, | ||
| 106 | fdivd, | ||
| 107 | |||
| 108 | fmind, | ||
| 109 | fmaxd, | ||
| 110 | |||
| 111 | fsqrtd, | ||
| 112 | |||
| 113 | fld, | ||
| 114 | fsd, | ||
| 115 | |||
| 116 | feqd, | ||
| 117 | fltd, | ||
| 118 | fled, | ||
| 119 | |||
| 120 | fcvtws, | ||
| 121 | fcvtwus, | ||
| 122 | fcvtls, | ||
| 123 | fcvtlus, | ||
| 124 | |||
| 125 | fcvtwd, | ||
| 126 | fcvtwud, | ||
| 127 | fcvtld, | ||
| 128 | fcvtlud, | ||
| 129 | |||
| 130 | fsgnjns, | ||
| 131 | fsgnjnd, | ||
| 132 | |||
| 133 | fsgnjxs, | ||
| 134 | fsgnjxd, | ||
| 135 | |||
| 136 | // Zicsr Extension Instructions | ||
| 137 | csrrs, | ||
| 138 | |||
| 139 | // V Extension Instructions | ||
| 140 | vsetvli, | ||
| 141 | vsetivli, | ||
| 142 | vaddvv, | ||
| 143 | vfaddvv, | ||
| 144 | vsubvv, | ||
| 145 | vfsubvv, | ||
| 146 | vmulvv, | ||
| 147 | vfmulvv, | ||
| 148 | vslidedownvx, | ||
| 149 | |||
| 150 | vle8v, | ||
| 151 | vle16v, | ||
| 152 | vle32v, | ||
| 153 | vle64v, | ||
| 154 | |||
| 155 | vse8v, | ||
| 156 | vse16v, | ||
| 157 | vse32v, | ||
| 158 | vse64v, | ||
| 159 | |||
| 160 | vadcvv, | ||
| 161 | vmvvx, | ||
| 162 | |||
| 163 | // Zbb Extension Instructions | ||
| 164 | clz, | ||
| 165 | clzw, | ||
| 166 | |||
| 167 | // A Extension Instructions | ||
| 168 | fence, | ||
| 169 | fencetso, | ||
| 170 | |||
| 171 | amoswapw, | ||
| 172 | amoaddw, | ||
| 173 | amoandw, | ||
| 174 | amoorw, | ||
| 175 | amoxorw, | ||
| 176 | amomaxw, | ||
| 177 | amominw, | ||
| 178 | amomaxuw, | ||
| 179 | amominuw, | ||
| 180 | |||
| 181 | amoswapd, | ||
| 182 | amoaddd, | ||
| 183 | amoandd, | ||
| 184 | amoord, | ||
| 185 | amoxord, | ||
| 186 | amomaxd, | ||
| 187 | amomind, | ||
| 188 | amomaxud, | ||
| 189 | amominud, | ||
| 190 | |||
| 191 | // Pseudo-instructions. Used for anything that isn't 1:1 with an | ||
| 192 | // assembly instruction. | ||
| 193 | |||
| 194 | /// Pseudo-instruction that will generate a backpatched | ||
| 195 | /// function prologue. | ||
| 196 | pseudo_prologue, | ||
| 197 | /// Pseudo-instruction that will generate a backpatched | ||
| 198 | /// function epilogue | ||
| 199 | pseudo_epilogue, | ||
| 200 | |||
| 201 | /// Pseudo-instruction: End of prologue | ||
| 202 | pseudo_dbg_prologue_end, | ||
| 203 | /// Pseudo-instruction: Beginning of epilogue | ||
| 204 | pseudo_dbg_epilogue_begin, | ||
| 205 | /// Pseudo-instruction: Update debug line | ||
| 206 | pseudo_dbg_line_column, | ||
| 207 | |||
| 208 | /// Pseudo-instruction that loads from memory into a register. | ||
| 209 | pseudo_load_rm, | ||
| 210 | /// Pseudo-instruction that stores from a register into memory | ||
| 211 | pseudo_store_rm, | ||
| 212 | /// Pseudo-instruction that loads the address of memory into a register. | ||
| 213 | pseudo_lea_rm, | ||
| 214 | /// Jumps. Uses `inst` payload. | ||
| 215 | pseudo_j, | ||
| 216 | /// Dead inst, ignored by the emitter. | ||
| 217 | pseudo_dead, | ||
| 218 | /// Loads the address of a value that hasn't yet been allocated in memory. | ||
| 219 | pseudo_load_symbol, | ||
| 220 | |||
| 221 | /// Moves the value of rs1 to rd. | ||
| 222 | pseudo_mv, | ||
| 223 | |||
| 224 | pseudo_restore_regs, | ||
| 225 | pseudo_spill_regs, | ||
| 226 | |||
| 227 | pseudo_compare, | ||
| 228 | pseudo_not, | ||
| 229 | pseudo_extern_fn_reloc, | ||
| 230 | pseudo_fence, | ||
| 231 | pseudo_amo, | ||
| 232 | }; | ||
src/link/riscv.zig+7-33| ... | @@ -25,47 +25,27 @@ pub fn writeAddend( | ... | @@ -25,47 +25,27 @@ pub fn writeAddend( |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | pub fn writeInstU(code: *[4]u8, value: u32) void { | 27 | pub fn writeInstU(code: *[4]u8, value: u32) void { |
| 28 | var data = Encoding.Data{ | 28 | var data: Instruction = .{ .U = mem.bytesToValue(std.meta.TagPayload(Instruction, .U), code) }; |
| 29 | .U = mem.bytesToValue(std.meta.TagPayload( | ||
| 30 | Encoding.Data, | ||
| 31 | Encoding.Data.U, | ||
| 32 | ), code), | ||
| 33 | }; | ||
| 34 | const compensated: u32 = @bitCast(@as(i32, @bitCast(value)) + 0x800); | 29 | const compensated: u32 = @bitCast(@as(i32, @bitCast(value)) + 0x800); |
| 35 | data.U.imm12_31 = bitSlice(compensated, 31, 12); | 30 | data.U.imm12_31 = bitSlice(compensated, 31, 12); |
| 36 | mem.writeInt(u32, code, data.toU32(), .little); | 31 | mem.writeInt(u32, code, data.toU32(), .little); |
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | pub fn writeInstI(code: *[4]u8, value: u32) void { | 34 | pub fn writeInstI(code: *[4]u8, value: u32) void { |
| 40 | var data = Encoding.Data{ | 35 | var data: Instruction = .{ .I = mem.bytesToValue(std.meta.TagPayload(Instruction, .I), code) }; |
| 41 | .I = mem.bytesToValue(std.meta.TagPayload( | ||
| 42 | Encoding.Data, | ||
| 43 | Encoding.Data.I, | ||
| 44 | ), code), | ||
| 45 | }; | ||
| 46 | data.I.imm0_11 = bitSlice(value, 11, 0); | 36 | data.I.imm0_11 = bitSlice(value, 11, 0); |
| 47 | mem.writeInt(u32, code, data.toU32(), .little); | 37 | mem.writeInt(u32, code, data.toU32(), .little); |
| 48 | } | 38 | } |
| 49 | 39 | ||
| 50 | pub fn writeInstS(code: *[4]u8, value: u32) void { | 40 | pub fn writeInstS(code: *[4]u8, value: u32) void { |
| 51 | var data = Encoding.Data{ | 41 | var data: Instruction = .{ .S = mem.bytesToValue(std.meta.TagPayload(Instruction, .S), code) }; |
| 52 | .S = mem.bytesToValue(std.meta.TagPayload( | ||
| 53 | Encoding.Data, | ||
| 54 | Encoding.Data.S, | ||
| 55 | ), code), | ||
| 56 | }; | ||
| 57 | data.S.imm0_4 = bitSlice(value, 4, 0); | 42 | data.S.imm0_4 = bitSlice(value, 4, 0); |
| 58 | data.S.imm5_11 = bitSlice(value, 11, 5); | 43 | data.S.imm5_11 = bitSlice(value, 11, 5); |
| 59 | mem.writeInt(u32, code, data.toU32(), .little); | 44 | mem.writeInt(u32, code, data.toU32(), .little); |
| 60 | } | 45 | } |
| 61 | 46 | ||
| 62 | pub fn writeInstJ(code: *[4]u8, value: u32) void { | 47 | pub fn writeInstJ(code: *[4]u8, value: u32) void { |
| 63 | var data = Encoding.Data{ | 48 | var data: Instruction = .{ .J = mem.bytesToValue(std.meta.TagPayload(Instruction, .J), code) }; |
| 64 | .J = mem.bytesToValue(std.meta.TagPayload( | ||
| 65 | Encoding.Data, | ||
| 66 | Encoding.Data.J, | ||
| 67 | ), code), | ||
| 68 | }; | ||
| 69 | data.J.imm1_10 = bitSlice(value, 10, 1); | 49 | data.J.imm1_10 = bitSlice(value, 10, 1); |
| 70 | data.J.imm11 = bitSlice(value, 11, 11); | 50 | data.J.imm11 = bitSlice(value, 11, 11); |
| 71 | data.J.imm12_19 = bitSlice(value, 19, 12); | 51 | data.J.imm12_19 = bitSlice(value, 19, 12); |
| ... | @@ -74,12 +54,7 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void { | ... | @@ -74,12 +54,7 @@ pub fn writeInstJ(code: *[4]u8, value: u32) void { |
| 74 | } | 54 | } |
| 75 | 55 | ||
| 76 | pub fn writeInstB(code: *[4]u8, value: u32) void { | 56 | pub fn writeInstB(code: *[4]u8, value: u32) void { |
| 77 | var data = Encoding.Data{ | 57 | var data: Instruction = .{ .B = mem.bytesToValue(std.meta.TagPayload(Instruction, .B), code) }; |
| 78 | .B = mem.bytesToValue(std.meta.TagPayload( | ||
| 79 | Encoding.Data, | ||
| 80 | Encoding.Data.B, | ||
| 81 | ), code), | ||
| 82 | }; | ||
| 83 | data.B.imm1_4 = bitSlice(value, 4, 1); | 58 | data.B.imm1_4 = bitSlice(value, 4, 1); |
| 84 | data.B.imm5_10 = bitSlice(value, 10, 5); | 59 | data.B.imm5_10 = bitSlice(value, 10, 5); |
| 85 | data.B.imm11 = bitSlice(value, 11, 11); | 60 | data.B.imm11 = bitSlice(value, 11, 11); |
| ... | @@ -109,9 +84,8 @@ pub const RiscvEflags = packed struct(u32) { | ... | @@ -109,9 +84,8 @@ pub const RiscvEflags = packed struct(u32) { |
| 109 | _unused: u8, | 84 | _unused: u8, |
| 110 | }; | 85 | }; |
| 111 | 86 | ||
| 112 | const encoder = @import("../arch/riscv64/encoder.zig"); | ||
| 113 | const Encoding = @import("../arch/riscv64/Encoding.zig"); | ||
| 114 | const mem = std.mem; | 87 | const mem = std.mem; |
| 115 | const std = @import("std"); | 88 | const std = @import("std"); |
| 116 | 89 | ||
| 117 | pub const Instruction = encoder.Instruction; | 90 | const encoding = @import("../arch/riscv64/encoding.zig"); |
| 91 | const Instruction = encoding.Instruction; |
test/behavior/align.zig-1| ... | @@ -510,7 +510,6 @@ test "read 128-bit field from default aligned struct in global memory" { | ... | @@ -510,7 +510,6 @@ test "read 128-bit field from default aligned struct in global memory" { |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | test "struct field explicit alignment" { | 512 | test "struct field explicit alignment" { |
| 513 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | ||
| 514 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 513 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 515 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 514 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 516 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 515 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/byteswap.zig+1| ... | @@ -100,6 +100,7 @@ test "@byteSwap vectors u8" { | ... | @@ -100,6 +100,7 @@ test "@byteSwap vectors u8" { |
| 100 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 100 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 101 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 101 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 102 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 102 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 103 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 103 | 104 | ||
| 104 | try comptime vector8(); | 105 | try comptime vector8(); |
| 105 | try vector8(); | 106 | try vector8(); |
test/behavior/defer.zig+2| ... | @@ -116,6 +116,7 @@ test "errdefer with payload" { | ... | @@ -116,6 +116,7 @@ test "errdefer with payload" { |
| 116 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 116 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 117 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 117 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 118 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 118 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 119 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 119 | 120 | ||
| 120 | const S = struct { | 121 | const S = struct { |
| 121 | fn foo() !i32 { | 122 | fn foo() !i32 { |
| ... | @@ -138,6 +139,7 @@ test "reference to errdefer payload" { | ... | @@ -138,6 +139,7 @@ test "reference to errdefer payload" { |
| 138 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 139 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 139 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 140 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 140 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO | 141 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO |
| 142 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 141 | 143 | ||
| 142 | const S = struct { | 144 | const S = struct { |
| 143 | fn foo() !i32 { | 145 | fn foo() !i32 { |
test/behavior/optional.zig+1| ... | @@ -591,6 +591,7 @@ test "cast slice to const slice nested in error union and optional" { | ... | @@ -591,6 +591,7 @@ test "cast slice to const slice nested in error union and optional" { |
| 591 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 591 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 592 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 592 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 593 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 593 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 594 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 594 | 595 | ||
| 595 | const S = struct { | 596 | const S = struct { |
| 596 | fn inner() !?[]u8 { | 597 | fn inner() !?[]u8 { |
test/behavior/pointers.zig+1| ... | @@ -228,6 +228,7 @@ test "implicit cast error unions with non-optional to optional pointer" { | ... | @@ -228,6 +228,7 @@ test "implicit cast error unions with non-optional to optional pointer" { |
| 228 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 228 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 229 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 229 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 230 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 230 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 231 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 231 | 232 | ||
| 232 | const S = struct { | 233 | const S = struct { |
| 233 | fn doTheTest() !void { | 234 | fn doTheTest() !void { |
test/behavior/switch.zig+2| ... | @@ -427,6 +427,7 @@ test "else prong of switch on error set excludes other cases" { | ... | @@ -427,6 +427,7 @@ test "else prong of switch on error set excludes other cases" { |
| 427 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 427 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 428 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 428 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 429 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 429 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 430 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 430 | 431 | ||
| 431 | const S = struct { | 432 | const S = struct { |
| 432 | fn doTheTest() !void { | 433 | fn doTheTest() !void { |
| ... | @@ -462,6 +463,7 @@ test "switch prongs with error set cases make a new error set type for capture v | ... | @@ -462,6 +463,7 @@ test "switch prongs with error set cases make a new error set type for capture v |
| 462 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 463 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 463 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 464 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 464 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 465 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 466 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 465 | 467 | ||
| 466 | const S = struct { | 468 | const S = struct { |
| 467 | fn doTheTest() !void { | 469 | fn doTheTest() !void { |
test/behavior/try.zig+1| ... | @@ -51,6 +51,7 @@ test "`try`ing an if/else expression" { | ... | @@ -51,6 +51,7 @@ test "`try`ing an if/else expression" { |
| 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 52 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 52 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 53 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 53 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 54 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 54 | 55 | ||
| 55 | const S = struct { | 56 | const S = struct { |
| 56 | fn getError() !void { | 57 | fn getError() !void { |