25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_arm_instr_dpi.c,v 1.11 2005/10/22 12:22:13 debug Exp $ |
* $Id: cpu_arm_instr_dpi.c,v 1.16 2005/11/19 18:53:07 debug Exp $ |
29 |
* |
* |
30 |
* |
* |
31 |
* ARM Data Processing Instructions |
* ARM Data Processing Instructions |
69 |
*/ |
*/ |
70 |
void A__NAME(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME(struct cpu *cpu, struct arm_instr_call *ic) |
71 |
{ |
{ |
72 |
|
#if defined(A__RSB) || defined(A__RSC) |
73 |
|
#define VAR_A b |
74 |
|
#define VAR_B a |
75 |
|
#else |
76 |
|
#define VAR_A a |
77 |
|
#define VAR_B b |
78 |
|
#endif |
79 |
|
|
80 |
#ifdef A__REG |
#ifdef A__REG |
81 |
uint32_t (*reg_func)(struct cpu *, struct arm_instr_call *) |
uint32_t (*reg_func)(struct cpu *, struct arm_instr_call *) |
82 |
= (void *)(size_t)ic->arg[1]; |
= (void *)(size_t)ic->arg[1]; |
95 |
#else |
#else |
96 |
uint32_t |
uint32_t |
97 |
#endif |
#endif |
98 |
c64, |
VAR_B = |
|
#if !defined(A__MOV) && !defined(A__MVN) |
|
|
a = reg(ic->arg[0]), |
|
|
#endif |
|
|
b = |
|
99 |
#ifdef A__REG |
#ifdef A__REG |
100 |
reg_func(cpu, ic); |
reg_func(cpu, ic) |
101 |
|
#else |
102 |
|
#ifdef A__REGSHORT |
103 |
|
reg(ic->arg[1]) |
104 |
#else |
#else |
105 |
ic->arg[1]; |
ic->arg[1] |
106 |
#endif |
#endif |
107 |
|
#endif |
108 |
|
, c64 |
109 |
|
#if !defined(A__MOV) && !defined(A__MVN) |
110 |
|
, VAR_A = reg(ic->arg[0]) |
111 |
|
#endif |
112 |
|
; |
113 |
|
|
114 |
#if defined(A__MOV) || defined(A__MVN) || defined(A__TST) || defined(A__TEQ) \ |
#if defined(A__MOV) || defined(A__MVN) || defined(A__TST) || defined(A__TEQ) \ |
115 |
|| defined(A__AND) || defined(A__BIC) || defined(A__EOR) || defined(A__ORR) |
|| defined(A__AND) || defined(A__BIC) || defined(A__EOR) || defined(A__ORR) |
123 |
* TODO 2: Perhaps this check should be moved out from here, and into |
* TODO 2: Perhaps this check should be moved out from here, and into |
124 |
* cpu_arm_instr.c. (More correct, and higher performance.) |
* cpu_arm_instr.c. (More correct, and higher performance.) |
125 |
*/ |
*/ |
126 |
if (b > 255) { |
if (VAR_B > 255) { |
127 |
cpu->cd.arm.cpsr &= ~ARM_FLAG_C; |
if (VAR_B & 0x80000000) |
128 |
if (b & 0x80000000) |
cpu->cd.arm.flags |= ARM_F_C; |
129 |
cpu->cd.arm.cpsr |= ARM_FLAG_C; |
else |
130 |
|
cpu->cd.arm.flags &= ~ARM_F_C; |
131 |
} |
} |
132 |
#endif |
#endif |
133 |
#endif |
#endif |
136 |
#if !defined(A__MOV) && !defined(A__MVN) |
#if !defined(A__MOV) && !defined(A__MVN) |
137 |
#ifdef A__PC |
#ifdef A__PC |
138 |
if (ic->arg[0] == (size_t)&cpu->cd.arm.r[ARM_PC]) { |
if (ic->arg[0] == (size_t)&cpu->cd.arm.r[ARM_PC]) { |
139 |
uint32_t low_pc; |
uint32_t low_pc = ((size_t)ic - (size_t) |
|
low_pc = ((size_t)ic - (size_t) |
|
140 |
cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call); |
cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call); |
141 |
a = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) |
VAR_A = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) |
142 |
<< ARM_INSTR_ALIGNMENT_SHIFT); |
<< ARM_INSTR_ALIGNMENT_SHIFT); |
143 |
a += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8; |
VAR_A += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8; |
144 |
} |
} |
145 |
#endif |
#endif |
146 |
#endif |
#endif |
147 |
|
|
|
|
|
|
#if defined(A__RSB) || defined(A__RSC) |
|
|
{ uint32_t tmp = a; a = b; b = tmp; } |
|
|
#endif |
|
|
|
|
148 |
/* |
/* |
149 |
* Perform the operation: |
* Perform the operation: |
150 |
*/ |
*/ |
161 |
c64 = a + b; |
c64 = a + b; |
162 |
#endif |
#endif |
163 |
#if defined(A__ADC) |
#if defined(A__ADC) |
164 |
c64 = a + b + (cpu->cd.arm.cpsr & ARM_FLAG_C? 1 : 0); |
c64 = a + b + (cpu->cd.arm.flags & ARM_F_C? 1 : 0); |
165 |
#endif |
#endif |
166 |
#if defined(A__SBC) || defined(A__RSC) |
#if defined(A__SBC) || defined(A__RSC) |
167 |
c64 = a - b - (1 - (cpu->cd.arm.cpsr & ARM_FLAG_C? 1 : 0)); |
b += (cpu->cd.arm.flags & ARM_F_C? 0 : 1); |
168 |
|
c64 = a - b; |
169 |
#endif |
#endif |
170 |
#if defined(A__ORR) |
#if defined(A__ORR) |
171 |
c64 = a | b; |
c64 = a | b; |
187 |
#ifdef A__PC |
#ifdef A__PC |
188 |
if (ic->arg[2] == (size_t)&cpu->cd.arm.r[ARM_PC]) { |
if (ic->arg[2] == (size_t)&cpu->cd.arm.r[ARM_PC]) { |
189 |
#ifndef A__S |
#ifndef A__S |
190 |
uint32_t old_pc = cpu->cd.arm.r[ARM_PC]; |
uint32_t old_pc = cpu->pc; |
191 |
uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1) |
uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1) |
192 |
<< ARM_INSTR_ALIGNMENT_SHIFT) | |
<< ARM_INSTR_ALIGNMENT_SHIFT) | |
193 |
((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1); |
((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1); |
194 |
#endif |
#endif |
195 |
cpu->pc = reg(ic->arg[2]) = c64; |
cpu->pc = (uint32_t)c64; |
196 |
#ifdef A__S |
#ifdef A__S |
197 |
/* Copy the right SPSR into CPSR: */ |
/* Copy the right SPSR into CPSR: */ |
198 |
arm_save_register_bank(cpu); |
arm_save_register_bank(cpu); |
207 |
cpu->cd.arm.cpsr = cpu->cd.arm.spsr_abt; break; |
cpu->cd.arm.cpsr = cpu->cd.arm.spsr_abt; break; |
208 |
case ARM_MODE_UND32: |
case ARM_MODE_UND32: |
209 |
cpu->cd.arm.cpsr = cpu->cd.arm.spsr_und; break; |
cpu->cd.arm.cpsr = cpu->cd.arm.spsr_und; break; |
|
default:fatal("huh? weird mode in dpi s with pc\n"); |
|
|
exit(1); |
|
210 |
} |
} |
211 |
|
cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28; |
212 |
arm_load_register_bank(cpu); |
arm_load_register_bank(cpu); |
213 |
#else |
#else |
214 |
if ((old_pc & ~mask_within_page) == |
if ((old_pc & ~mask_within_page) == |
215 |
(cpu->pc & ~mask_within_page)) { |
((uint32_t)cpu->pc & ~mask_within_page)) { |
216 |
cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page + |
cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page + |
217 |
((cpu->pc & mask_within_page) >> |
((cpu->pc & mask_within_page) >> |
218 |
ARM_INSTR_ALIGNMENT_SHIFT); |
ARM_INSTR_ALIGNMENT_SHIFT); |
233 |
*/ |
*/ |
234 |
#ifdef A__S |
#ifdef A__S |
235 |
c32 = c64; |
c32 = c64; |
236 |
cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N |
cpu->cd.arm.flags |
237 |
#if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \ |
#if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \ |
238 |
|| defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB) |
|| defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB) |
239 |
| ARM_FLAG_V | ARM_FLAG_C |
= 0; |
240 |
|
#else |
241 |
|
&= ~(ARM_F_Z | ARM_F_N); |
242 |
#endif |
#endif |
|
); |
|
243 |
|
|
244 |
#if defined(A__CMP) || defined(A__RSB) || defined(A__SUB) |
#if defined(A__CMP) || defined(A__RSB) || defined(A__SUB) || \ |
245 |
|
defined(A__RSC) || defined(A__SBC) |
246 |
if ((uint32_t)a >= (uint32_t)b) |
if ((uint32_t)a >= (uint32_t)b) |
247 |
cpu->cd.arm.cpsr |= ARM_FLAG_C; |
cpu->cd.arm.flags |= ARM_F_C; |
248 |
#else |
#else |
249 |
#if defined(A__ADC) || defined(A__ADD) || defined(A__CMN) |
#if defined(A__ADC) || defined(A__ADD) || defined(A__CMN) |
250 |
if (c32 != c64) |
if (c32 != c64) |
251 |
cpu->cd.arm.cpsr |= ARM_FLAG_C; |
cpu->cd.arm.flags |= ARM_F_C; |
|
#else |
|
|
#if defined(A__RSC) || defined(A__SBC) |
|
|
{ |
|
|
uint32_t low_pc; |
|
|
low_pc = ((size_t)ic - (size_t) |
|
|
cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call); |
|
|
a = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) |
|
|
<< ARM_INSTR_ALIGNMENT_SHIFT); |
|
|
a += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8; |
|
|
fatal("TODO: C flag: pc = 0x%08x\n", a); |
|
|
exit(1); |
|
|
} |
|
|
#endif |
|
252 |
#endif |
#endif |
253 |
#endif |
#endif |
254 |
|
|
255 |
if (c32 == 0) |
if (c32 == 0) |
256 |
cpu->cd.arm.cpsr |= ARM_FLAG_Z; |
cpu->cd.arm.flags |= ARM_F_Z; |
257 |
|
|
258 |
if ((int32_t)c32 < 0) |
if ((int32_t)c32 < 0) |
259 |
cpu->cd.arm.cpsr |= ARM_FLAG_N; |
cpu->cd.arm.flags |= ARM_F_N; |
260 |
|
|
261 |
/* Calculate the Overflow bit: */ |
/* Calculate the Overflow bit: */ |
262 |
#if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \ |
#if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \ |
270 |
(int32_t)c32 >= 0)) |
(int32_t)c32 >= 0)) |
271 |
v = 1; |
v = 1; |
272 |
#else |
#else |
273 |
#if defined(A__SUB) || defined(A__RSB) || defined(A__CMP) |
#if defined(A__SUB) || defined(A__RSB) || defined(A__CMP) || \ |
274 |
|
defined(A__RSC) || defined(A__SBC) |
275 |
if (((int32_t)a >= 0 && (int32_t)b < 0 && |
if (((int32_t)a >= 0 && (int32_t)b < 0 && |
276 |
(int32_t)c32 < 0) || |
(int32_t)c32 < 0) || |
277 |
((int32_t)a < 0 && (int32_t)b >= 0 && |
((int32_t)a < 0 && (int32_t)b >= 0 && |
278 |
(int32_t)c32 >= 0)) |
(int32_t)c32 >= 0)) |
279 |
v = 1; |
v = 1; |
|
#else |
|
|
fatal("NO\n"); |
|
|
exit(1); |
|
280 |
#endif |
#endif |
281 |
#endif |
#endif |
282 |
if (v) |
if (v) |
283 |
cpu->cd.arm.cpsr |= ARM_FLAG_V; |
cpu->cd.arm.flags |= ARM_F_V; |
284 |
} |
} |
285 |
#endif |
#endif |
286 |
#endif /* A__S */ |
#endif /* A__S */ |
287 |
|
|
288 |
|
#undef VAR_A |
289 |
|
#undef VAR_B |
290 |
} |
} |
291 |
|
|
292 |
|
|
293 |
void A__NAME__eq(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__eq(struct cpu *cpu, struct arm_instr_call *ic) |
294 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_Z) A__NAME(cpu, ic); } |
{ if (cpu->cd.arm.flags & ARM_F_Z) A__NAME(cpu, ic); } |
295 |
void A__NAME__ne(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__ne(struct cpu *cpu, struct arm_instr_call *ic) |
296 |
{ if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); } |
{ if (!(cpu->cd.arm.flags & ARM_F_Z)) A__NAME(cpu, ic); } |
297 |
void A__NAME__cs(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__cs(struct cpu *cpu, struct arm_instr_call *ic) |
298 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_C) A__NAME(cpu, ic); } |
{ if (cpu->cd.arm.flags & ARM_F_C) A__NAME(cpu, ic); } |
299 |
void A__NAME__cc(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__cc(struct cpu *cpu, struct arm_instr_call *ic) |
300 |
{ if (!(cpu->cd.arm.cpsr & ARM_FLAG_C)) A__NAME(cpu, ic); } |
{ if (!(cpu->cd.arm.flags & ARM_F_C)) A__NAME(cpu, ic); } |
301 |
void A__NAME__mi(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__mi(struct cpu *cpu, struct arm_instr_call *ic) |
302 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_N) A__NAME(cpu, ic); } |
{ if (cpu->cd.arm.flags & ARM_F_N) A__NAME(cpu, ic); } |
303 |
void A__NAME__pl(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__pl(struct cpu *cpu, struct arm_instr_call *ic) |
304 |
{ if (!(cpu->cd.arm.cpsr & ARM_FLAG_N)) A__NAME(cpu, ic); } |
{ if (!(cpu->cd.arm.flags & ARM_F_N)) A__NAME(cpu, ic); } |
305 |
void A__NAME__vs(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__vs(struct cpu *cpu, struct arm_instr_call *ic) |
306 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_V) A__NAME(cpu, ic); } |
{ if (cpu->cd.arm.flags & ARM_F_V) A__NAME(cpu, ic); } |
307 |
void A__NAME__vc(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__vc(struct cpu *cpu, struct arm_instr_call *ic) |
308 |
{ if (!(cpu->cd.arm.cpsr & ARM_FLAG_V)) A__NAME(cpu, ic); } |
{ if (!(cpu->cd.arm.flags & ARM_F_V)) A__NAME(cpu, ic); } |
309 |
|
|
310 |
|
#ifndef BLAHURG |
311 |
|
#define BLAHURG |
312 |
|
extern uint8_t condition_hi[16]; |
313 |
|
extern uint8_t condition_ge[16]; |
314 |
|
extern uint8_t condition_gt[16]; |
315 |
|
#endif |
316 |
|
|
317 |
void A__NAME__hi(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__hi(struct cpu *cpu, struct arm_instr_call *ic) |
318 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_C && |
{ if (condition_hi[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
!(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); } |
|
319 |
void A__NAME__ls(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__ls(struct cpu *cpu, struct arm_instr_call *ic) |
320 |
{ if (cpu->cd.arm.cpsr & ARM_FLAG_Z || |
{ if (!condition_hi[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
!(cpu->cd.arm.cpsr & ARM_FLAG_C)) A__NAME(cpu, ic); } |
|
321 |
void A__NAME__ge(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__ge(struct cpu *cpu, struct arm_instr_call *ic) |
322 |
{ if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) == |
{ if (condition_ge[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) A__NAME(cpu, ic); } |
|
323 |
void A__NAME__lt(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__lt(struct cpu *cpu, struct arm_instr_call *ic) |
324 |
{ if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) != |
{ if (!condition_ge[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) A__NAME(cpu, ic); } |
|
325 |
void A__NAME__gt(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__gt(struct cpu *cpu, struct arm_instr_call *ic) |
326 |
{ if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) == |
{ if (condition_gt[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) && |
|
|
!(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); } |
|
327 |
void A__NAME__le(struct cpu *cpu, struct arm_instr_call *ic) |
void A__NAME__le(struct cpu *cpu, struct arm_instr_call *ic) |
328 |
{ if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) != |
{ if (!condition_gt[cpu->cd.arm.flags]) A__NAME(cpu, ic); } |
|
((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) || |
|
|
(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); } |
|
329 |
|
|