Lower packed integer add instructions (v128)

Adds lowering support for packed integer add instructions and helper
function for determining if a type for an instruction indicates it is
packed.
This commit is contained in:
Johnnie Birch
2020-08-05 13:18:12 -07:00
parent 2eadc6e2a8
commit dd6ba5f9d7
2 changed files with 37 additions and 28 deletions

View File

@@ -1662,7 +1662,7 @@ pub(crate) fn emit(
SseOpcode::Paddb => (LegacyPrefix::_66, 0x0FFC), SseOpcode::Paddb => (LegacyPrefix::_66, 0x0FFC),
SseOpcode::Paddd => (LegacyPrefix::_66, 0x0FFE), SseOpcode::Paddd => (LegacyPrefix::_66, 0x0FFE),
SseOpcode::Paddq => (LegacyPrefix::_66, 0x0FD4), SseOpcode::Paddq => (LegacyPrefix::_66, 0x0FD4),
SSeOpcode::Paddw => (LegacyPrefix::_66, 0x0FFD), SseOpcode::Paddw => (LegacyPrefix::_66, 0x0FFD),
SseOpcode::Subps => (LegacyPrefix::None, 0x0F5C), SseOpcode::Subps => (LegacyPrefix::None, 0x0F5C),
SseOpcode::Subpd => (LegacyPrefix::_66, 0x0F5C), SseOpcode::Subpd => (LegacyPrefix::_66, 0x0F5C),
SseOpcode::Subss => (LegacyPrefix::_F3, 0x0F5C), SseOpcode::Subss => (LegacyPrefix::_F3, 0x0F5C),

View File

@@ -45,14 +45,6 @@ fn is_bool_ty(ty: Type) -> bool {
} }
} }
fn int_ty_is_64(ty: Type) -> bool {
match ty {
types::I8 | types::I16 | types::I32 => false,
types::I64 => true,
_ => panic!("type {} is none of I8, I16, I32 or I64", ty),
}
}
fn iri_to_u64_imm(ctx: Ctx, inst: IRInst) -> Option<u64> { fn iri_to_u64_imm(ctx: Ctx, inst: IRInst) -> Option<u64> {
ctx.get_constant(inst) ctx.get_constant(inst)
} }
@@ -346,28 +338,45 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
| Opcode::Band | Opcode::Band
| Opcode::Bor | Opcode::Bor
| Opcode::Bxor => { | Opcode::Bxor => {
let lhs = input_to_reg(ctx, inputs[0]);
let rhs = input_to_reg_mem_imm(ctx, inputs[1]);
let dst = output_to_reg(ctx, outputs[0]);
let ty = ty.unwrap();
// TODO For commutative operations (add, mul, and, or, xor), try to commute the // TODO For commutative operations (add, mul, and, or, xor), try to commute the
// operands if one is an immediate. // operands if one is an immediate.
let ty = ty.unwrap();
println!("Type: {}, Ops: {}", ty, op);
if ty.lane_count() > 1 {
let sse_op = match op {
Opcode::Iadd => match ty {
I8x16 => SseOpcode::Paddb,
I16x8 => SseOpcode::Paddw,
I32x4 => SseOpcode::Paddd,
I64x2 => SseOpcode::Paddq,
_ => panic!("Unsupported type for packed Iadd instruction"),
},
_ => panic!("Unsupported packed instruction"),
};
let lhs = input_to_reg(ctx, inputs[0]);
let rhs = input_to_reg_mem(ctx, inputs[1]);
let dst = output_to_reg(ctx, outputs[0]);
println!("Type: {}", ty); // Move the `lhs` to the same register as `dst`.
let is_64 = int_ty_is_64(ty.unwrap()); ctx.emit(Inst::gen_move(dst, lhs, ty));
let alu_op = match op { ctx.emit(Inst::xmm_rm_r(sse_op, rhs, dst));
Opcode::Iadd | Opcode::IaddIfcout => AluRmiROpcode::Add, } else {
Opcode::Isub => AluRmiROpcode::Sub, let is_64 = ty == types::I64;
Opcode::Imul => AluRmiROpcode::Mul, let alu_op = match op {
Opcode::Band => AluRmiROpcode::And, Opcode::Iadd | Opcode::IaddIfcout => AluRmiROpcode::Add,
Opcode::Bor => AluRmiROpcode::Or, Opcode::Isub => AluRmiROpcode::Sub,
Opcode::Bxor => AluRmiROpcode::Xor, Opcode::Imul => AluRmiROpcode::Mul,
_ => unreachable!(), Opcode::Band => AluRmiROpcode::And,
}; Opcode::Bor => AluRmiROpcode::Or,
Opcode::Bxor => AluRmiROpcode::Xor,
ctx.emit(Inst::mov_r_r(true, lhs, dst)); _ => unreachable!(),
ctx.emit(Inst::alu_rmi_r(is_64, alu_op, rhs, dst)); };
let lhs = input_to_reg(ctx, inputs[0]);
let rhs = input_to_reg_mem_imm(ctx, inputs[1]);
let dst = output_to_reg(ctx, outputs[0]);
ctx.emit(Inst::mov_r_r(true, lhs, dst));
ctx.emit(Inst::alu_rmi_r(is_64, alu_op, rhs, dst));
}
} }
Opcode::Ishl | Opcode::Ushr | Opcode::Sshr | Opcode::Rotl | Opcode::Rotr => { Opcode::Ishl | Opcode::Ushr | Opcode::Sshr | Opcode::Rotl | Opcode::Rotr => {