Skip to content

Commit f465b40

Browse files
committed
ARM: optimize LSL, LSR, ASR and ROR arithmetic
1 parent cbd3f63 commit f465b40

File tree

2 files changed

+32
-56
lines changed

2 files changed

+32
-56
lines changed

src/nba/src/arm/arm7tdmi.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#pragma once
99

1010
#include <array>
11+
#include <algorithm>
1112
#include <nba/common/compiler.hpp>
1213
#include <nba/log.hpp>
1314
#include <nba/save_state.hpp>

src/nba/src/arm/handlers/arithmetic.inl

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -195,79 +195,54 @@ void DoShift(int opcode, u32& operand, u8 amount, int& carry, bool immediate) {
195195
}
196196

197197
void LSL(u32& operand, u8 amount, int& carry) {
198-
if (amount == 0) return;
199-
200-
if (amount >= 32) {
201-
if (amount > 32) {
202-
carry = 0;
203-
} else {
204-
carry = operand & 1;
205-
}
206-
operand = 0;
207-
return;
198+
const int adj_amount = std::min<int>(amount, 33);
199+
const u32 result = (u32)((u64)operand << adj_amount);
200+
if(adj_amount != 0) {
201+
carry = (u32)((u64)operand << (adj_amount - 1)) >> 31;
208202
}
209-
210-
carry = (operand << (amount - 1)) >> 31;
211-
operand <<= amount;
203+
operand = result;
212204
}
213205

214206
void LSR(u32& operand, u8 amount, int& carry, bool immediate) {
215-
if (amount == 0) {
216-
// LSR #0 equals to LSR #32
217-
if (immediate) {
218-
amount = 32;
219-
} else {
220-
return;
221-
}
207+
// LSR #32 is encoded as LSR #0
208+
if(immediate && amount == 0) {
209+
amount = 32;
222210
}
223211

224-
if (amount >= 32) {
225-
if (amount > 32) {
226-
carry = 0;
227-
} else {
228-
carry = operand >> 31;
229-
}
230-
operand = 0;
231-
return;
212+
const int adj_amount = std::min<int>(amount, 33);
213+
const u32 result = (u32)((u64)operand >> adj_amount);
214+
if(adj_amount != 0) {
215+
carry = ((u64)operand >> (adj_amount - 1)) & 1u;
232216
}
233-
234-
carry = (operand >> (amount - 1)) & 1;
235-
operand >>= amount;
217+
operand = result;
236218
}
237219

238220
void ASR(u32& operand, u8 amount, int& carry, bool immediate) {
239-
if (amount == 0) {
240-
// ASR #0 equals to ASR #32
241-
if (immediate) {
242-
amount = 32;
243-
} else {
244-
return;
245-
}
221+
// ASR #32 is encoded as ASR #0
222+
if(immediate && amount == 0) {
223+
amount = 32;
246224
}
247225

248-
int msb = operand >> 31;
249-
250-
if (amount >= 32) {
251-
carry = msb;
252-
operand = 0xFFFFFFFF * msb;
253-
return;
226+
const int adj_amount = std::min<int>(amount, 33);
227+
const u32 result = (u32)((s64)(s32)operand >> adj_amount);
228+
if(adj_amount != 0) {
229+
carry = ((s64)(s32)operand >> (adj_amount - 1)) & 1u;
254230
}
255-
256-
carry = (operand >> (amount - 1)) & 1;
257-
operand = (operand >> amount) | ((0xFFFFFFFF * msb) << (32 - amount));
231+
operand = result;
258232
}
259233

260234
void ROR(u32& operand, u8 amount, int& carry, bool immediate) {
261-
// ROR #0 equals to RRX #1
262-
if (amount != 0 || !immediate) {
263-
if (amount == 0) return;
264-
265-
amount %= 32;
266-
operand = (operand >> amount) | (operand << (32 - amount));
267-
carry = operand >> 31;
268-
} else {
269-
auto lsb = operand & 1;
235+
// RRX #1 is encoded as ROR #0
236+
if(immediate && amount == 0) {
237+
const int lsb = operand & 1;
270238
operand = (operand >> 1) | (carry << 31);
271239
carry = lsb;
240+
} else {
241+
if(amount == 0) {
242+
return;
243+
}
244+
const int adj_amount = amount & 31;
245+
operand = (operand >> adj_amount) | (operand << ((32 - adj_amount) & 31));
246+
carry = operand >> 31;
272247
}
273248
}

0 commit comments

Comments
 (0)