x86_64: some encodings
This commit is contained in:
parent
9dc5f795b2
commit
73769beb32
@ -3765,12 +3765,31 @@ pub const MIR = struct {
|
|||||||
const gp_register_encoding: Encoding.GP64 = switch (physical_register) {
|
const gp_register_encoding: Encoding.GP64 = switch (physical_register) {
|
||||||
.rax => .a,
|
.rax => .a,
|
||||||
.rdi => .di,
|
.rdi => .di,
|
||||||
|
.rsi => .si,
|
||||||
|
.rdx => .d,
|
||||||
|
.rcx => .c,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
return gp_register_encoding;
|
return gp_register_encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn computeStackSize(stack_objects: []const StackObject) u32 {
|
||||||
|
var result: u32 = 0;
|
||||||
|
|
||||||
|
for (stack_objects) |stack_object| {
|
||||||
|
result += @intCast(stack_object.size);
|
||||||
|
result = std.mem.alignForward(u32, result, stack_object.alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn computeStackOffset(stack_objects: []const StackObject) i32 {
|
||||||
|
const stack_size = computeStackSize(stack_objects);
|
||||||
|
return -@as(i32, @intCast(stack_size));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn encode(mir: *MIR) !*emit.Result {
|
pub fn encode(mir: *MIR) !*emit.Result {
|
||||||
const image = try mir.allocator.create(emit.Result);
|
const image = try mir.allocator.create(emit.Result);
|
||||||
image.* = try emit.Result.create(mir.allocator, mir.target, mir.entry_point);
|
image.* = try emit.Result.create(mir.allocator, mir.target, mir.entry_point);
|
||||||
@ -3790,16 +3809,7 @@ pub const MIR = struct {
|
|||||||
function_offsets.putAssumeCapacityNoClobber(function_index, function_offset);
|
function_offsets.putAssumeCapacityNoClobber(function_index, function_offset);
|
||||||
image.sections.items[0].symbol_table.putAssumeCapacityNoClobber(function.name, function_offset);
|
image.sections.items[0].symbol_table.putAssumeCapacityNoClobber(function.name, function_offset);
|
||||||
|
|
||||||
const stack_size = blk: {
|
const stack_size = std.mem.alignForward(u32, computeStackSize(function.instruction_selection.stack_objects.items), 0x10);
|
||||||
var result: u32 = 0;
|
|
||||||
|
|
||||||
for (function.instruction_selection.stack_objects.items) |stack_object| {
|
|
||||||
assert(std.mem.isAligned(result, stack_object.alignment));
|
|
||||||
result += @intCast(stack_object.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk result;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (stack_size != 0) {
|
if (stack_size != 0) {
|
||||||
image.appendCodeByte(0x55); // push rbp
|
image.appendCodeByte(0x55); // push rbp
|
||||||
@ -3859,15 +3869,46 @@ pub const MIR = struct {
|
|||||||
|
|
||||||
switch (memory.addressing_mode.base) {
|
switch (memory.addressing_mode.base) {
|
||||||
.frame_index => |frame_index| {
|
.frame_index => |frame_index| {
|
||||||
const stack_offset = blk: {
|
const stack_offset = computeStackOffset(function.instruction_selection.stack_objects.items[0 .. frame_index + 1]);
|
||||||
var computed_stack_offset: usize = 0;
|
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
||||||
for (function.instruction_selection.stack_objects.items[0 .. frame_index + 1]) |stack_object| {
|
|
||||||
assert(std.mem.isAligned(computed_stack_offset, stack_object.alignment));
|
|
||||||
computed_stack_offset += stack_object.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk -@as(i64, @intCast(computed_stack_offset));
|
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
||||||
};
|
image.appendCode(stack_bytes);
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.mov64mr => {
|
||||||
|
assert(instruction.operands.items.len == 2);
|
||||||
|
|
||||||
|
const rex = Rex{
|
||||||
|
.b = false,
|
||||||
|
.x = false,
|
||||||
|
.r = false,
|
||||||
|
.w = true,
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(rex));
|
||||||
|
|
||||||
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
|
const source_gp64 = getGP64Encoding(source_operand.*);
|
||||||
|
|
||||||
|
const destination_operand = mir.operands.get(instruction.operands.items[0]);
|
||||||
|
assert(destination_operand.u == .memory);
|
||||||
|
const memory = destination_operand.u.memory;
|
||||||
|
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||||
|
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||||
|
image.appendCodeByte(opcode);
|
||||||
|
|
||||||
|
const modrm = ModRm{
|
||||||
|
.rm = @intFromEnum(Encoding.GP64.bp),
|
||||||
|
.reg = @intCast(@intFromEnum(source_gp64)),
|
||||||
|
.mod = @as(u2, @intFromBool(false)) << 1 | @intFromBool(true),
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(modrm));
|
||||||
|
|
||||||
|
switch (memory.addressing_mode.base) {
|
||||||
|
.frame_index => |frame_index| {
|
||||||
|
const stack_offset = computeStackOffset(function.instruction_selection.stack_objects.items[0 .. frame_index + 1]);
|
||||||
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
||||||
|
|
||||||
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
||||||
@ -3899,15 +3940,7 @@ pub const MIR = struct {
|
|||||||
|
|
||||||
switch (source_memory.addressing_mode.base) {
|
switch (source_memory.addressing_mode.base) {
|
||||||
.frame_index => |frame_index| {
|
.frame_index => |frame_index| {
|
||||||
const stack_offset = blk: {
|
const stack_offset = computeStackOffset(function.instruction_selection.stack_objects.items[0 .. frame_index + 1]);
|
||||||
var computed_stack_offset: usize = 0;
|
|
||||||
for (function.instruction_selection.stack_objects.items[0 .. frame_index + 1]) |stack_object| {
|
|
||||||
assert(std.mem.isAligned(computed_stack_offset, stack_object.alignment));
|
|
||||||
computed_stack_offset += stack_object.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk -@as(i64, @intCast(computed_stack_offset));
|
|
||||||
};
|
|
||||||
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
||||||
|
|
||||||
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
||||||
@ -3916,6 +3949,60 @@ pub const MIR = struct {
|
|||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.mov64rm => {
|
||||||
|
assert(instruction.operands.items.len == 2);
|
||||||
|
|
||||||
|
const rex = Rex{
|
||||||
|
.b = false,
|
||||||
|
.x = false,
|
||||||
|
.r = false,
|
||||||
|
.w = true,
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(rex));
|
||||||
|
|
||||||
|
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||||
|
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||||
|
image.appendCodeByte(opcode);
|
||||||
|
|
||||||
|
const destination_operand = mir.operands.get(instruction.operands.items[0]);
|
||||||
|
const destination_gp64 = getGP64Encoding(destination_operand.*);
|
||||||
|
|
||||||
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
|
assert(source_operand.u == .memory);
|
||||||
|
const source_memory = source_operand.u.memory;
|
||||||
|
|
||||||
|
const modrm = ModRm{
|
||||||
|
.rm = @intFromEnum(Encoding.GP64.bp),
|
||||||
|
.reg = @intCast(@intFromEnum(destination_gp64)),
|
||||||
|
.mod = @as(u2, @intFromBool(false)) << 1 | @intFromBool(true),
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(modrm));
|
||||||
|
|
||||||
|
switch (source_memory.addressing_mode.base) {
|
||||||
|
.frame_index => |frame_index| {
|
||||||
|
const stack_offset = computeStackOffset(function.instruction_selection.stack_objects.items[0 .. frame_index + 1]);
|
||||||
|
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
||||||
|
|
||||||
|
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
||||||
|
image.appendCode(stack_bytes);
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.mov32ri => {
|
||||||
|
assert(instruction.operands.items.len == 2);
|
||||||
|
|
||||||
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
|
const source_immediate: u32 = @intCast(source_operand.u.immediate);
|
||||||
|
|
||||||
|
const destination_operand = mir.operands.get(instruction.operands.items[0]);
|
||||||
|
const destination_gp32 = getGP32Encoding(destination_operand.*);
|
||||||
|
|
||||||
|
const opcode = @as(u8, 0xb8) | @as(u3, @intCast(@intFromEnum(destination_gp32)));
|
||||||
|
image.appendCodeByte(opcode);
|
||||||
|
|
||||||
|
image.appendCode(std.mem.asBytes(&source_immediate));
|
||||||
|
},
|
||||||
.mov32ri64 => {
|
.mov32ri64 => {
|
||||||
assert(instruction.operands.items.len == 2);
|
assert(instruction.operands.items.len == 2);
|
||||||
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
@ -3962,15 +4049,7 @@ pub const MIR = struct {
|
|||||||
|
|
||||||
switch (source_memory.addressing_mode.base) {
|
switch (source_memory.addressing_mode.base) {
|
||||||
.frame_index => |frame_index| {
|
.frame_index => |frame_index| {
|
||||||
const stack_offset = blk: {
|
const stack_offset = computeStackOffset(function.instruction_selection.stack_objects.items[0 .. frame_index + 1]);
|
||||||
var computed_stack_offset: usize = 0;
|
|
||||||
for (function.instruction_selection.stack_objects.items[0 .. frame_index + 1]) |stack_object| {
|
|
||||||
assert(std.mem.isAligned(computed_stack_offset, stack_object.alignment));
|
|
||||||
computed_stack_offset += stack_object.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
break :blk -@as(i64, @intCast(computed_stack_offset));
|
|
||||||
};
|
|
||||||
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
const displacement_bytes: u3 = if (std.math.cast(i8, stack_offset)) |_| @sizeOf(i8) else if (std.math.cast(i32, stack_offset)) |_| @sizeOf(i32) else unreachable;
|
||||||
|
|
||||||
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
const stack_bytes = std.mem.asBytes(&stack_offset)[0..displacement_bytes];
|
||||||
@ -4016,9 +4095,6 @@ pub const MIR = struct {
|
|||||||
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
assert(destination_operand.id == source_operand.id);
|
assert(destination_operand.id == source_operand.id);
|
||||||
|
|
||||||
// const destination_physical_register = destination_operand.u.register.index.physical;
|
|
||||||
// _ = destination_physical_register;
|
|
||||||
// const source_physical_register = source_operand.u.register.index.physical;
|
|
||||||
switch (destination_operand.id) {
|
switch (destination_operand.id) {
|
||||||
.gp32 => {
|
.gp32 => {
|
||||||
image.appendCodeByte(0x89);
|
image.appendCodeByte(0x89);
|
||||||
@ -4032,9 +4108,69 @@ pub const MIR = struct {
|
|||||||
};
|
};
|
||||||
image.appendCodeByte(@bitCast(modrm));
|
image.appendCodeByte(@bitCast(modrm));
|
||||||
},
|
},
|
||||||
|
.gp64 => {
|
||||||
|
const rex = Rex{
|
||||||
|
.b = false,
|
||||||
|
.x = false,
|
||||||
|
.r = false,
|
||||||
|
.w = true,
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(rex));
|
||||||
|
|
||||||
|
image.appendCodeByte(0x89);
|
||||||
|
|
||||||
|
const destination_register = getGP64Encoding(destination_operand.*);
|
||||||
|
const source_register = getGP64Encoding(source_operand.*);
|
||||||
|
const modrm = ModRm{
|
||||||
|
.rm = @intCast(@intFromEnum(destination_register)),
|
||||||
|
.reg = @intCast(@intFromEnum(source_register)),
|
||||||
|
.mod = @as(u2, @intFromBool(true)) << 1 | @intFromBool(true),
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(modrm));
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.lea64r => {
|
||||||
|
assert(instruction.operands.items.len == 2);
|
||||||
|
const rex = Rex{
|
||||||
|
.b = false,
|
||||||
|
.x = false,
|
||||||
|
.r = false,
|
||||||
|
.w = true,
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(rex));
|
||||||
|
|
||||||
|
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||||
|
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||||
|
image.appendCodeByte(opcode);
|
||||||
|
|
||||||
|
const destination_operand = mir.operands.get(instruction.operands.items[0]);
|
||||||
|
const destination_register = getGP64Encoding(destination_operand.*);
|
||||||
|
// const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
|
const modrm = ModRm{
|
||||||
|
.rm = @intFromEnum(Encoding.GP64.bp),
|
||||||
|
.reg = @intCast(@intFromEnum(destination_register)),
|
||||||
|
.mod = @as(u2, @intFromBool(false)) << 1 | @intFromBool(false),
|
||||||
|
};
|
||||||
|
image.appendCodeByte(@bitCast(modrm));
|
||||||
|
|
||||||
|
const source_operand = mir.operands.get(instruction.operands.items[1]);
|
||||||
|
switch (source_operand.u) {
|
||||||
|
.lea64mem => |lea64mem| {
|
||||||
|
assert(lea64mem.gp64 == null);
|
||||||
|
assert(lea64mem.scale == 1);
|
||||||
|
assert(lea64mem.scale_reg == null);
|
||||||
|
|
||||||
|
switch (lea64mem.displacement) {
|
||||||
|
.string_literal => unreachable,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
unreachable;
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user