| author | |
| committer | |
| log | 7221cd8ec90b5f206cf0b2979ba165719e5a2f23 |
| tree | 5bedc30933986fb1e8216769657a4068c1b75e28 |
| parent | f61a70e812b0301f4e54e38ff4ce2b041f395e8d |
3 files changed, 94 insertions(+), 165 deletions(-)
src/arch/x86_64/CodeGen.zig+31-60| ... | ... | @@ -400,6 +400,29 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 400 | 400 | return result; |
| 401 | 401 | } |
| 402 | 402 | |
| 403 | fn asmSetCCRegister(self: *Self, reg: Register, cc: bits.Condition) !void { | |
| 404 | _ = try self.addInst(.{ | |
| 405 | .tag = .setcc, | |
| 406 | .ops = .r_c, | |
| 407 | .data = .{ .r_c = .{ | |
| 408 | .r1 = reg, | |
| 409 | .cc = cc, | |
| 410 | } }, | |
| 411 | }); | |
| 412 | } | |
| 413 | ||
| 414 | fn asmCmovCCRegisterRegister(self: *Self, reg1: Register, reg2: Register, cc: bits.Condition) !void { | |
| 415 | _ = try self.addInst(.{ | |
| 416 | .tag = .cmovcc, | |
| 417 | .ops = .rr_c, | |
| 418 | .data = .{ .rr_c = .{ | |
| 419 | .r1 = reg1, | |
| 420 | .r2 = reg2, | |
| 421 | .cc = cc, | |
| 422 | } }, | |
| 423 | }); | |
| 424 | } | |
| 425 | ||
| 403 | 426 | fn asmNone(self: *Self, tag: Mir.Inst.Tag) !void { |
| 404 | 427 | _ = try self.addInst(.{ |
| 405 | 428 | .tag = tag, |
| ... | ... | @@ -1346,15 +1369,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void { |
| 1346 | 1369 | .unsigned => .b, |
| 1347 | 1370 | .signed => .l, |
| 1348 | 1371 | }; |
| 1349 | _ = cc; | |
| 1350 | // _ = try self.addInst(.{ | |
| 1351 | // .tag = .cond_mov, | |
| 1352 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 1353 | // .reg1 = dst_mcv.register, | |
| 1354 | // .reg2 = lhs_reg, | |
| 1355 | // }), | |
| 1356 | // .data = .{ .cc = cc }, | |
| 1357 | // }); | |
| 1372 | try self.asmCmovCCRegisterRegister(dst_mcv.register, lhs_reg, cc); | |
| 1358 | 1373 | |
| 1359 | 1374 | break :result dst_mcv; |
| 1360 | 1375 | }; |
| ... | ... | @@ -1554,14 +1569,7 @@ fn genSetStackTruncatedOverflowCompare( |
| 1554 | 1569 | .signed => .o, |
| 1555 | 1570 | .unsigned => .c, |
| 1556 | 1571 | }; |
| 1557 | _ = cc; | |
| 1558 | // _ = try self.addInst(.{ | |
| 1559 | // .tag = .cond_set_byte, | |
| 1560 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 1561 | // .reg1 = overflow_reg.to8(), | |
| 1562 | // }), | |
| 1563 | // .data = .{ .cc = cc }, | |
| 1564 | // }); | |
| 1572 | try self.asmSetCCRegister(overflow_reg.to8(), cc); | |
| 1565 | 1573 | |
| 1566 | 1574 | const scratch_reg = temp_regs[1]; |
| 1567 | 1575 | try self.genSetReg(extended_ty, scratch_reg, .{ .register = reg }); |
| ... | ... | @@ -1574,12 +1582,7 @@ fn genSetStackTruncatedOverflowCompare( |
| 1574 | 1582 | ); |
| 1575 | 1583 | |
| 1576 | 1584 | const eq_reg = temp_regs[2]; |
| 1577 | // _ = try self.addInst(.{ | |
| 1578 | // .tag = .cond_set_byte, | |
| 1579 | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = eq_reg.to8() }), | |
| 1580 | // .data = .{ .cc = .ne }, | |
| 1581 | // }); | |
| 1582 | ||
| 1585 | try self.asmSetCCRegister(eq_reg.to8(), .ne); | |
| 1583 | 1586 | try self.genBinOpMir( |
| 1584 | 1587 | .@"or", |
| 1585 | 1588 | Type.u8, |
| ... | ... | @@ -1829,14 +1832,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa |
| 1829 | 1832 | // }), |
| 1830 | 1833 | // .data = undefined, |
| 1831 | 1834 | // }); |
| 1832 | // _ = try self.addInst(.{ | |
| 1833 | // .tag = .cond_mov, | |
| 1834 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 1835 | // .reg1 = divisor.to64(), | |
| 1836 | // .reg2 = .rdx, | |
| 1837 | // }), | |
| 1838 | // .data = .{ .cc = .e }, | |
| 1839 | // }); | |
| 1835 | try self.asmCmovCCRegisterRegister(divisor.to64(), .rdx, .e); | |
| 1840 | 1836 | try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax }); |
| 1841 | 1837 | return MCValue{ .register = divisor }; |
| 1842 | 1838 | } |
| ... | ... | @@ -2881,13 +2877,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2881 | 2877 | const overflow_bit_ty = value_ty.structFieldType(1); |
| 2882 | 2878 | const overflow_bit_offset = value_ty.structFieldOffset(1, self.target.*); |
| 2883 | 2879 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 2884 | // _ = try self.addInst(.{ | |
| 2885 | // .tag = .cond_set_byte, | |
| 2886 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 2887 | // .reg1 = tmp_reg.to8(), | |
| 2888 | // }), | |
| 2889 | // .data = .{ .cc = ro.eflags }, | |
| 2890 | // }); | |
| 2880 | try self.asmSetCCRegister(tmp_reg.to8(), ro.eflags); | |
| 2891 | 2881 | try self.genInlineMemcpyRegisterRegister( |
| 2892 | 2882 | overflow_bit_ty, |
| 2893 | 2883 | reg, |
| ... | ... | @@ -3185,13 +3175,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3185 | 3175 | defer self.register_manager.unlockReg(reg_lock); |
| 3186 | 3176 | |
| 3187 | 3177 | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 3188 | // _ = try self.addInst(.{ | |
| 3189 | // .tag = .cond_set_byte, | |
| 3190 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 3191 | // .reg1 = dst_reg.to8(), | |
| 3192 | // }), | |
| 3193 | // .data = .{ .cc = ro.eflags }, | |
| 3194 | // }); | |
| 3178 | try self.asmSetCCRegister(dst_reg.to8(), ro.eflags); | |
| 3195 | 3179 | break :result MCValue{ .register = dst_reg.to8() }; |
| 3196 | 3180 | }, |
| 3197 | 3181 | else => unreachable, |
| ... | ... | @@ -5577,13 +5561,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5577 | 5561 | const overflow_bit_ty = ty.structFieldType(1); |
| 5578 | 5562 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); |
| 5579 | 5563 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 5580 | // _ = try self.addInst(.{ | |
| 5581 | // .tag = .cond_set_byte, | |
| 5582 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 5583 | // .reg1 = tmp_reg.to8(), | |
| 5584 | // }), | |
| 5585 | // .data = .{ .cc = ro.eflags }, | |
| 5586 | // }); | |
| 5564 | try self.asmSetCCRegister(tmp_reg.to8(), ro.eflags); | |
| 5587 | 5565 | |
| 5588 | 5566 | return self.genSetStack( |
| 5589 | 5567 | overflow_bit_ty, |
| ... | ... | @@ -6114,14 +6092,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6114 | 6092 | } |
| 6115 | 6093 | }, |
| 6116 | 6094 | .eflags => |cc| { |
| 6117 | _ = cc; | |
| 6118 | // _ = try self.addInst(.{ | |
| 6119 | // .tag = .cond_set_byte, | |
| 6120 | // .ops = Mir.Inst.Ops.encode(.{ | |
| 6121 | // .reg1 = reg.to8(), | |
| 6122 | // }), | |
| 6123 | // .data = .{ .cc = cc }, | |
| 6124 | // }); | |
| 6095 | return self.asmSetCCRegister(reg.to8(), cc); | |
| 6125 | 6096 | }, |
| 6126 | 6097 | .immediate => |x| { |
| 6127 | 6098 | if (x == 0) { |
src/arch/x86_64/Emit.zig+43-103| ... | ... | @@ -118,6 +118,9 @@ pub fn lowerMir(emit: *Emit) InnerError!void { |
| 118 | 118 | => try emit.mirEncodeGeneric(tag, inst), |
| 119 | 119 | |
| 120 | 120 | // Pseudo-instructions |
| 121 | .cmovcc => try emit.mirCmovCC(inst), | |
| 122 | .setcc => try emit.mirSetCC(inst), | |
| 123 | ||
| 121 | 124 | .dbg_line => try emit.mirDbgLine(inst), |
| 122 | 125 | .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst), |
| 123 | 126 | .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst), |
| ... | ... | @@ -200,9 +203,11 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 200 | 203 | .{ .imm = Immediate.u(data.ri_u.imm) }, |
| 201 | 204 | }, |
| 202 | 205 | .ri64 => { |
| 203 | operands[0] = .{ .reg = data.rx.r1 }; | |
| 204 | 206 | const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data; |
| 205 | operands[1] = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }; | |
| 207 | operands[0..2].* = .{ | |
| 208 | .{ .reg = data.rx.r1 }, | |
| 209 | .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }, | |
| 210 | }; | |
| 206 | 211 | }, |
| 207 | 212 | else => unreachable, |
| 208 | 213 | } |
| ... | ... | @@ -215,6 +220,42 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE |
| 215 | 220 | }); |
| 216 | 221 | } |
| 217 | 222 | |
| 223 | fn mnemonicFromCC(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic { | |
| 224 | inline for (@typeInfo(bits.Condition).Enum.fields) |field| { | |
| 225 | if (mem.eql(u8, field.name, @tagName(cc))) | |
| 226 | return @field(Instruction.Mnemonic, basename ++ field.name); | |
| 227 | } else unreachable; | |
| 228 | } | |
| 229 | ||
| 230 | fn mirCmovCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | |
| 231 | const ops = emit.mir.instructions.items(.ops)[inst]; | |
| 232 | switch (ops) { | |
| 233 | .rr_c => { | |
| 234 | const data = emit.mir.instructions.items(.data)[inst].rr_c; | |
| 235 | const mnemonic = mnemonicFromCC("cmov", data.cc); | |
| 236 | return emit.encode(mnemonic, .{ | |
| 237 | .op1 = .{ .reg = data.r1 }, | |
| 238 | .op2 = .{ .reg = data.r2 }, | |
| 239 | }); | |
| 240 | }, | |
| 241 | else => unreachable, // TODO | |
| 242 | } | |
| 243 | } | |
| 244 | ||
| 245 | fn mirSetCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | |
| 246 | const ops = emit.mir.instructions.items(.ops)[inst]; | |
| 247 | switch (ops) { | |
| 248 | .r_c => { | |
| 249 | const data = emit.mir.instructions.items(.data)[inst].r_c; | |
| 250 | const mnemonic = mnemonicFromCC("set", data.cc); | |
| 251 | return emit.encode(mnemonic, .{ | |
| 252 | .op1 = .{ .reg = data.r1 }, | |
| 253 | }); | |
| 254 | }, | |
| 255 | else => unreachable, // TODO | |
| 256 | } | |
| 257 | } | |
| 258 | ||
| 218 | 259 | fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { |
| 219 | 260 | const payload = emit.mir.instructions.items(.data)[inst].payload; |
| 220 | 261 | const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data; |
| ... | ... | @@ -333,107 +374,6 @@ fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) |
| 333 | 374 | // }); |
| 334 | 375 | // } |
| 335 | 376 | |
| 336 | // fn mirCondSetByte(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | |
| 337 | // const tag = emit.mir.instructions.items(.tag)[inst]; | |
| 338 | // assert(tag == .cond_set_byte); | |
| 339 | // const ops = emit.mir.instructions.items(.ops)[inst].decode(); | |
| 340 | // const cc = emit.mir.instructions.items(.data)[inst].cc; | |
| 341 | // const mnemonic: Instruction.Mnemonic = switch (cc) { | |
| 342 | // .a => .seta, | |
| 343 | // .ae => .setae, | |
| 344 | // .b => .setb, | |
| 345 | // .be => .setbe, | |
| 346 | // .c => .setc, | |
| 347 | // .e => .sete, | |
| 348 | // .g => .setg, | |
| 349 | // .ge => .setge, | |
| 350 | // .l => .setl, | |
| 351 | // .le => .setle, | |
| 352 | // .na => .setna, | |
| 353 | // .nae => .setnae, | |
| 354 | // .nb => .setnb, | |
| 355 | // .nbe => .setnbe, | |
| 356 | // .nc => .setnc, | |
| 357 | // .ne => .setne, | |
| 358 | // .ng => .setng, | |
| 359 | // .nge => .setnge, | |
| 360 | // .nl => .setnl, | |
| 361 | // .nle => .setnle, | |
| 362 | // .no => .setno, | |
| 363 | // .np => .setnp, | |
| 364 | // .ns => .setns, | |
| 365 | // .nz => .setnz, | |
| 366 | // .o => .seto, | |
| 367 | // .p => .setp, | |
| 368 | // .pe => .setpe, | |
| 369 | // .po => .setpo, | |
| 370 | // .s => .sets, | |
| 371 | // .z => .setz, | |
| 372 | // }; | |
| 373 | // return emit.encode(mnemonic, .{ .op1 = .{ .reg = ops.reg1 } }); | |
| 374 | // } | |
| 375 | ||
| 376 | // fn mirCondMov(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | |
| 377 | // const tag = emit.mir.instructions.items(.tag)[inst]; | |
| 378 | // assert(tag == .cond_mov); | |
| 379 | // const ops = emit.mir.instructions.items(.ops)[inst].decode(); | |
| 380 | // const cc = emit.mir.instructions.items(.data)[inst].cc; | |
| 381 | // const mnemonic: Instruction.Mnemonic = switch (cc) { | |
| 382 | // .a => .cmova, | |
| 383 | // .ae => .cmovae, | |
| 384 | // .b => .cmovb, | |
| 385 | // .be => .cmovbe, | |
| 386 | // .c => .cmovc, | |
| 387 | // .e => .cmove, | |
| 388 | // .g => .cmovg, | |
| 389 | // .ge => .cmovge, | |
| 390 | // .l => .cmovl, | |
| 391 | // .le => .cmovle, | |
| 392 | // .na => .cmovna, | |
| 393 | // .nae => .cmovnae, | |
| 394 | // .nb => .cmovnb, | |
| 395 | // .nbe => .cmovnbe, | |
| 396 | // .nc => .cmovnc, | |
| 397 | // .ne => .cmovne, | |
| 398 | // .ng => .cmovng, | |
| 399 | // .nge => .cmovnge, | |
| 400 | // .nl => .cmovnl, | |
| 401 | // .nle => .cmovnle, | |
| 402 | // .no => .cmovno, | |
| 403 | // .np => .cmovnp, | |
| 404 | // .ns => .cmovns, | |
| 405 | // .nz => .cmovnz, | |
| 406 | // .o => .cmovo, | |
| 407 | // .p => .cmovp, | |
| 408 | // .pe => .cmovpe, | |
| 409 | // .po => .cmovpo, | |
| 410 | // .s => .cmovs, | |
| 411 | // .z => .cmovz, | |
| 412 | // }; | |
| 413 | // const op1: Instruction.Operand = .{ .reg = ops.reg1 }; | |
| 414 | ||
| 415 | // if (ops.flags == 0b00) { | |
| 416 | // return emit.encode(mnemonic, .{ | |
| 417 | // .op1 = op1, | |
| 418 | // .op2 = .{ .reg = ops.reg2 }, | |
| 419 | // }); | |
| 420 | // } | |
| 421 | // const disp = emit.mir.instructions.items(.data)[inst].disp; | |
| 422 | // const ptr_size: Memory.PtrSize = switch (ops.flags) { | |
| 423 | // 0b00 => unreachable, | |
| 424 | // 0b01 => .word, | |
| 425 | // 0b10 => .dword, | |
| 426 | // 0b11 => .qword, | |
| 427 | // }; | |
| 428 | // return emit.encode(mnemonic, .{ | |
| 429 | // .op1 = op1, | |
| 430 | // .op2 = .{ .mem = Memory.sib(ptr_size, .{ | |
| 431 | // .base = ops.reg2, | |
| 432 | // .disp = disp, | |
| 433 | // }) }, | |
| 434 | // }); | |
| 435 | // } | |
| 436 | ||
| 437 | 377 | // fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { |
| 438 | 378 | // const tag = emit.mir.instructions.items(.tag)[inst]; |
| 439 | 379 | // assert(tag == .lea); |
src/arch/x86_64/Mir.zig+20-2| ... | ... | @@ -56,8 +56,6 @@ pub const Inst = struct { |
| 56 | 56 | cqo, |
| 57 | 57 | /// Logical compare |
| 58 | 58 | cmp, |
| 59 | /// Conditional move | |
| 60 | cmovcc, | |
| 61 | 59 | /// Unsigned division |
| 62 | 60 | div, |
| 63 | 61 | /// Store integer with truncation |
| ... | ... | @@ -134,6 +132,9 @@ pub const Inst = struct { |
| 134 | 132 | /// Unordered compare scalar double-precision floating-point values |
| 135 | 133 | ucomisd, |
| 136 | 134 | |
| 135 | /// Conditional move | |
| 136 | cmovcc, | |
| 137 | ||
| 137 | 138 | /// End of prologue |
| 138 | 139 | dbg_prologue_end, |
| 139 | 140 | /// Start of epilogue |
| ... | ... | @@ -161,6 +162,12 @@ pub const Inst = struct { |
| 161 | 162 | /// Register, register, register operands. |
| 162 | 163 | /// Uses `rrr` payload. |
| 163 | 164 | rrr, |
| 165 | /// Register with condition code (CC). | |
| 166 | /// Uses `r_c` payload. | |
| 167 | r_c, | |
| 168 | /// Register, register with condition code (CC). | |
| 169 | /// Uses `rr_c` payload. | |
| 170 | rr_c, | |
| 164 | 171 | /// Register, immediate (sign-extended) operands. |
| 165 | 172 | /// Uses `ri_s` payload. |
| 166 | 173 | ri_s, |
| ... | ... | @@ -241,6 +248,17 @@ pub const Inst = struct { |
| 241 | 248 | r2: Register, |
| 242 | 249 | r3: Register, |
| 243 | 250 | }, |
| 251 | /// Register with condition code (CC). | |
| 252 | r_c: struct { | |
| 253 | r1: Register, | |
| 254 | cc: bits.Condition, | |
| 255 | }, | |
| 256 | /// Register, register with condition code (CC). | |
| 257 | rr_c: struct { | |
| 258 | r1: Register, | |
| 259 | r2: Register, | |
| 260 | cc: bits.Condition, | |
| 261 | }, | |
| 244 | 262 | /// Register, signed immediate. |
| 245 | 263 | ri_s: struct { |
| 246 | 264 | r1: Register, |