implement signed multiplication
This commit is contained in:
parent
be6ea6c45d
commit
d390ee08f6
@ -552,6 +552,7 @@ pub const BinaryOperation = struct {
|
||||
logical_and,
|
||||
logical_xor,
|
||||
logical_or,
|
||||
multiply,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -238,6 +238,7 @@ pub const BinaryOperation = struct {
|
||||
logical_and,
|
||||
logical_xor,
|
||||
logical_or,
|
||||
multiply,
|
||||
};
|
||||
|
||||
pub const List = BlockList(@This());
|
||||
@ -737,6 +738,7 @@ pub const Builder = struct {
|
||||
.logical_and => .logical_and,
|
||||
.logical_xor => .logical_xor,
|
||||
.logical_or => .logical_or,
|
||||
.multiply => .multiply,
|
||||
},
|
||||
.type = try builder.translateType(sema_binary_operation.type),
|
||||
});
|
||||
|
@ -40,15 +40,15 @@ pub const Logger = enum {
|
||||
pub var bitset = std.EnumSet(Logger).initMany(&.{
|
||||
.instruction_selection_ir_function,
|
||||
.instruction_selection_mir_function,
|
||||
.instruction_selection_register_operand_list,
|
||||
.register_allocation_block,
|
||||
.register_allocation_problematic_hint,
|
||||
.register_allocation_assignment,
|
||||
.register_allocation_reload,
|
||||
.register_allocation_function_before,
|
||||
.register_allocation_new_instruction,
|
||||
.register_allocation_new_instruction_function_before,
|
||||
.register_allocation_instruction_avoid_copy,
|
||||
// .instruction_selection_register_operand_list,
|
||||
// .register_allocation_block,
|
||||
// .register_allocation_problematic_hint,
|
||||
// .register_allocation_assignment,
|
||||
// .register_allocation_reload,
|
||||
// .register_allocation_function_before,
|
||||
// .register_allocation_new_instruction,
|
||||
// .register_allocation_new_instruction_function_before,
|
||||
// .register_allocation_instruction_avoid_copy,
|
||||
.register_allocation_function_after,
|
||||
// .register_allocation_operand_list_verification,
|
||||
// .encoding,
|
||||
@ -1491,6 +1491,8 @@ const Instruction = struct {
|
||||
and32rr,
|
||||
call64pcrel32,
|
||||
copy,
|
||||
imul32rm,
|
||||
imul32rr,
|
||||
lea64r,
|
||||
mov32r0,
|
||||
mov32rm,
|
||||
@ -1918,6 +1920,40 @@ const instruction_descriptors = std.EnumArray(Instruction.Id, Instruction.Descri
|
||||
},
|
||||
},
|
||||
},
|
||||
.imul32rr = .{
|
||||
.opcode = 0x6b,
|
||||
.operands = &.{
|
||||
.{
|
||||
.id = .gp32,
|
||||
.kind = .dst,
|
||||
},
|
||||
.{
|
||||
.id = .gp32,
|
||||
.kind = .src,
|
||||
},
|
||||
.{
|
||||
.id = .gp32,
|
||||
.kind = .src,
|
||||
},
|
||||
},
|
||||
},
|
||||
.imul32rm = .{
|
||||
.opcode = 0x6b,
|
||||
.operands = &.{
|
||||
.{
|
||||
.id = .gp32,
|
||||
.kind = .dst,
|
||||
},
|
||||
.{
|
||||
.id = .gp32,
|
||||
.kind = .src,
|
||||
},
|
||||
.{
|
||||
.id = .i32mem,
|
||||
.kind = .src,
|
||||
},
|
||||
},
|
||||
},
|
||||
.lea64r = .{
|
||||
// .format = .mrm_source_mem,
|
||||
.opcode = 0x8d,
|
||||
@ -2951,6 +2987,10 @@ pub const MIR = struct {
|
||||
.i32 => .or32rr,
|
||||
else => unreachable,
|
||||
},
|
||||
.multiply => switch (value_type) {
|
||||
.i32 => .imul32rr,
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
||||
const instruction_descriptor = instruction_descriptors.get(instruction_id);
|
||||
@ -3018,6 +3058,10 @@ pub const MIR = struct {
|
||||
.i32 => .or32rm,
|
||||
else => unreachable,
|
||||
},
|
||||
.multiply => switch (value_type) {
|
||||
.i32 => .imul32rm,
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
||||
try instruction_selection.folded_loads.putNoClobber(mir.allocator, ir_binary_operation.right, {});
|
||||
@ -4604,7 +4648,10 @@ pub const MIR = struct {
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
},
|
||||
.add32rr, .sub32rr => {
|
||||
.add32rr,
|
||||
.sub32rr,
|
||||
.imul32rr,
|
||||
=> {
|
||||
assert(instruction.operands.items.len == 3);
|
||||
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||
@ -4631,7 +4678,46 @@ pub const MIR = struct {
|
||||
};
|
||||
try image.section_manager.appendCodeByte(@bitCast(modrm));
|
||||
},
|
||||
.add32rm, .sub32rm, .and32rm, .xor32rm, .or32rm => {
|
||||
.mov32mi => {
|
||||
assert(instruction.operands.items.len == 2);
|
||||
|
||||
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||
try image.section_manager.appendCodeByte(opcode);
|
||||
|
||||
const destination_operand_index = instruction.operands.items[0];
|
||||
const destination_operand = mir.operands.get(destination_operand_index);
|
||||
switch (destination_operand.u.memory.addressing_mode.base) {
|
||||
.register_base => unreachable,
|
||||
.frame_index => |frame_index| {
|
||||
const modrm = ModRm{
|
||||
.rm = @intFromEnum(Encoding.GP64.bp),
|
||||
.reg = 0,
|
||||
.mod = @as(u2, @intFromBool(false)) << 1 | @intFromBool(true),
|
||||
};
|
||||
try image.section_manager.appendCodeByte(@bitCast(modrm));
|
||||
|
||||
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];
|
||||
try image.section_manager.appendCode(stack_bytes);
|
||||
},
|
||||
}
|
||||
|
||||
const source_operand_index = instruction.operands.items[1];
|
||||
const source_operand = mir.operands.get(source_operand_index);
|
||||
const source_immediate: u32 = @intCast(source_operand.u.immediate);
|
||||
|
||||
try image.section_manager.appendCode(std.mem.asBytes(&source_immediate));
|
||||
},
|
||||
.add32rm,
|
||||
.sub32rm,
|
||||
.and32rm,
|
||||
.xor32rm,
|
||||
.or32rm,
|
||||
.imul32rm,
|
||||
=> {
|
||||
assert(instruction.operands.items.len == 3);
|
||||
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||
@ -4670,39 +4756,6 @@ pub const MIR = struct {
|
||||
},
|
||||
}
|
||||
},
|
||||
.mov32mi => {
|
||||
assert(instruction.operands.items.len == 2);
|
||||
|
||||
const instruction_descriptor = instruction_descriptors.get(instruction.id);
|
||||
const opcode: u8 = @intCast(instruction_descriptor.opcode);
|
||||
try image.section_manager.appendCodeByte(opcode);
|
||||
|
||||
const destination_operand_index = instruction.operands.items[0];
|
||||
const destination_operand = mir.operands.get(destination_operand_index);
|
||||
switch (destination_operand.u.memory.addressing_mode.base) {
|
||||
.register_base => unreachable,
|
||||
.frame_index => |frame_index| {
|
||||
const modrm = ModRm{
|
||||
.rm = @intFromEnum(Encoding.GP64.bp),
|
||||
.reg = 0,
|
||||
.mod = @as(u2, @intFromBool(false)) << 1 | @intFromBool(true),
|
||||
};
|
||||
try image.section_manager.appendCodeByte(@bitCast(modrm));
|
||||
|
||||
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];
|
||||
try image.section_manager.appendCode(stack_bytes);
|
||||
},
|
||||
}
|
||||
|
||||
const source_operand_index = instruction.operands.items[1];
|
||||
const source_operand = mir.operands.get(source_operand_index);
|
||||
const source_immediate: u32 = @intCast(source_operand.u.immediate);
|
||||
|
||||
try image.section_manager.appendCode(std.mem.asBytes(&source_immediate));
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
|
||||
|
@ -543,6 +543,7 @@ const Analyzer = struct {
|
||||
.logical_and => .logical_and,
|
||||
.logical_xor => .logical_xor,
|
||||
.logical_or => .logical_or,
|
||||
.multiply => .multiply,
|
||||
else => |t| @panic(@tagName(t)),
|
||||
},
|
||||
});
|
||||
@ -1013,6 +1014,7 @@ const Analyzer = struct {
|
||||
.logical_and,
|
||||
.logical_xor,
|
||||
.logical_or,
|
||||
.multiply,
|
||||
=> try analyzer.processBinaryOperation(scope_index, expect_type, node_index),
|
||||
.expression_group => return try analyzer.resolveNode(value, scope_index, expect_type, node.left), //unreachable,
|
||||
else => |t| @panic(@tagName(t)),
|
||||
|
@ -158,6 +158,7 @@ pub const Node = packed struct(u128) {
|
||||
logical_xor = 64,
|
||||
expression_group = 65,
|
||||
logical_or = 66,
|
||||
multiply = 67,
|
||||
};
|
||||
};
|
||||
|
||||
@ -717,6 +718,7 @@ const Analyzer = struct {
|
||||
logical_and,
|
||||
logical_xor,
|
||||
logical_or,
|
||||
multiply,
|
||||
};
|
||||
|
||||
const operator_precedence = std.EnumArray(PrecedenceOperator, i32).init(.{
|
||||
@ -727,6 +729,7 @@ const Analyzer = struct {
|
||||
.logical_and = 40,
|
||||
.logical_xor = 40,
|
||||
.logical_or = 40,
|
||||
.multiply = 70,
|
||||
});
|
||||
|
||||
const operator_associativity = std.EnumArray(PrecedenceOperator, Associativity).init(.{
|
||||
@ -737,6 +740,7 @@ const Analyzer = struct {
|
||||
.logical_and = .left,
|
||||
.logical_xor = .left,
|
||||
.logical_or = .left,
|
||||
.multiply = .left,
|
||||
});
|
||||
|
||||
const operator_node_id = std.EnumArray(PrecedenceOperator, Node.Id).init(.{
|
||||
@ -747,6 +751,7 @@ const Analyzer = struct {
|
||||
.logical_and = .logical_and,
|
||||
.logical_xor = .logical_xor,
|
||||
.logical_or = .logical_or,
|
||||
.multiply = .multiply,
|
||||
});
|
||||
|
||||
fn expressionPrecedence(analyzer: *Analyzer, minimum_precedence: i32) !Node.Index {
|
||||
@ -807,6 +812,10 @@ const Analyzer = struct {
|
||||
.equal => unreachable,
|
||||
else => .logical_or,
|
||||
},
|
||||
.asterisk => switch (next_token_id) {
|
||||
.equal => unreachable,
|
||||
else => .multiply,
|
||||
},
|
||||
else => |t| @panic(@tagName(t)),
|
||||
};
|
||||
} else {
|
||||
@ -833,6 +842,7 @@ const Analyzer = struct {
|
||||
.logical_and,
|
||||
.logical_xor,
|
||||
.logical_or,
|
||||
.multiply,
|
||||
=> false,
|
||||
.compare_equal,
|
||||
.compare_not_equal,
|
||||
|
Loading…
x
Reference in New Issue
Block a user