| 4154 | } |
| 4155 | |
| 4156 | AddressMode OpDispatchBuilder::DecodeAddress(const X86Tables::DecodedOp& Op, const X86Tables::DecodedOperand& Operand, |
| 4157 | MemoryAccessType AccessType, bool IsLoad) { |
| 4158 | const auto GPRSize = GetGPROpSize(); |
| 4159 | |
| 4160 | AddressMode A {}; |
| 4161 | A.Segment = GetSegment(Op->Flags); |
| 4162 | A.AddrSize = (Op->Flags & X86Tables::DecodeFlags::FLAG_ADDRESS_SIZE) != 0 ? (GPRSize >> 1) : GPRSize; |
| 4163 | A.NonTSO = AccessType == MemoryAccessType::NONTSO || AccessType == MemoryAccessType::STREAM; |
| 4164 | |
| 4165 | if (Operand.IsLiteral()) { |
| 4166 | A.Offset = Operand.Literal(); |
| 4167 | |
| 4168 | if (Operand.Data.Literal.Size != 8 && IsLoad) { |
| 4169 | // zero extend |
| 4170 | uint64_t width = Operand.Data.Literal.Size * 8; |
| 4171 | A.Offset &= ((1ULL << width) - 1); |
| 4172 | } |
| 4173 | } else if (Operand.IsGPR()) { |
| 4174 | // Not an address, let the caller deal with it |
| 4175 | A.AddrSize = GPRSize; |
| 4176 | } else if (Operand.IsGPRDirect()) { |
| 4177 | A.Base = LoadGPRRegister(Operand.Data.GPR.GPR, GPRSize); |
| 4178 | A.NonTSO |= IsNonTSOReg(AccessType, Operand.Data.GPR.GPR); |
| 4179 | } else if (Operand.IsGPRIndirect()) { |
| 4180 | A.Base = LoadGPRRegister(Operand.Data.GPRIndirect.GPR, GPRSize); |
| 4181 | A.Offset = Operand.Data.GPRIndirect.Displacement; |
| 4182 | A.NonTSO |= IsNonTSOReg(AccessType, Operand.Data.GPRIndirect.GPR); |
| 4183 | } else if (Operand.IsRIPRelative()) { |
| 4184 | if (Is64BitMode) { |
| 4185 | A.Base = GetRelocatedPC(Op, Operand.Data.RIPLiteral.Value.s); |
| 4186 | } else { |
| 4187 | // 32bit this isn't RIP relative but instead absolute |
| 4188 | A.Offset = Operand.Data.RIPLiteral.Value.u; |
| 4189 | } |
| 4190 | } else if (Operand.IsSIB()) { |
| 4191 | const bool IsVSIB = IsLoad && ((Op->Flags & X86Tables::DecodeFlags::FLAG_VSIB_BYTE) != 0); |
| 4192 | |
| 4193 | if (Operand.Data.SIB.Base != FEXCore::X86State::REG_INVALID) { |
| 4194 | A.Base = LoadGPRRegister(Operand.Data.SIB.Base, GPRSize); |
| 4195 | } |
| 4196 | |
| 4197 | // NOTE: VSIB cannot have the index * scale portion calculated ahead of time, |
| 4198 | // since the index in this case is a vector. So, we can't just apply the scale |
| 4199 | // to it, since this needs to be applied to each element in the index register |
| 4200 | // after said element has been sign extended. So, we pass this through for the |
| 4201 | // instruction implementation to handle. |
| 4202 | // |
| 4203 | // What we do handle though, is the applying the displacement value to |
| 4204 | // the base register (if a base register is provided), since this is a |
| 4205 | // part of the address calculation that can be done ahead of time. |
| 4206 | if (!IsVSIB && Operand.Data.SIB.Index != FEXCore::X86State::REG_INVALID) { |
| 4207 | A.Index = LoadGPRRegister(Operand.Data.SIB.Index, GPRSize); |
| 4208 | A.IndexScale = Operand.Data.SIB.Scale; |
| 4209 | } |
| 4210 | |
| 4211 | A.Offset = Operand.Data.SIB.Offset; |
| 4212 | A.NonTSO |= IsNonTSOReg(AccessType, Operand.Data.SIB.Base) || IsNonTSOReg(AccessType, Operand.Data.SIB.Index); |
| 4213 | } else { |
nothing calls this directly
no test coverage detected