|
1 | 1 | use crate::bitset::Bitset; |
| 2 | +use crate::jit::assembler::arm::alu_assembler::AluShiftImm; |
2 | 3 | use crate::jit::assembler::arm::branch_assembler::B; |
3 | 4 | use crate::jit::assembler::basic_block::BasicBlock; |
4 | 5 | use crate::jit::assembler::block_inst::{BlockAluOp, BlockAluSetCond, BlockInst, BlockSystemRegOp, BlockTransferOp, BranchEncoding, GuestInstInfo}; |
@@ -214,6 +215,16 @@ impl<'a> BlockAsm<'a> { |
214 | 215 | if op2.operand.needs_reg_for_imm(0xFF) { |
215 | 216 | debug_assert_eq!(op2.shift, BlockShift::default()); |
216 | 217 | let imm = op2.operand.as_imm(); |
| 218 | + |
| 219 | + let msb_ones = (imm.leading_ones() + 0x1) & !0x1; |
| 220 | + if msb_ones != 0 { |
| 221 | + let ror_imm = (imm << msb_ones) | (imm >> (32 - msb_ones)); |
| 222 | + if ror_imm & !0xFF == 0 { |
| 223 | + *op2 = (ror_imm, ShiftType::Ror, msb_ones >> 1).into(); |
| 224 | + return; |
| 225 | + } |
| 226 | + } |
| 227 | + |
217 | 228 | let lsb_zeros = imm.trailing_zeros() & !0x1; |
218 | 229 | if (imm >> lsb_zeros) & !0xFF == 0 { |
219 | 230 | *op2 = (imm >> lsb_zeros, ShiftType::Ror, (32 - lsb_zeros) >> 1).into(); |
@@ -258,30 +269,38 @@ impl<'a> BlockAsm<'a> { |
258 | 269 | } |
259 | 270 |
|
260 | 271 | pub fn load_u8(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
261 | | - self.transfer(BlockTransferOp::Read, op0, op1, op2, false, MemoryAmount::Byte) |
| 272 | + self.transfer_read(op0, op1, op2, false, MemoryAmount::Byte) |
262 | 273 | } |
263 | 274 |
|
264 | 275 | pub fn store_u8(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
265 | | - self.transfer(BlockTransferOp::Write, op0, op1, op2, false, MemoryAmount::Byte) |
| 276 | + self.transfer_write(op0, op1, op2, false, MemoryAmount::Byte) |
266 | 277 | } |
267 | 278 |
|
268 | 279 | pub fn load_u16(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
269 | | - self.transfer(BlockTransferOp::Read, op0, op1, op2, false, MemoryAmount::Half) |
| 280 | + self.transfer_read(op0, op1, op2, false, MemoryAmount::Half) |
270 | 281 | } |
271 | 282 |
|
272 | 283 | pub fn store_u16(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
273 | | - self.transfer(BlockTransferOp::Write, op0, op1, op2, false, MemoryAmount::Half) |
| 284 | + self.transfer_write(op0, op1, op2, false, MemoryAmount::Half) |
274 | 285 | } |
275 | 286 |
|
276 | 287 | pub fn load_u32(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
277 | | - self.transfer(BlockTransferOp::Read, op0, op1, op2, false, MemoryAmount::Word) |
| 288 | + self.transfer_read(op0, op1, op2, false, MemoryAmount::Word) |
278 | 289 | } |
279 | 290 |
|
280 | 291 | pub fn store_u32(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) { |
281 | | - self.transfer(BlockTransferOp::Write, op0, op1, op2, false, MemoryAmount::Word) |
| 292 | + self.transfer_write(op0, op1, op2, false, MemoryAmount::Word) |
| 293 | + } |
| 294 | + |
| 295 | + pub fn transfer_read(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>, signed: bool, amount: MemoryAmount) { |
| 296 | + self.transfer(BlockTransferOp::Read, op0, op1, op2, signed, amount) |
282 | 297 | } |
283 | 298 |
|
284 | | - fn transfer(&mut self, op: BlockTransferOp, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>, signed: bool, amount: MemoryAmount) { |
| 299 | + pub fn transfer_write(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>, signed: bool, amount: MemoryAmount) { |
| 300 | + self.transfer(BlockTransferOp::Write, op0, op1, op2, signed, amount) |
| 301 | + } |
| 302 | + |
| 303 | + pub fn transfer(&mut self, op: BlockTransferOp, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>, signed: bool, amount: MemoryAmount) { |
285 | 304 | let mut op2 = op2.into(); |
286 | 305 | if op2.operand.needs_reg_for_imm(0xFFF) { |
287 | 306 | self.mov(self.tmp_operand_imm_reg, op2.operand); |
@@ -1003,6 +1022,11 @@ impl<'a> BlockAsm<'a> { |
1003 | 1022 | pub fn finalize(&mut self, jit_mem_offset: usize) -> &Vec<u32> { |
1004 | 1023 | for &branch_placeholder in &self.buf.branch_placeholders { |
1005 | 1024 | let encoding = BranchEncoding::from(self.buf.opcodes[branch_placeholder]); |
| 1025 | + if Cond::from(u8::from(encoding.cond())) == Cond::NV { |
| 1026 | + self.buf.opcodes[branch_placeholder] = AluShiftImm::mov_al(Reg::R0, Reg::R0); |
| 1027 | + continue; |
| 1028 | + } |
| 1029 | + |
1006 | 1030 | let diff = if encoding.is_call_common() { |
1007 | 1031 | let opcode_index = (jit_mem_offset >> 2) + branch_placeholder; |
1008 | 1032 | let branch_to = u32::from(encoding.index()) >> 2; |
|
0 commit comments