]>
Commit | Line | Data |
---|---|---|
4fa551d7 TS |
1 | /* |
2 | * CRIS emulation micro-operations for qemu. | |
3 | * | |
4 | * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | */ | |
20 | #include "exec.h" | |
941db528 | 21 | #include "host-utils.h" |
4fa551d7 TS |
22 | |
23 | #define REGNAME r0 | |
24 | #define REG (env->regs[0]) | |
25 | #include "op_template.h" | |
26 | ||
27 | #define REGNAME r1 | |
28 | #define REG (env->regs[1]) | |
29 | #include "op_template.h" | |
30 | ||
31 | #define REGNAME r2 | |
32 | #define REG (env->regs[2]) | |
33 | #include "op_template.h" | |
34 | ||
35 | #define REGNAME r3 | |
36 | #define REG (env->regs[3]) | |
37 | #include "op_template.h" | |
38 | ||
39 | #define REGNAME r4 | |
40 | #define REG (env->regs[4]) | |
41 | #include "op_template.h" | |
42 | ||
43 | #define REGNAME r5 | |
44 | #define REG (env->regs[5]) | |
45 | #include "op_template.h" | |
46 | ||
47 | #define REGNAME r6 | |
48 | #define REG (env->regs[6]) | |
49 | #include "op_template.h" | |
50 | ||
51 | #define REGNAME r7 | |
52 | #define REG (env->regs[7]) | |
53 | #include "op_template.h" | |
54 | ||
55 | #define REGNAME r8 | |
56 | #define REG (env->regs[8]) | |
57 | #include "op_template.h" | |
58 | ||
59 | #define REGNAME r9 | |
60 | #define REG (env->regs[9]) | |
61 | #include "op_template.h" | |
62 | ||
63 | #define REGNAME r10 | |
64 | #define REG (env->regs[10]) | |
65 | #include "op_template.h" | |
66 | ||
67 | #define REGNAME r11 | |
68 | #define REG (env->regs[11]) | |
69 | #include "op_template.h" | |
70 | ||
71 | #define REGNAME r12 | |
72 | #define REG (env->regs[12]) | |
73 | #include "op_template.h" | |
74 | ||
75 | #define REGNAME r13 | |
76 | #define REG (env->regs[13]) | |
77 | #include "op_template.h" | |
78 | ||
79 | #define REGNAME r14 | |
80 | #define REG (env->regs[14]) | |
81 | #include "op_template.h" | |
82 | ||
83 | #define REGNAME r15 | |
84 | #define REG (env->regs[15]) | |
85 | #include "op_template.h" | |
86 | ||
87 | ||
88 | #define REGNAME p0 | |
89 | #define REG (env->pregs[0]) | |
90 | #include "op_template.h" | |
91 | ||
92 | #define REGNAME p1 | |
93 | #define REG (env->pregs[1]) | |
94 | #include "op_template.h" | |
95 | ||
96 | #define REGNAME p2 | |
97 | #define REG (env->pregs[2]) | |
98 | #include "op_template.h" | |
99 | ||
100 | #define REGNAME p3 | |
101 | #define REG (env->pregs[3]) | |
102 | #include "op_template.h" | |
103 | ||
104 | #define REGNAME p4 | |
105 | #define REG (env->pregs[4]) | |
106 | #include "op_template.h" | |
107 | ||
108 | #define REGNAME p5 | |
109 | #define REG (env->pregs[5]) | |
110 | #include "op_template.h" | |
111 | ||
112 | #define REGNAME p6 | |
113 | #define REG (env->pregs[6]) | |
114 | #include "op_template.h" | |
115 | ||
116 | #define REGNAME p7 | |
117 | #define REG (env->pregs[7]) | |
118 | #include "op_template.h" | |
119 | ||
120 | #define REGNAME p8 | |
121 | #define REG (env->pregs[8]) | |
122 | #include "op_template.h" | |
123 | ||
124 | #define REGNAME p9 | |
125 | #define REG (env->pregs[9]) | |
126 | #include "op_template.h" | |
127 | ||
128 | #define REGNAME p10 | |
129 | #define REG (env->pregs[10]) | |
130 | #include "op_template.h" | |
131 | ||
132 | #define REGNAME p11 | |
133 | #define REG (env->pregs[11]) | |
134 | #include "op_template.h" | |
135 | ||
136 | #define REGNAME p12 | |
137 | #define REG (env->pregs[12]) | |
138 | #include "op_template.h" | |
139 | ||
140 | #define REGNAME p13 | |
141 | #define REG (env->pregs[13]) | |
142 | #include "op_template.h" | |
143 | ||
144 | #define REGNAME p14 | |
145 | #define REG (env->pregs[14]) | |
146 | #include "op_template.h" | |
147 | ||
148 | #define REGNAME p15 | |
149 | #define REG (env->pregs[15]) | |
150 | #include "op_template.h" | |
151 | ||
152 | /* Microcode. */ | |
153 | ||
4fa551d7 TS |
154 | void OPPROTO op_break_im(void) |
155 | { | |
786c02f1 | 156 | env->trap_vector = PARAM1; |
4fa551d7 TS |
157 | env->exception_index = EXCP_BREAK; |
158 | cpu_loop_exit(); | |
159 | } | |
160 | ||
161 | void OPPROTO op_debug(void) | |
162 | { | |
163 | env->exception_index = EXCP_DEBUG; | |
164 | cpu_loop_exit(); | |
165 | } | |
166 | ||
167 | void OPPROTO op_exec_insn(void) | |
168 | { | |
169 | env->stats.exec_insns++; | |
170 | RETURN(); | |
171 | } | |
172 | void OPPROTO op_exec_load(void) | |
173 | { | |
174 | env->stats.exec_loads++; | |
175 | RETURN(); | |
176 | } | |
177 | void OPPROTO op_exec_store(void) | |
178 | { | |
179 | env->stats.exec_stores++; | |
180 | RETURN(); | |
181 | } | |
182 | ||
183 | void OPPROTO op_ccs_lshift (void) | |
184 | { | |
185 | uint32_t ccs; | |
186 | ||
187 | /* Apply the ccs shift. */ | |
9004627f | 188 | ccs = env->pregs[PR_CCS]; |
4fa551d7 | 189 | ccs = (ccs & 0xc0000000) | ((ccs << 12) >> 2); |
9004627f | 190 | env->pregs[PR_CCS] = ccs; |
fd56059f | 191 | RETURN(); |
4fa551d7 TS |
192 | } |
193 | void OPPROTO op_ccs_rshift (void) | |
194 | { | |
b41f7df0 | 195 | register uint32_t ccs; |
4fa551d7 TS |
196 | |
197 | /* Apply the ccs shift. */ | |
9004627f | 198 | ccs = env->pregs[PR_CCS]; |
786c02f1 | 199 | ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10); |
b41f7df0 EI |
200 | if (ccs & U_FLAG) |
201 | { | |
202 | /* Enter user mode. */ | |
203 | env->ksp = env->regs[R_SP]; | |
204 | env->regs[R_SP] = env->pregs[PR_USP]; | |
205 | } | |
206 | ||
9004627f | 207 | env->pregs[PR_CCS] = ccs; |
b41f7df0 | 208 | |
fd56059f | 209 | RETURN(); |
4fa551d7 TS |
210 | } |
211 | ||
212 | void OPPROTO op_setf (void) | |
213 | { | |
b41f7df0 EI |
214 | if (!(env->pregs[PR_CCS] & U_FLAG) && (PARAM1 & U_FLAG)) |
215 | { | |
216 | /* Enter user mode. */ | |
217 | env->ksp = env->regs[R_SP]; | |
218 | env->regs[R_SP] = env->pregs[PR_USP]; | |
219 | } | |
220 | ||
9004627f | 221 | env->pregs[PR_CCS] |= PARAM1; |
4fa551d7 TS |
222 | RETURN(); |
223 | } | |
224 | ||
225 | void OPPROTO op_clrf (void) | |
226 | { | |
9004627f | 227 | env->pregs[PR_CCS] &= ~PARAM1; |
4fa551d7 TS |
228 | RETURN(); |
229 | } | |
230 | ||
231 | void OPPROTO op_movl_debug1_T0 (void) | |
232 | { | |
233 | env->debug1 = T0; | |
234 | RETURN(); | |
235 | } | |
236 | ||
237 | void OPPROTO op_movl_debug2_T0 (void) | |
238 | { | |
239 | env->debug2 = T0; | |
240 | RETURN(); | |
241 | } | |
242 | ||
243 | void OPPROTO op_movl_debug3_T0 (void) | |
244 | { | |
245 | env->debug3 = T0; | |
246 | RETURN(); | |
247 | } | |
248 | void OPPROTO op_movl_debug1_T1 (void) | |
249 | { | |
250 | env->debug1 = T1; | |
251 | RETURN(); | |
252 | } | |
253 | ||
254 | void OPPROTO op_movl_debug2_T1 (void) | |
255 | { | |
256 | env->debug2 = T1; | |
257 | RETURN(); | |
258 | } | |
259 | ||
260 | void OPPROTO op_movl_debug3_T1 (void) | |
261 | { | |
262 | env->debug3 = T1; | |
263 | RETURN(); | |
264 | } | |
265 | void OPPROTO op_movl_debug3_im (void) | |
266 | { | |
267 | env->debug3 = PARAM1; | |
268 | RETURN(); | |
269 | } | |
270 | void OPPROTO op_movl_T0_flags (void) | |
271 | { | |
9004627f | 272 | T0 = env->pregs[PR_CCS]; |
4fa551d7 TS |
273 | RETURN(); |
274 | } | |
275 | void OPPROTO op_movl_flags_T0 (void) | |
276 | { | |
9004627f | 277 | env->pregs[PR_CCS] = T0; |
4fa551d7 TS |
278 | RETURN(); |
279 | } | |
280 | ||
281 | void OPPROTO op_movl_sreg_T0 (void) | |
282 | { | |
b41f7df0 EI |
283 | uint32_t srs; |
284 | srs = env->pregs[PR_SRS]; | |
285 | srs &= 3; | |
286 | ||
287 | env->sregs[srs][PARAM1] = T0; | |
4fa551d7 TS |
288 | RETURN(); |
289 | } | |
290 | ||
786c02f1 EI |
291 | void OPPROTO op_movl_tlb_hi_T0 (void) |
292 | { | |
293 | uint32_t srs; | |
294 | srs = env->pregs[PR_SRS]; | |
295 | if (srs == 1 || srs == 2) | |
296 | { | |
297 | /* Writes to tlb-hi write to mm_cause as a side effect. */ | |
298 | env->sregs[SFR_RW_MM_TLB_HI] = T0; | |
299 | env->sregs[SFR_R_MM_CAUSE] = T0; | |
300 | } | |
301 | RETURN(); | |
302 | } | |
303 | ||
4fa551d7 TS |
304 | void OPPROTO op_movl_tlb_lo_T0 (void) |
305 | { | |
786c02f1 | 306 | uint32_t srs; |
b41f7df0 EI |
307 | |
308 | env->pregs[PR_SRS] &= 3; | |
9004627f | 309 | srs = env->pregs[PR_SRS]; |
b41f7df0 | 310 | |
4fa551d7 TS |
311 | if (srs == 1 || srs == 2) |
312 | { | |
786c02f1 EI |
313 | uint32_t set; |
314 | uint32_t idx; | |
4fa551d7 TS |
315 | uint32_t lo, hi; |
316 | ||
317 | idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; | |
318 | set >>= 4; | |
319 | set &= 3; | |
320 | ||
786c02f1 | 321 | idx &= 15; |
4fa551d7 TS |
322 | /* We've just made a write to tlb_lo. */ |
323 | lo = env->sregs[SFR_RW_MM_TLB_LO]; | |
786c02f1 EI |
324 | /* Writes are done via r_mm_cause. */ |
325 | hi = env->sregs[SFR_R_MM_CAUSE]; | |
4fa551d7 TS |
326 | env->tlbsets[srs - 1][set][idx].lo = lo; |
327 | env->tlbsets[srs - 1][set][idx].hi = hi; | |
328 | } | |
4fa551d7 TS |
329 | RETURN(); |
330 | } | |
331 | ||
332 | void OPPROTO op_movl_T0_sreg (void) | |
333 | { | |
b41f7df0 EI |
334 | uint32_t srs; |
335 | env->pregs[PR_SRS] &= 3; | |
336 | srs = env->pregs[PR_SRS]; | |
337 | ||
338 | if (srs == 1 || srs == 2) | |
339 | { | |
340 | uint32_t set; | |
341 | uint32_t idx; | |
342 | uint32_t lo, hi; | |
343 | ||
344 | idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; | |
345 | set >>= 4; | |
346 | set &= 3; | |
347 | idx &= 15; | |
348 | ||
349 | /* Update the mirror regs. */ | |
350 | hi = env->tlbsets[srs - 1][set][idx].hi; | |
351 | lo = env->tlbsets[srs - 1][set][idx].lo; | |
352 | env->sregs[SFR_RW_MM_TLB_HI] = hi; | |
353 | env->sregs[SFR_RW_MM_TLB_LO] = lo; | |
354 | } | |
355 | T0 = env->sregs[srs][PARAM1]; | |
4fa551d7 TS |
356 | RETURN(); |
357 | } | |
358 | ||
359 | void OPPROTO op_update_cc (void) | |
360 | { | |
361 | env->cc_op = PARAM1; | |
362 | env->cc_dest = PARAM2; | |
363 | env->cc_src = PARAM3; | |
364 | RETURN(); | |
365 | } | |
366 | ||
367 | void OPPROTO op_update_cc_op (void) | |
368 | { | |
369 | env->cc_op = PARAM1; | |
370 | RETURN(); | |
371 | } | |
372 | ||
373 | void OPPROTO op_update_cc_mask (void) | |
374 | { | |
375 | env->cc_mask = PARAM1; | |
376 | RETURN(); | |
377 | } | |
378 | ||
379 | void OPPROTO op_update_cc_dest_T0 (void) | |
380 | { | |
381 | env->cc_dest = T0; | |
382 | RETURN(); | |
383 | } | |
384 | ||
385 | void OPPROTO op_update_cc_result_T0 (void) | |
386 | { | |
387 | env->cc_result = T0; | |
388 | RETURN(); | |
389 | } | |
390 | ||
391 | void OPPROTO op_update_cc_size_im (void) | |
392 | { | |
393 | env->cc_size = PARAM1; | |
394 | RETURN(); | |
395 | } | |
396 | ||
397 | void OPPROTO op_update_cc_src_T1 (void) | |
398 | { | |
399 | env->cc_src = T1; | |
400 | RETURN(); | |
401 | } | |
402 | void OPPROTO op_update_cc_x (void) | |
403 | { | |
404 | env->cc_x_live = PARAM1; | |
405 | env->cc_x = PARAM2; | |
406 | RETURN(); | |
407 | } | |
408 | ||
4fa551d7 TS |
409 | void OPPROTO op_extb_T0_T0 (void) |
410 | { | |
411 | T0 = ((int8_t)T0); | |
412 | RETURN(); | |
413 | } | |
414 | void OPPROTO op_extb_T1_T0 (void) | |
415 | { | |
416 | T1 = ((int8_t)T0); | |
417 | RETURN(); | |
418 | } | |
419 | void OPPROTO op_extb_T1_T1 (void) | |
420 | { | |
421 | T1 = ((int8_t)T1); | |
422 | RETURN(); | |
423 | } | |
424 | void OPPROTO op_zextb_T0_T0 (void) | |
425 | { | |
426 | T0 = ((uint8_t)T0); | |
427 | RETURN(); | |
428 | } | |
429 | void OPPROTO op_zextb_T1_T0 (void) | |
430 | { | |
431 | T1 = ((uint8_t)T0); | |
432 | RETURN(); | |
433 | } | |
434 | void OPPROTO op_zextb_T1_T1 (void) | |
435 | { | |
436 | T1 = ((uint8_t)T1); | |
437 | RETURN(); | |
438 | } | |
439 | void OPPROTO op_extw_T0_T0 (void) | |
440 | { | |
441 | T0 = ((int16_t)T0); | |
442 | RETURN(); | |
443 | } | |
444 | void OPPROTO op_extw_T1_T0 (void) | |
445 | { | |
446 | T1 = ((int16_t)T0); | |
447 | RETURN(); | |
448 | } | |
449 | void OPPROTO op_extw_T1_T1 (void) | |
450 | { | |
451 | T1 = ((int16_t)T1); | |
452 | RETURN(); | |
453 | } | |
454 | ||
455 | void OPPROTO op_zextw_T0_T0 (void) | |
456 | { | |
457 | T0 = ((uint16_t)T0); | |
458 | RETURN(); | |
459 | } | |
460 | void OPPROTO op_zextw_T1_T0 (void) | |
461 | { | |
462 | T1 = ((uint16_t)T0); | |
463 | RETURN(); | |
464 | } | |
465 | ||
466 | void OPPROTO op_zextw_T1_T1 (void) | |
467 | { | |
468 | T1 = ((uint16_t)T1); | |
469 | RETURN(); | |
470 | } | |
471 | ||
472 | void OPPROTO op_movl_T0_im (void) | |
473 | { | |
474 | T0 = PARAM1; | |
475 | RETURN(); | |
476 | } | |
477 | void OPPROTO op_movl_T1_im (void) | |
478 | { | |
479 | T1 = PARAM1; | |
480 | RETURN(); | |
481 | } | |
482 | ||
483 | void OPPROTO op_addl_T0_im (void) | |
484 | { | |
485 | T0 += PARAM1; | |
486 | RETURN(); | |
487 | } | |
488 | ||
489 | void OPPROTO op_addl_T1_im (void) | |
490 | { | |
491 | T1 += PARAM1; | |
492 | RETURN(); | |
493 | ||
494 | } | |
495 | void OPPROTO op_subl_T0_im (void) | |
496 | { | |
497 | T0 -= PARAM1; | |
498 | RETURN(); | |
499 | } | |
500 | ||
501 | void OPPROTO op_addxl_T0_C (void) | |
502 | { | |
9004627f EI |
503 | if (env->pregs[PR_CCS] & X_FLAG) |
504 | T0 += !!(env->pregs[PR_CCS] & C_FLAG); | |
4fa551d7 TS |
505 | RETURN(); |
506 | } | |
507 | void OPPROTO op_subxl_T0_C (void) | |
508 | { | |
9004627f EI |
509 | if (env->pregs[PR_CCS] & X_FLAG) |
510 | T0 -= !!(env->pregs[PR_CCS] & C_FLAG); | |
4fa551d7 TS |
511 | RETURN(); |
512 | } | |
513 | void OPPROTO op_addl_T0_C (void) | |
514 | { | |
9004627f | 515 | T0 += !!(env->pregs[PR_CCS] & C_FLAG); |
4fa551d7 TS |
516 | RETURN(); |
517 | } | |
518 | void OPPROTO op_addl_T0_R (void) | |
519 | { | |
9004627f | 520 | T0 += !!(env->pregs[PR_CCS] & R_FLAG); |
4fa551d7 TS |
521 | RETURN(); |
522 | } | |
523 | ||
524 | void OPPROTO op_clr_R (void) | |
525 | { | |
9004627f | 526 | env->pregs[PR_CCS] &= ~R_FLAG; |
4fa551d7 TS |
527 | RETURN(); |
528 | } | |
529 | ||
530 | ||
531 | void OPPROTO op_andl_T0_im (void) | |
532 | { | |
533 | T0 &= PARAM1; | |
534 | RETURN(); | |
535 | } | |
536 | ||
537 | void OPPROTO op_andl_T1_im (void) | |
538 | { | |
539 | T1 &= PARAM1; | |
540 | RETURN(); | |
541 | } | |
542 | ||
543 | void OPPROTO op_movl_T0_T1 (void) | |
544 | { | |
545 | T0 = T1; | |
546 | RETURN(); | |
547 | } | |
548 | ||
549 | void OPPROTO op_swp_T0_T1 (void) | |
550 | { | |
551 | T0 ^= T1; | |
552 | T1 ^= T0; | |
553 | T0 ^= T1; | |
554 | RETURN(); | |
555 | } | |
556 | ||
557 | void OPPROTO op_movl_T1_T0 (void) | |
558 | { | |
559 | T1 = T0; | |
560 | RETURN(); | |
561 | } | |
562 | ||
563 | void OPPROTO op_movl_pc_T0 (void) | |
564 | { | |
565 | env->pc = T0; | |
566 | RETURN(); | |
567 | } | |
568 | ||
569 | void OPPROTO op_movl_T0_0 (void) | |
570 | { | |
571 | T0 = 0; | |
572 | RETURN(); | |
573 | } | |
574 | ||
575 | void OPPROTO op_addl_T0_T1 (void) | |
576 | { | |
577 | T0 += T1; | |
578 | RETURN(); | |
579 | } | |
580 | ||
581 | void OPPROTO op_subl_T0_T1 (void) | |
582 | { | |
583 | T0 -= T1; | |
584 | RETURN(); | |
585 | } | |
586 | ||
587 | void OPPROTO op_absl_T1_T1 (void) | |
588 | { | |
589 | int32_t st = T1; | |
590 | ||
591 | T1 = st < 0 ? -st : st; | |
592 | RETURN(); | |
593 | } | |
594 | ||
595 | void OPPROTO op_muls_T0_T1 (void) | |
596 | { | |
597 | int64_t tmp, t0 ,t1; | |
598 | ||
599 | /* cast into signed values to make GCC sign extend these babies. */ | |
600 | t0 = (int32_t)T0; | |
601 | t1 = (int32_t)T1; | |
602 | ||
603 | tmp = t0 * t1; | |
604 | T0 = tmp & 0xffffffff; | |
9004627f | 605 | env->pregs[PR_MOF] = tmp >> 32; |
4fa551d7 TS |
606 | RETURN(); |
607 | } | |
608 | ||
609 | void OPPROTO op_mulu_T0_T1 (void) | |
610 | { | |
611 | uint64_t tmp, t0 ,t1; | |
612 | t0 = T0; | |
613 | t1 = T1; | |
614 | ||
615 | tmp = t0 * t1; | |
616 | T0 = tmp & 0xffffffff; | |
9004627f | 617 | env->pregs[PR_MOF] = tmp >> 32; |
4fa551d7 TS |
618 | RETURN(); |
619 | } | |
620 | ||
621 | void OPPROTO op_dstep_T0_T1 (void) | |
622 | { | |
623 | T0 <<= 1; | |
624 | if (T0 >= T1) | |
625 | T0 -= T1; | |
626 | RETURN(); | |
627 | } | |
628 | ||
629 | void OPPROTO op_orl_T0_T1 (void) | |
630 | { | |
631 | T0 |= T1; | |
632 | RETURN(); | |
633 | } | |
634 | ||
635 | void OPPROTO op_andl_T0_T1 (void) | |
636 | { | |
637 | T0 &= T1; | |
638 | RETURN(); | |
639 | } | |
640 | ||
641 | void OPPROTO op_xorl_T0_T1 (void) | |
642 | { | |
643 | T0 ^= T1; | |
644 | RETURN(); | |
645 | } | |
646 | ||
647 | void OPPROTO op_lsll_T0_T1 (void) | |
648 | { | |
649 | int s = T1; | |
650 | if (s > 31) | |
651 | T0 = 0; | |
652 | else | |
653 | T0 <<= s; | |
654 | RETURN(); | |
655 | } | |
656 | ||
657 | void OPPROTO op_lsll_T0_im (void) | |
658 | { | |
659 | T0 <<= PARAM1; | |
660 | RETURN(); | |
661 | } | |
662 | ||
663 | void OPPROTO op_lsrl_T0_T1 (void) | |
664 | { | |
665 | int s = T1; | |
666 | if (s > 31) | |
667 | T0 = 0; | |
668 | else | |
669 | T0 >>= s; | |
670 | RETURN(); | |
671 | } | |
672 | ||
673 | /* Rely on GCC emitting an arithmetic shift for signed right shifts. */ | |
674 | void OPPROTO op_asrl_T0_T1 (void) | |
675 | { | |
676 | int s = T1; | |
677 | if (s > 31) | |
678 | T0 = T0 & 0x80000000 ? -1 : 0; | |
679 | else | |
680 | T0 = (int32_t)T0 >> s; | |
681 | RETURN(); | |
682 | } | |
683 | ||
684 | void OPPROTO op_btst_T0_T1 (void) | |
685 | { | |
686 | /* FIXME: clean this up. */ | |
687 | ||
688 | /* des ref: | |
689 | The N flag is set according to the selected bit in the dest reg. | |
690 | The Z flag is set if the selected bit and all bits to the right are | |
691 | zero. | |
bbaf29c7 EI |
692 | The X flag is cleared. |
693 | Other flags are left untouched. | |
4fa551d7 TS |
694 | The destination reg is not affected.*/ |
695 | unsigned int fz, sbit, bset, mask, masked_t0; | |
696 | ||
697 | sbit = T1 & 31; | |
698 | bset = !!(T0 & (1 << sbit)); | |
699 | mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1; | |
700 | masked_t0 = T0 & mask; | |
701 | fz = !(masked_t0 | bset); | |
bbaf29c7 EI |
702 | |
703 | /* Clear the X, N and Z flags. */ | |
704 | T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG); | |
4fa551d7 | 705 | /* Set the N and Z flags accordingly. */ |
bbaf29c7 | 706 | T0 |= (bset << 3) | (fz << 2); |
4fa551d7 TS |
707 | RETURN(); |
708 | } | |
709 | ||
710 | void OPPROTO op_bound_T0_T1 (void) | |
711 | { | |
712 | if (T0 > T1) | |
713 | T0 = T1; | |
714 | RETURN(); | |
715 | } | |
716 | ||
717 | void OPPROTO op_lz_T0_T1 (void) | |
718 | { | |
941db528 | 719 | T0 = clz32(T1); |
4fa551d7 TS |
720 | RETURN(); |
721 | } | |
722 | ||
723 | void OPPROTO op_negl_T0_T1 (void) | |
724 | { | |
725 | T0 = -T1; | |
726 | RETURN(); | |
727 | } | |
728 | ||
729 | void OPPROTO op_negl_T1_T1 (void) | |
730 | { | |
731 | T1 = -T1; | |
732 | RETURN(); | |
733 | } | |
734 | ||
735 | void OPPROTO op_not_T0_T0 (void) | |
736 | { | |
737 | T0 = ~(T0); | |
738 | RETURN(); | |
739 | } | |
740 | void OPPROTO op_not_T1_T1 (void) | |
741 | { | |
742 | T1 = ~(T1); | |
743 | RETURN(); | |
744 | } | |
745 | ||
746 | void OPPROTO op_swapw_T0_T0 (void) | |
747 | { | |
748 | T0 = (T0 << 16) | ((T0 >> 16)); | |
749 | RETURN(); | |
750 | } | |
751 | ||
752 | void OPPROTO op_swapb_T0_T0 (void) | |
753 | { | |
754 | T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff); | |
755 | RETURN(); | |
756 | } | |
757 | ||
758 | void OPPROTO op_swapr_T0_T0 (void) | |
759 | { | |
760 | T0 = (((T0 << 7) & 0x80808080) | | |
761 | ((T0 << 5) & 0x40404040) | | |
762 | ((T0 << 3) & 0x20202020) | | |
763 | ((T0 << 1) & 0x10101010) | | |
764 | ((T0 >> 1) & 0x08080808) | | |
765 | ((T0 >> 3) & 0x04040404) | | |
766 | ((T0 >> 5) & 0x02020202) | | |
767 | ((T0 >> 7) & 0x01010101)); | |
768 | RETURN(); | |
769 | } | |
770 | ||
771 | void OPPROTO op_tst_cc_eq (void) { | |
9004627f | 772 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
773 | int z_set; |
774 | ||
775 | z_set = !!(flags & Z_FLAG); | |
776 | T0 = z_set; | |
777 | RETURN(); | |
778 | } | |
779 | ||
780 | void OPPROTO op_tst_cc_eq_fast (void) { | |
781 | T0 = !(env->cc_result); | |
782 | RETURN(); | |
783 | } | |
784 | ||
785 | void OPPROTO op_tst_cc_ne (void) { | |
9004627f | 786 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
787 | int z_set; |
788 | ||
789 | z_set = !!(flags & Z_FLAG); | |
790 | T0 = !z_set; | |
791 | RETURN(); | |
792 | } | |
793 | void OPPROTO op_tst_cc_ne_fast (void) { | |
794 | T0 = !!(env->cc_result); | |
795 | RETURN(); | |
796 | } | |
797 | ||
798 | void OPPROTO op_tst_cc_cc (void) { | |
9004627f | 799 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
800 | int c_set; |
801 | ||
802 | c_set = !!(flags & C_FLAG); | |
803 | T0 = !c_set; | |
804 | RETURN(); | |
805 | } | |
806 | void OPPROTO op_tst_cc_cs (void) { | |
9004627f | 807 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
808 | int c_set; |
809 | ||
810 | c_set = !!(flags & C_FLAG); | |
811 | T0 = c_set; | |
812 | RETURN(); | |
813 | } | |
814 | ||
815 | void OPPROTO op_tst_cc_vc (void) { | |
9004627f | 816 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
817 | int v_set; |
818 | ||
819 | v_set = !!(flags & V_FLAG); | |
820 | T0 = !v_set; | |
821 | RETURN(); | |
822 | } | |
823 | void OPPROTO op_tst_cc_vs (void) { | |
9004627f | 824 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
825 | int v_set; |
826 | ||
827 | v_set = !!(flags & V_FLAG); | |
828 | T0 = v_set; | |
829 | RETURN(); | |
830 | } | |
831 | void OPPROTO op_tst_cc_pl (void) { | |
9004627f | 832 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
833 | int n_set; |
834 | ||
835 | n_set = !!(flags & N_FLAG); | |
836 | T0 = !n_set; | |
837 | RETURN(); | |
838 | } | |
839 | void OPPROTO op_tst_cc_pl_fast (void) { | |
840 | T0 = ((int32_t)env->cc_result) >= 0; | |
841 | RETURN(); | |
842 | } | |
843 | ||
844 | void OPPROTO op_tst_cc_mi (void) { | |
9004627f | 845 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
846 | int n_set; |
847 | ||
848 | n_set = !!(flags & N_FLAG); | |
849 | T0 = n_set; | |
850 | RETURN(); | |
851 | } | |
852 | void OPPROTO op_tst_cc_mi_fast (void) { | |
853 | T0 = ((int32_t)env->cc_result) < 0; | |
854 | RETURN(); | |
855 | } | |
856 | ||
857 | void OPPROTO op_tst_cc_ls (void) { | |
9004627f | 858 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
859 | int c_set; |
860 | int z_set; | |
861 | ||
862 | c_set = !!(flags & C_FLAG); | |
863 | z_set = !!(flags & Z_FLAG); | |
864 | T0 = c_set || z_set; | |
865 | RETURN(); | |
866 | } | |
867 | void OPPROTO op_tst_cc_hi (void) { | |
9004627f | 868 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
869 | int z_set; |
870 | int c_set; | |
871 | ||
872 | z_set = !!(flags & Z_FLAG); | |
873 | c_set = !!(flags & C_FLAG); | |
874 | T0 = !c_set && !z_set; | |
875 | RETURN(); | |
876 | ||
877 | } | |
878 | ||
879 | void OPPROTO op_tst_cc_ge (void) { | |
9004627f | 880 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
881 | int n_set; |
882 | int v_set; | |
883 | ||
884 | n_set = !!(flags & N_FLAG); | |
885 | v_set = !!(flags & V_FLAG); | |
886 | T0 = (n_set && v_set) || (!n_set && !v_set); | |
887 | RETURN(); | |
888 | } | |
889 | ||
890 | void OPPROTO op_tst_cc_ge_fast (void) { | |
891 | T0 = ((int32_t)env->cc_src < (int32_t)env->cc_dest); | |
892 | RETURN(); | |
893 | } | |
894 | ||
895 | void OPPROTO op_tst_cc_lt (void) { | |
9004627f | 896 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
897 | int n_set; |
898 | int v_set; | |
899 | ||
900 | n_set = !!(flags & N_FLAG); | |
901 | v_set = !!(flags & V_FLAG); | |
902 | T0 = (n_set && !v_set) || (!n_set && v_set); | |
903 | RETURN(); | |
904 | } | |
905 | ||
906 | void OPPROTO op_tst_cc_gt (void) { | |
9004627f | 907 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
908 | int n_set; |
909 | int v_set; | |
910 | int z_set; | |
911 | ||
912 | n_set = !!(flags & N_FLAG); | |
913 | v_set = !!(flags & V_FLAG); | |
914 | z_set = !!(flags & Z_FLAG); | |
915 | T0 = (n_set && v_set && !z_set) | |
916 | || (!n_set && !v_set && !z_set); | |
917 | RETURN(); | |
918 | } | |
919 | ||
920 | void OPPROTO op_tst_cc_le (void) { | |
9004627f | 921 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
922 | int n_set; |
923 | int v_set; | |
924 | int z_set; | |
925 | ||
926 | n_set = !!(flags & N_FLAG); | |
927 | v_set = !!(flags & V_FLAG); | |
928 | z_set = !!(flags & Z_FLAG); | |
929 | T0 = z_set || (n_set && !v_set) || (!n_set && v_set); | |
930 | RETURN(); | |
931 | } | |
932 | ||
933 | void OPPROTO op_tst_cc_p (void) { | |
9004627f | 934 | uint32_t flags = env->pregs[PR_CCS]; |
4fa551d7 TS |
935 | int p_set; |
936 | ||
937 | p_set = !!(flags & P_FLAG); | |
938 | T0 = p_set; | |
939 | RETURN(); | |
940 | } | |
941 | ||
942 | /* Evaluate the if the branch should be taken or not. Needs to be done in | |
943 | the original sequence. The acutal branch is rescheduled to right after the | |
944 | delay-slot. */ | |
945 | void OPPROTO op_evaluate_bcc (void) | |
946 | { | |
947 | env->btaken = T0; | |
948 | RETURN(); | |
949 | } | |
950 | ||
951 | /* this one is used on every alu op, optimize it!. */ | |
952 | void OPPROTO op_goto_if_not_x (void) | |
953 | { | |
9004627f | 954 | if (env->pregs[PR_CCS] & X_FLAG) |
4fa551d7 TS |
955 | GOTO_LABEL_PARAM(1); |
956 | RETURN(); | |
957 | } | |
958 | ||
959 | void OPPROTO op_cc_jmp (void) | |
960 | { | |
961 | if (env->btaken) | |
962 | env->pc = PARAM1; | |
963 | else | |
964 | env->pc = PARAM2; | |
965 | RETURN(); | |
966 | } | |
967 | ||
968 | void OPPROTO op_cc_ngoto (void) | |
969 | { | |
970 | if (!env->btaken) | |
971 | GOTO_LABEL_PARAM(1); | |
972 | RETURN(); | |
973 | } | |
974 | ||
975 | void OPPROTO op_movl_btarget_T0 (void) | |
976 | { | |
977 | env->btarget = T0; | |
978 | RETURN(); | |
979 | } | |
980 | ||
57fec1fe | 981 | void OPPROTO op_jmp1 (void) |
4fa551d7 TS |
982 | { |
983 | env->pc = env->btarget; | |
984 | RETURN(); | |
985 | } |