diff --git a/pkgs/boots/assembler/x64.dora b/pkgs/boots/assembler/x64.dora index 64aace027..9b16dbacd 100644 --- a/pkgs/boots/assembler/x64.dora +++ b/pkgs/boots/assembler/x64.dora @@ -753,6 +753,17 @@ impl AssemblerX64 { self.emitAddress(dest.lowBits(), src); } + pub fn movss_rl(dest: FloatRegister, label: Label) { + assert(!self.hasAvx2); + self.emitByte(0xF3u8); + if dest.needsRexBit() { + self.emitRex(false, true, false, false); + } + self.emitByte(0x0Fu8); + self.emitByte(0x10u8); + self.emitLabelAddress(dest.lowBits(), label); + } + pub fn movss_rr(dest: FloatRegister, src: FloatRegister) { assert(!self.hasAvx2); self.emitByte(0xF3u8); @@ -1651,6 +1662,22 @@ impl AssemblerX64 { self.emitAddress(dest.lowBits(), src); } + pub fn vmovss_rl(dest: FloatRegister, label: Label) { + assert(self.hasAvx2); + self.emitVex( + dest.needsRexBit(), + false, + false, + VEX_MMMMM_0F, + VEX_W0, + VEX_VVVV_UNUSED, + VEX_L_SCALAR_128, + VEX_PP_F3, + ); + self.emitByte(0x10u8); + self.emitLabelAddress(dest.lowBits(), label); + } + pub fn vmovss_rr(dest: FloatRegister, lhs: FloatRegister, rhs: FloatRegister) { assert(self.hasAvx2); self.emitVex( @@ -2146,6 +2173,13 @@ impl AssemblerX64 { } } + fn emitLabelAddress(reg: Int32, label: Label) { + self.emitModRm(0b00i32, reg, 0b101i32); + let pc = self.buffer.size(); + self.jumps.push((pc, label, JumpDistance::Far)); + self.emitInt32(0i32); + } + // r - rex.r bit (1 bit) // x - rex.x bit (1 bit) // b - rex.b bit (1 bit) @@ -2253,7 +2287,7 @@ impl AssemblerX64 { self.buffer.emitInt32(value); } - fn emitInt64(value: Int64) { + pub fn emitInt64(value: Int64) { self.buffer.emitInt64(value); } diff --git a/pkgs/boots/codegen/x64.dora b/pkgs/boots/codegen/x64.dora index 77603c7b1..fad0d30ff 100644 --- a/pkgs/boots/codegen/x64.dora +++ b/pkgs/boots/codegen/x64.dora @@ -76,6 +76,7 @@ pub class CodeGenX64 { asm: AssemblerX64, graph: Graph, constPool: ConstPool, + epilogConstants: Vec[(Label, ConstPoolValue)], locations: LocationTable, lazyCompilation: LazyCompilationData, gcPoints: GcPointTable, @@ -92,6 +93,7 @@ impl CodeGenX64 { asm = AssemblerX64::new(config.hasAvx2), graph, constPool = ConstPool::new(), + epilogConstants = Vec[(Label, ConstPoolValue)]::new(), locations = LocationTable::new(), lazyCompilation = LazyCompilationData::new(), gcPoints = GcPointTable::new(), @@ -127,21 +129,33 @@ impl CodeGenX64 { } } + fn emitEpilogConstants() { + for (label, constant) in self.epilogConstants { + self.asm.bindLabel(label); + + match constant { + ConstPoolValue::Float32(value) => { + self.asm.emitInt32(value.asInt32()); + } + + ConstPoolValue::Float64(value) => { + self.asm.emitInt64(value.asInt64()); + } + + _ => unreachable[()](), + } + } + } + fn mov_imm_f32(dest: FloatRegister, value: Float32) { - let entry = self.constPool.push(ConstPoolValue::Float32(value)); - let const_offset = entry.disp; + let label = self.asm.createLabel(); + self.epilogConstants.push((label, ConstPoolValue::Float32(value))); if self.hasAvx2 { - self.asm.vmovss_ra(dest, AsmAddress::rip(0i32)); + self.asm.vmovss_rl(dest, label); } else { - self.asm.movss_ra(dest, AsmAddress::rip(0i32)); + self.asm.movss_rl(dest, label); } - - let inst_end = self.asm.position(); - let disp = -(const_offset + inst_end); - self.asm.setPosition(inst_end - 4i32); - self.asm.emitInt32(disp); - self.asm.setPositionEnd(); } fn mov_imm_f64(dest: FloatRegister, value: Float64) { @@ -3249,6 +3263,7 @@ impl CodeGen for CodeGenX64 { fn finalize(): CodeDescriptor { self.emitDeferredCode(); + self.emitEpilogConstants(); self.asm.resolveJumps(); self.asm.nop();