From d887643b7a528736fff857c67f1a93afa3d8b2f5 Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 27 Dec 2021 18:19:58 -0800 Subject: vector x indexed fmla,fmls,fmul --- src/armv8/a64.rs | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index b698f6c..af52bf4 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -3089,26 +3089,174 @@ impl Decoder for InstDecoder { return Err(DecodeError::InvalidOpcode); } 0b0_0000 => { - if size < 0b10 { + // FMLAL + if size != 0b10 { return Err(DecodeError::InvalidOpcode); } - // FMLAL + if (word >> 29 & 1) == 0 { + inst.opcode = Opcode::FMLAL; + } else { + inst.opcode = Opcode::FMLAL2; + } + + let index = (H << 2) | (L << 1) | M; + + let datasize = if Q == 1 { SIMDSizeCode::Q } else { SIMDSizeCode::D }; + + inst.operands = [ + Operand::SIMDRegisterElements(datasize, Rd as u16, SIMDSizeCode::S), + Operand::SIMDRegisterElements(datasize, Rn as u16, SIMDSizeCode::H), + Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rm as u16, SIMDSizeCode::H, index as u8), + Operand::Nothing, + ]; + } + 0b0_0100 => { + // FMLSL + if size != 0b10 { + return Err(DecodeError::InvalidOpcode); + } + if (word >> 29 & 1) == 0 { + inst.opcode = Opcode::FMLSL; + } else { + inst.opcode = Opcode::FMLSL2; + } + + let index = (H << 2) | (L << 1) | M; + + let datasize = if Q == 1 { SIMDSizeCode::Q } else { SIMDSizeCode::D }; + + inst.operands = [ + Operand::SIMDRegisterElements(datasize, Rd as u16, SIMDSizeCode::S), + Operand::SIMDRegisterElements(datasize, Rn as u16, SIMDSizeCode::H), + Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rm as u16, SIMDSizeCode::H, index as u8), + Operand::Nothing, + ]; } 0b0_0001 => { - // TODO: // FMLA (not size=0b01) - } - 0b0_0100 => { - // TODO: - // FMLSL (not size<0b10) + if size == 0b01 { + return Err(DecodeError::InvalidOpcode); + } + + inst.opcode = Opcode::FMLA; + + let sz = size & 1; + + if sz == 1 && L == 1 { + return Err(DecodeError::InvalidOperand); + } + + if sz == 1 && Q == 0 { + return Err(DecodeError::InvalidOperand); + } + + let (index, Rm, size) = if size == 0b00 { + let index = (H << 2) | (L << 1) | M; + (index, Rm, SIMDSizeCode::H) + } else if size == 0b10 { + // `sz == 0` + let index = (H << 1) | L; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::S) + } else { + // `sz == 1` + let index = H; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::D) + }; + + let datasize = if Q == 1 { SIMDSizeCode::Q } else { SIMDSizeCode::D }; + + inst.operands = [ + Operand::SIMDRegisterElements(datasize, Rd as u16, size), + Operand::SIMDRegisterElements(datasize, Rn as u16, size), + Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rm as u16, size, index as u8), + Operand::Nothing, + ]; } 0b0_0101 => { - // TODO: // FMLS (not size=0b01) + if size == 0b01 { + return Err(DecodeError::InvalidOpcode); + } + + inst.opcode = Opcode::FMLS; + + let sz = size & 1; + + if sz == 1 && L == 1 { + return Err(DecodeError::InvalidOperand); + } + + if sz == 1 && Q == 0 { + return Err(DecodeError::InvalidOperand); + } + + let (index, Rm, size) = if size == 0b00 { + let index = (H << 2) | (L << 1) | M; + (index, Rm, SIMDSizeCode::H) + } else if size == 0b10 { + // `sz == 0` + let index = (H << 1) | L; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::S) + } else { + // `sz == 1` + let index = H; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::D) + }; + + let datasize = if Q == 1 { SIMDSizeCode::Q } else { SIMDSizeCode::D }; + + inst.operands = [ + Operand::SIMDRegisterElements(datasize, Rd as u16, size), + Operand::SIMDRegisterElements(datasize, Rn as u16, size), + Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rm as u16, size, index as u8), + Operand::Nothing, + ]; } 0b0_1001 => { - // TODO: // FMUL (not size=0b01) + if size == 0b01 { + return Err(DecodeError::InvalidOpcode); + } + + inst.opcode = Opcode::FMUL; + + let sz = size & 1; + + if sz == 1 && L == 1 { + return Err(DecodeError::InvalidOperand); + } + + if sz == 1 && Q == 0 { + return Err(DecodeError::InvalidOperand); + } + + let (index, Rm, size) = if size == 0b00 { + let index = (H << 2) | (L << 1) | M; + (index, Rm, SIMDSizeCode::H) + } else if size == 0b10 { + // `sz == 0` + let index = (H << 1) | L; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::S) + } else { + // `sz == 1` + let index = H; + let Rm = (M << 4) | Rm; + (index, Rm, SIMDSizeCode::D) + }; + + let datasize = if Q == 1 { SIMDSizeCode::Q } else { SIMDSizeCode::D }; + + inst.operands = [ + Operand::SIMDRegisterElements(datasize, Rd as u16, size), + Operand::SIMDRegisterElements(datasize, Rn as u16, size), + Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rm as u16, size, index as u8), + Operand::Nothing, + ]; } 0b1_0000 => { if size == 0b00 || size == 0b11 { -- cgit v1.1