| ... | @@ -25,6 +25,7 @@ const Type = @import("../../type.zig").Type; | ... | @@ -25,6 +25,7 @@ const Type = @import("../../type.zig").Type; |
| 25 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; | 25 | const fmtIntSizeBin = std.fmt.fmtIntSizeBin; |
| 26 | | 26 | |
| 27 | mir: Mir, | 27 | mir: Mir, |
| | 28 | bin_file: *link.File, |
| 28 | | 29 | |
| 29 | pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index), air: Air) !void { | 30 | pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap(Mir.Inst.Index, Air.Inst.Index), air: Air) !void { |
| 30 | const instruction_bytes = print.mir.instructions.len * | 31 | const instruction_bytes = print.mir.instructions.len * |
| ... | @@ -116,15 +117,15 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap | ... | @@ -116,15 +117,15 @@ pub fn printMir(print: *const Print, w: anytype, mir_to_air_map: std.AutoHashMap |
| 116 | .jmp => try print.mirJmpCall(.jmp, inst, w), | 117 | .jmp => try print.mirJmpCall(.jmp, inst, w), |
| 117 | .call => try print.mirJmpCall(.call, inst, w), | 118 | .call => try print.mirJmpCall(.call, inst, w), |
| 118 | | 119 | |
| 119 | // .cond_jmp_greater_less => try print.mirCondJmp(.cond_jmp_greater_less, inst, w), | 120 | .cond_jmp_greater_less => try print.mirCondJmp(.cond_jmp_greater_less, inst, w), |
| 120 | // .cond_jmp_above_below => try print.mirCondJmp(.cond_jmp_above_below, inst, w), | 121 | .cond_jmp_above_below => try print.mirCondJmp(.cond_jmp_above_below, inst, w), |
| 121 | // .cond_jmp_eq_ne => try print.mirCondJmp(.cond_jmp_eq_ne, inst, w), | 122 | .cond_jmp_eq_ne => try print.mirCondJmp(.cond_jmp_eq_ne, inst, w), |
| 122 | | 123 | |
| 123 | // .cond_set_byte_greater_less => try print.mirCondSetByte(.cond_set_byte_greater_less, inst, w), | 124 | .cond_set_byte_greater_less => try print.mirCondSetByte(.cond_set_byte_greater_less, inst, w), |
| 124 | // .cond_set_byte_above_below => try print.mirCondSetByte(.cond_set_byte_above_below, inst, w), | 125 | .cond_set_byte_above_below => try print.mirCondSetByte(.cond_set_byte_above_below, inst, w), |
| 125 | // .cond_set_byte_eq_ne => try print.mirCondSetByte(.cond_set_byte_eq_ne, inst, w), | 126 | .cond_set_byte_eq_ne => try print.mirCondSetByte(.cond_set_byte_eq_ne, inst, w), |
| 126 | | 127 | |
| 127 | // .@"test" => try print.mirTest(inst, w), | 128 | .@"test" => try print.mirTest(inst, w), |
| 128 | | 129 | |
| 129 | .brk => try w.writeAll("brk\n"), | 130 | .brk => try w.writeAll("brk\n"), |
| 130 | .ret => try w.writeAll("ret\n"), | 131 | .ret => try w.writeAll("ret\n"), |
| ... | @@ -209,254 +210,24 @@ fn mirJmpCall(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: a | ... | @@ -209,254 +210,24 @@ fn mirJmpCall(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: a |
| 209 | try w.print("{s}\n", .{@tagName(ops.reg1)}); | 210 | try w.print("{s}\n", .{@tagName(ops.reg1)}); |
| 210 | } | 211 | } |
| 211 | | 212 | |
| 212 | const CondType = enum { | | |
| 213 | /// greater than or equal | | |
| 214 | gte, | | |
| 215 | | | |
| 216 | /// greater than | | |
| 217 | gt, | | |
| 218 | | | |
| 219 | /// less than | | |
| 220 | lt, | | |
| 221 | | | |
| 222 | /// less than or equal | | |
| 223 | lte, | | |
| 224 | | | |
| 225 | /// above or equal | | |
| 226 | ae, | | |
| 227 | | | |
| 228 | /// above | | |
| 229 | a, | | |
| 230 | | | |
| 231 | /// below | | |
| 232 | b, | | |
| 233 | | | |
| 234 | /// below or equal | | |
| 235 | be, | | |
| 236 | | | |
| 237 | /// not equal | | |
| 238 | ne, | | |
| 239 | | | |
| 240 | /// equal | | |
| 241 | eq, | | |
| 242 | | | |
| 243 | fn fromTagAndFlags(tag: Mir.Inst.Tag, flags: u2) CondType { | | |
| 244 | return switch (tag) { | | |
| 245 | .cond_jmp_greater_less, | | |
| 246 | .cond_set_byte_greater_less, | | |
| 247 | => switch (flags) { | | |
| 248 | 0b00 => CondType.gte, | | |
| 249 | 0b01 => CondType.gt, | | |
| 250 | 0b10 => CondType.lt, | | |
| 251 | 0b11 => CondType.lte, | | |
| 252 | }, | | |
| 253 | .cond_jmp_above_below, | | |
| 254 | .cond_set_byte_above_below, | | |
| 255 | => switch (flags) { | | |
| 256 | 0b00 => CondType.ae, | | |
| 257 | 0b01 => CondType.a, | | |
| 258 | 0b10 => CondType.b, | | |
| 259 | 0b11 => CondType.be, | | |
| 260 | }, | | |
| 261 | .cond_jmp_eq_ne, | | |
| 262 | .cond_set_byte_eq_ne, | | |
| 263 | => switch (@truncate(u1, flags)) { | | |
| 264 | 0b0 => CondType.ne, | | |
| 265 | 0b1 => CondType.eq, | | |
| 266 | }, | | |
| 267 | else => unreachable, | | |
| 268 | }; | | |
| 269 | } | | |
| 270 | }; | | |
| 271 | | | |
| 272 | inline fn getCondOpCode(tag: Mir.Inst.Tag, cond: CondType) u8 { | | |
| 273 | switch (cond) { | | |
| 274 | .gte => return switch (tag) { | | |
| 275 | .cond_jmp_greater_less => 0x8d, | | |
| 276 | .cond_set_byte_greater_less => 0x9d, | | |
| 277 | else => unreachable, | | |
| 278 | }, | | |
| 279 | .gt => return switch (tag) { | | |
| 280 | .cond_jmp_greater_less => 0x8f, | | |
| 281 | .cond_set_byte_greater_less => 0x9f, | | |
| 282 | else => unreachable, | | |
| 283 | }, | | |
| 284 | .lt => return switch (tag) { | | |
| 285 | .cond_jmp_greater_less => 0x8c, | | |
| 286 | .cond_set_byte_greater_less => 0x9c, | | |
| 287 | else => unreachable, | | |
| 288 | }, | | |
| 289 | .lte => return switch (tag) { | | |
| 290 | .cond_jmp_greater_less => 0x8e, | | |
| 291 | .cond_set_byte_greater_less => 0x9e, | | |
| 292 | else => unreachable, | | |
| 293 | }, | | |
| 294 | .ae => return switch (tag) { | | |
| 295 | .cond_jmp_above_below => 0x83, | | |
| 296 | .cond_set_byte_above_below => 0x93, | | |
| 297 | else => unreachable, | | |
| 298 | }, | | |
| 299 | .a => return switch (tag) { | | |
| 300 | .cond_jmp_above_below => 0x87, | | |
| 301 | .cond_set_byte_greater_less => 0x97, | | |
| 302 | else => unreachable, | | |
| 303 | }, | | |
| 304 | .b => return switch (tag) { | | |
| 305 | .cond_jmp_above_below => 0x82, | | |
| 306 | .cond_set_byte_greater_less => 0x92, | | |
| 307 | else => unreachable, | | |
| 308 | }, | | |
| 309 | .be => return switch (tag) { | | |
| 310 | .cond_jmp_above_below => 0x86, | | |
| 311 | .cond_set_byte_greater_less => 0x96, | | |
| 312 | else => unreachable, | | |
| 313 | }, | | |
| 314 | .eq => return switch (tag) { | | |
| 315 | .cond_jmp_eq_ne => 0x84, | | |
| 316 | .cond_set_byte_eq_ne => 0x94, | | |
| 317 | else => unreachable, | | |
| 318 | }, | | |
| 319 | .ne => return switch (tag) { | | |
| 320 | .cond_jmp_eq_ne => 0x85, | | |
| 321 | .cond_set_byte_eq_ne => 0x95, | | |
| 322 | else => unreachable, | | |
| 323 | }, | | |
| 324 | } | | |
| 325 | } | | |
| 326 | | | |
| 327 | fn mirCondJmp(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { | 213 | fn mirCondJmp(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { |
| 328 | _ = w; // TODO | 214 | _ = print; |
| 329 | const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); | 215 | _ = tag; |
| 330 | const target = print.mir.instructions.items(.data)[inst].inst; | 216 | _ = inst; |
| 331 | const cond = CondType.fromTagAndFlags(tag, ops.flags); | 217 | try w.writeAll("TODO print mirCondJmp\n"); |
| 332 | const opc = getCondOpCode(tag, cond); | | |
| 333 | const source = print.code.items.len; | | |
| 334 | const encoder = try Encoder.init(print.code, 6); | | |
| 335 | encoder.opcode_2byte(0x0f, opc); | | |
| 336 | try print.relocs.append(print.bin_file.allocator, .{ | | |
| 337 | .source = source, | | |
| 338 | .target = target, | | |
| 339 | .offset = print.code.items.len, | | |
| 340 | .length = 6, | | |
| 341 | }); | | |
| 342 | encoder.imm32(0); | | |
| 343 | } | 218 | } |
| 344 | | 219 | |
| 345 | fn mirCondSetByte(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { | 220 | fn mirCondSetByte(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { |
| 346 | _ = w; // TODO | 221 | _ = tag; |
| 347 | const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); | 222 | _ = inst; |
| 348 | const cond = CondType.fromTagAndFlags(tag, ops.flags); | 223 | _ = print; |
| 349 | const opc = getCondOpCode(tag, cond); | 224 | try w.writeAll("TODO print mirCondSetByte\n"); |
| 350 | const encoder = try Encoder.init(print.code, 4); | | |
| 351 | encoder.rex(.{ | | |
| 352 | .w = true, | | |
| 353 | .b = ops.reg1.isExtended(), | | |
| 354 | }); | | |
| 355 | encoder.opcode_2byte(0x0f, opc); | | |
| 356 | encoder.modRm_direct(0x0, ops.reg1.lowId()); | | |
| 357 | } | 225 | } |
| 358 | | 226 | |
| 359 | fn mirTest(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { | 227 | fn mirTest(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { |
| 360 | _ = w; // TODO | 228 | _ = print; |
| 361 | const tag = print.mir.instructions.items(.tag)[inst]; | 229 | _ = inst; |
| 362 | assert(tag == .@"test"); | 230 | try w.writeAll("TODO print mirTest\n"); |
| 363 | const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); | | |
| 364 | switch (ops.flags) { | | |
| 365 | 0b00 => blk: { | | |
| 366 | if (ops.reg2 == .none) { | | |
| 367 | // TEST r/m64, imm32 | | |
| 368 | const imm = print.mir.instructions.items(.data)[inst].imm; | | |
| 369 | if (ops.reg1.to64() == .rax) { | | |
| 370 | // TODO reduce the size of the instruction if the immediate | | |
| 371 | // is smaller than 32 bits | | |
| 372 | const encoder = try Encoder.init(print.code, 6); | | |
| 373 | encoder.rex(.{ | | |
| 374 | .w = true, | | |
| 375 | }); | | |
| 376 | encoder.opcode_1byte(0xa9); | | |
| 377 | encoder.imm32(imm); | | |
| 378 | break :blk; | | |
| 379 | } | | |
| 380 | const opc: u8 = if (ops.reg1.size() == 8) 0xf6 else 0xf7; | | |
| 381 | const encoder = try Encoder.init(print.code, 7); | | |
| 382 | encoder.rex(.{ | | |
| 383 | .w = true, | | |
| 384 | .b = ops.reg1.isExtended(), | | |
| 385 | }); | | |
| 386 | encoder.opcode_1byte(opc); | | |
| 387 | encoder.modRm_direct(0, ops.reg1.lowId()); | | |
| 388 | encoder.imm8(@intCast(i8, imm)); | | |
| 389 | break :blk; | | |
| 390 | } | | |
| 391 | // TEST r/m64, r64 | | |
| 392 | return print.fail("TODO TEST r/m64, r64", .{}); | | |
| 393 | }, | | |
| 394 | else => return print.fail("TODO more TEST alternatives", .{}), | | |
| 395 | } | | |
| 396 | } | | |
| 397 | | | |
| 398 | const EncType = enum { | | |
| 399 | /// OP r/m64, imm32 | | |
| 400 | mi, | | |
| 401 | | | |
| 402 | /// OP r/m64, r64 | | |
| 403 | mr, | | |
| 404 | | | |
| 405 | /// OP r64, r/m64 | | |
| 406 | rm, | | |
| 407 | }; | | |
| 408 | | | |
| 409 | const OpCode = struct { | | |
| 410 | opc: u8, | | |
| 411 | /// Only used if `EncType == .mi`. | | |
| 412 | modrm_ext: u3, | | |
| 413 | }; | | |
| 414 | | | |
| 415 | inline fn getArithOpCode(tag: Mir.Inst.Tag, enc: EncType) OpCode { | | |
| 416 | switch (enc) { | | |
| 417 | .mi => return switch (tag) { | | |
| 418 | .adc => .{ .opc = 0x81, .modrm_ext = 0x2 }, | | |
| 419 | .add => .{ .opc = 0x81, .modrm_ext = 0x0 }, | | |
| 420 | .sub => .{ .opc = 0x81, .modrm_ext = 0x5 }, | | |
| 421 | .xor => .{ .opc = 0x81, .modrm_ext = 0x6 }, | | |
| 422 | .@"and" => .{ .opc = 0x81, .modrm_ext = 0x4 }, | | |
| 423 | .@"or" => .{ .opc = 0x81, .modrm_ext = 0x1 }, | | |
| 424 | .sbb => .{ .opc = 0x81, .modrm_ext = 0x3 }, | | |
| 425 | .cmp => .{ .opc = 0x81, .modrm_ext = 0x7 }, | | |
| 426 | .mov => .{ .opc = 0xc7, .modrm_ext = 0x0 }, | | |
| 427 | else => unreachable, | | |
| 428 | }, | | |
| 429 | .mr => { | | |
| 430 | const opc: u8 = switch (tag) { | | |
| 431 | .adc => 0x11, | | |
| 432 | .add => 0x01, | | |
| 433 | .sub => 0x29, | | |
| 434 | .xor => 0x31, | | |
| 435 | .@"and" => 0x21, | | |
| 436 | .@"or" => 0x09, | | |
| 437 | .sbb => 0x19, | | |
| 438 | .cmp => 0x39, | | |
| 439 | .mov => 0x89, | | |
| 440 | else => unreachable, | | |
| 441 | }; | | |
| 442 | return .{ .opc = opc, .modrm_ext = undefined }; | | |
| 443 | }, | | |
| 444 | .rm => { | | |
| 445 | const opc: u8 = switch (tag) { | | |
| 446 | .adc => 0x13, | | |
| 447 | .add => 0x03, | | |
| 448 | .sub => 0x2b, | | |
| 449 | .xor => 0x33, | | |
| 450 | .@"and" => 0x23, | | |
| 451 | .@"or" => 0x0b, | | |
| 452 | .sbb => 0x1b, | | |
| 453 | .cmp => 0x3b, | | |
| 454 | .mov => 0x8b, | | |
| 455 | else => unreachable, | | |
| 456 | }; | | |
| 457 | return .{ .opc = opc, .modrm_ext = undefined }; | | |
| 458 | }, | | |
| 459 | } | | |
| 460 | } | 231 | } |
| 461 | | 232 | |
| 462 | fn mirArith(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { | 233 | fn mirArith(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { |
| ... | @@ -473,36 +244,61 @@ fn mirArith(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: any | ... | @@ -473,36 +244,61 @@ fn mirArith(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: any |
| 473 | 0b01 => { | 244 | 0b01 => { |
| 474 | const imm = print.mir.instructions.items(.data)[inst].imm; | 245 | const imm = print.mir.instructions.items(.data)[inst].imm; |
| 475 | if (ops.reg2 == .none) { | 246 | if (ops.reg2 == .none) { |
| 476 | try w.print("{s}, [ds:{d}]", .{ @tagName(ops.reg1), imm }); | 247 | try w.print("{s}, ", .{@tagName(ops.reg1)}); |
| | 248 | switch (ops.reg1.size()) { |
| | 249 | 8 => try w.print("byte ptr ", .{}), |
| | 250 | 16 => try w.print("word ptr ", .{}), |
| | 251 | 32 => try w.print("dword ptr ", .{}), |
| | 252 | 64 => try w.print("qword ptr ", .{}), |
| | 253 | else => unreachable, |
| | 254 | } |
| | 255 | try w.print("[ds:{d}]", .{imm}); |
| 477 | } else { | 256 | } else { |
| 478 | try w.print("{s}, [{s} + {d}]", .{ @tagName(ops.reg1), @tagName(ops.reg2), imm }); | 257 | try w.print("{s}, ", .{@tagName(ops.reg1)}); |
| | 258 | switch (ops.reg1.size()) { |
| | 259 | 8 => try w.print("byte ptr ", .{}), |
| | 260 | 16 => try w.print("word ptr ", .{}), |
| | 261 | 32 => try w.print("dword ptr ", .{}), |
| | 262 | 64 => try w.print("qword ptr ", .{}), |
| | 263 | else => unreachable, |
| | 264 | } |
| | 265 | try w.print("[{s} + {d}]", .{ @tagName(ops.reg2), imm }); |
| 479 | } | 266 | } |
| 480 | }, | 267 | }, |
| 481 | 0b10 => { | 268 | 0b10 => { |
| 482 | const imm = print.mir.instructions.items(.data)[inst].imm; | 269 | const imm = print.mir.instructions.items(.data)[inst].imm; |
| 483 | if (ops.reg2 == .none) { | 270 | if (ops.reg2 == .none) { |
| 484 | try w.print("[{s} + 0], {d}", .{ @tagName(ops.reg1), imm }); | 271 | try w.writeAll("unused variant"); |
| 485 | } else { | 272 | } else { |
| | 273 | switch (ops.reg2.size()) { |
| | 274 | 8 => try w.print("byte ptr ", .{}), |
| | 275 | 16 => try w.print("word ptr ", .{}), |
| | 276 | 32 => try w.print("dword ptr ", .{}), |
| | 277 | 64 => try w.print("qword ptr ", .{}), |
| | 278 | else => unreachable, |
| | 279 | } |
| 486 | try w.print("[{s} + {d}], {s}", .{ @tagName(ops.reg1), imm, @tagName(ops.reg2) }); | 280 | try w.print("[{s} + {d}], {s}", .{ @tagName(ops.reg1), imm, @tagName(ops.reg2) }); |
| 487 | } | 281 | } |
| 488 | }, | 282 | }, |
| 489 | 0b11 => { | 283 | 0b11 => { |
| 490 | if (ops.reg2 == .none) { | 284 | try w.writeAll("unused variant"); |
| 491 | const payload = print.mir.instructions.items(.data)[inst].payload; | | |
| 492 | const imm_pair = print.mir.extraData(Mir.ImmPair, payload).data; | | |
| 493 | try w.print("[{s} + {d}], {d}", .{ @tagName(ops.reg1), imm_pair.dest_off, imm_pair.operand }); | | |
| 494 | } | | |
| 495 | try w.writeAll("TODO"); | | |
| 496 | }, | 285 | }, |
| 497 | } | 286 | } |
| 498 | try w.writeByte('\n'); | 287 | try w.writeByte('\n'); |
| 499 | } | 288 | } |
| 500 | | 289 | |
| 501 | fn mirArithMemImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { | 290 | fn mirArithMemImm(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { |
| 502 | _ = print; | 291 | const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); |
| 503 | _ = tag; | 292 | const payload = print.mir.instructions.items(.data)[inst].payload; |
| 504 | _ = inst; | 293 | const imm_pair = print.mir.extraData(Mir.ImmPair, payload).data; |
| 505 | return w.writeAll("TODO mirArithMemImm\n"); | 294 | try w.print("{s} ", .{@tagName(tag)}); |
| | 295 | switch (ops.flags) { |
| | 296 | 0b00 => try w.print("byte ptr ", .{}), |
| | 297 | 0b01 => try w.print("word ptr ", .{}), |
| | 298 | 0b10 => try w.print("dword ptr ", .{}), |
| | 299 | 0b11 => try w.print("qword ptr ", .{}), |
| | 300 | } |
| | 301 | try w.print("[{s} + {d}], {d}\n", .{ @tagName(ops.reg1), imm_pair.dest_off, imm_pair.operand }); |
| 506 | } | 302 | } |
| 507 | | 303 | |
| 508 | fn mirArithScaleSrc(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { | 304 | fn mirArithScaleSrc(print: *const Print, tag: Mir.Inst.Tag, inst: Mir.Inst.Index, w: anytype) !void { |
| ... | @@ -575,16 +371,57 @@ fn mirIMulComplex(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { | ... | @@ -575,16 +371,57 @@ fn mirIMulComplex(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { |
| 575 | } | 371 | } |
| 576 | | 372 | |
| 577 | fn mirLea(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { | 373 | fn mirLea(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { |
| 578 | _ = print; | 374 | const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); |
| 579 | _ = inst; | 375 | try w.writeAll("lea "); |
| 580 | return w.writeAll("TODO lea\n"); | 376 | switch (ops.flags) { |
| 581 | // const tag = print.mir.instructions.items(.tag)[inst]; | 377 | 0b00 => { |
| 582 | // assert(tag == .lea); | 378 | const imm = print.mir.instructions.items(.data)[inst].imm; |
| 583 | // const ops = Mir.Ops.decode(print.mir.instructions.items(.ops)[inst]); | 379 | try w.print("{s} [", .{@tagName(ops.reg1)}); |
| 584 | // assert(ops.flags == 0b01); | 380 | if (ops.reg2 != .none) { |
| 585 | // const imm = print.mir.instructions.items(.data)[inst].imm; | 381 | try w.print("{s} + ", .{@tagName(ops.reg2)}); |
| 586 | | 382 | } else { |
| 587 | // try w.print("lea {s} [{s} + {d}]\n", .{ @tagName(ops.reg1), @tagName(ops.reg2), imm }); | 383 | try w.print("ds:", .{}); |
| | 384 | } |
| | 385 | try w.print("{d}]\n", .{imm}); |
| | 386 | }, |
| | 387 | 0b01 => { |
| | 388 | try w.print("{s}, ", .{@tagName(ops.reg1)}); |
| | 389 | switch (ops.reg1.size()) { |
| | 390 | 8 => try w.print("byte ptr ", .{}), |
| | 391 | 16 => try w.print("word ptr ", .{}), |
| | 392 | 32 => try w.print("dword ptr ", .{}), |
| | 393 | 64 => try w.print("qword ptr ", .{}), |
| | 394 | else => unreachable, |
| | 395 | } |
| | 396 | try w.print("[rip + 0x0] ", .{}); |
| | 397 | const payload = print.mir.instructions.items(.data)[inst].payload; |
| | 398 | const imm = print.mir.extraData(Mir.Imm64, payload).data.decode(); |
| | 399 | try w.print("target@{x}", .{imm}); |
| | 400 | }, |
| | 401 | 0b10 => { |
| | 402 | try w.print("{s}, ", .{@tagName(ops.reg1)}); |
| | 403 | switch (ops.reg1.size()) { |
| | 404 | 8 => try w.print("byte ptr ", .{}), |
| | 405 | 16 => try w.print("word ptr ", .{}), |
| | 406 | 32 => try w.print("dword ptr ", .{}), |
| | 407 | 64 => try w.print("qword ptr ", .{}), |
| | 408 | else => unreachable, |
| | 409 | } |
| | 410 | try w.print("[rip + 0x0] ", .{}); |
| | 411 | const got_entry = print.mir.instructions.items(.data)[inst].got_entry; |
| | 412 | if (print.bin_file.cast(link.File.MachO)) |macho_file| { |
| | 413 | const target = macho_file.locals.items[got_entry]; |
| | 414 | const target_name = macho_file.getString(target.n_strx); |
| | 415 | try w.print("target@{s}", .{target_name}); |
| | 416 | } else { |
| | 417 | try w.writeAll("TODO lea reg, [rip + reloc] for linking backends different than MachO"); |
| | 418 | } |
| | 419 | }, |
| | 420 | 0b11 => { |
| | 421 | try w.writeAll("unused variant\n"); |
| | 422 | }, |
| | 423 | } |
| | 424 | try w.writeAll("\n"); |
| 588 | } | 425 | } |
| 589 | | 426 | |
| 590 | fn mirCallExtern(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { | 427 | fn mirCallExtern(print: *const Print, inst: Mir.Inst.Index, w: anytype) !void { |