|
|
1.1 root 1: /*
2: * MIPS emulation micro-operations for qemu.
3: *
4: * Copyright (c) 2004-2005 Jocelyn Mayer
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:
21: #include "config.h"
22: #include "exec.h"
23:
24: #ifndef CALL_FROM_TB0
25: #define CALL_FROM_TB0(func) func();
26: #endif
27: #ifndef CALL_FROM_TB1
28: #define CALL_FROM_TB1(func, arg0) func(arg0);
29: #endif
30: #ifndef CALL_FROM_TB1_CONST16
31: #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
32: #endif
33: #ifndef CALL_FROM_TB2
34: #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
35: #endif
36: #ifndef CALL_FROM_TB2_CONST16
37: #define CALL_FROM_TB2_CONST16(func, arg0, arg1) \
38: CALL_FROM_TB2(func, arg0, arg1);
39: #endif
40: #ifndef CALL_FROM_TB3
41: #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
42: #endif
43: #ifndef CALL_FROM_TB4
44: #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
45: func(arg0, arg1, arg2, arg3);
46: #endif
47:
48: #define REG 1
49: #include "op_template.c"
50: #undef REG
51: #define REG 2
52: #include "op_template.c"
53: #undef REG
54: #define REG 3
55: #include "op_template.c"
56: #undef REG
57: #define REG 4
58: #include "op_template.c"
59: #undef REG
60: #define REG 5
61: #include "op_template.c"
62: #undef REG
63: #define REG 6
64: #include "op_template.c"
65: #undef REG
66: #define REG 7
67: #include "op_template.c"
68: #undef REG
69: #define REG 8
70: #include "op_template.c"
71: #undef REG
72: #define REG 9
73: #include "op_template.c"
74: #undef REG
75: #define REG 10
76: #include "op_template.c"
77: #undef REG
78: #define REG 11
79: #include "op_template.c"
80: #undef REG
81: #define REG 12
82: #include "op_template.c"
83: #undef REG
84: #define REG 13
85: #include "op_template.c"
86: #undef REG
87: #define REG 14
88: #include "op_template.c"
89: #undef REG
90: #define REG 15
91: #include "op_template.c"
92: #undef REG
93: #define REG 16
94: #include "op_template.c"
95: #undef REG
96: #define REG 17
97: #include "op_template.c"
98: #undef REG
99: #define REG 18
100: #include "op_template.c"
101: #undef REG
102: #define REG 19
103: #include "op_template.c"
104: #undef REG
105: #define REG 20
106: #include "op_template.c"
107: #undef REG
108: #define REG 21
109: #include "op_template.c"
110: #undef REG
111: #define REG 22
112: #include "op_template.c"
113: #undef REG
114: #define REG 23
115: #include "op_template.c"
116: #undef REG
117: #define REG 24
118: #include "op_template.c"
119: #undef REG
120: #define REG 25
121: #include "op_template.c"
122: #undef REG
123: #define REG 26
124: #include "op_template.c"
125: #undef REG
126: #define REG 27
127: #include "op_template.c"
128: #undef REG
129: #define REG 28
130: #include "op_template.c"
131: #undef REG
132: #define REG 29
133: #include "op_template.c"
134: #undef REG
135: #define REG 30
136: #include "op_template.c"
137: #undef REG
138: #define REG 31
139: #include "op_template.c"
140: #undef REG
141:
142: #define TN T0
143: #include "op_template.c"
144: #undef TN
145: #define TN T1
146: #include "op_template.c"
147: #undef TN
148: #define TN T2
149: #include "op_template.c"
150: #undef TN
151:
152: void op_dup_T0 (void)
153: {
154: T2 = T0;
155: RETURN();
156: }
157:
158: void op_load_HI (void)
159: {
160: T0 = env->HI;
161: RETURN();
162: }
163:
164: void op_store_HI (void)
165: {
166: env->HI = T0;
167: RETURN();
168: }
169:
170: void op_load_LO (void)
171: {
172: T0 = env->LO;
173: RETURN();
174: }
175:
176: void op_store_LO (void)
177: {
178: env->LO = T0;
179: RETURN();
180: }
181:
182: /* Load and store */
183: #define MEMSUFFIX _raw
184: #include "op_mem.c"
185: #undef MEMSUFFIX
186: #if !defined(CONFIG_USER_ONLY)
187: #define MEMSUFFIX _user
188: #include "op_mem.c"
189: #undef MEMSUFFIX
190:
191: #define MEMSUFFIX _kernel
192: #include "op_mem.c"
193: #undef MEMSUFFIX
194: #endif
195:
196: /* Arithmetic */
197: void op_add (void)
198: {
199: T0 += T1;
200: RETURN();
201: }
202:
203: void op_addo (void)
204: {
205: target_ulong tmp;
206:
207: tmp = T0;
208: T0 += T1;
1.1.1.3 ! root 209: if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
! 210: /* operands of same sign, result different sign */
1.1.1.2 root 211: CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1 root 212: }
213: RETURN();
214: }
215:
216: void op_sub (void)
217: {
218: T0 -= T1;
219: RETURN();
220: }
221:
222: void op_subo (void)
223: {
224: target_ulong tmp;
225:
226: tmp = T0;
227: T0 = (int32_t)T0 - (int32_t)T1;
1.1.1.3 ! root 228: if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
! 229: /* operands of different sign, first operand and result different sign */
1.1.1.2 root 230: CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1 root 231: }
232: RETURN();
233: }
234:
235: void op_mul (void)
236: {
237: T0 = (int32_t)T0 * (int32_t)T1;
238: RETURN();
239: }
240:
241: void op_div (void)
242: {
243: if (T1 != 0) {
244: env->LO = (int32_t)T0 / (int32_t)T1;
245: env->HI = (int32_t)T0 % (int32_t)T1;
246: }
247: RETURN();
248: }
249:
250: void op_divu (void)
251: {
252: if (T1 != 0) {
253: env->LO = T0 / T1;
254: env->HI = T0 % T1;
255: }
256: RETURN();
257: }
258:
259: /* Logical */
260: void op_and (void)
261: {
262: T0 &= T1;
263: RETURN();
264: }
265:
266: void op_nor (void)
267: {
268: T0 = ~(T0 | T1);
269: RETURN();
270: }
271:
272: void op_or (void)
273: {
274: T0 |= T1;
275: RETURN();
276: }
277:
278: void op_xor (void)
279: {
280: T0 ^= T1;
281: RETURN();
282: }
283:
284: void op_sll (void)
285: {
286: T0 = T0 << T1;
287: RETURN();
288: }
289:
290: void op_sra (void)
291: {
292: T0 = (int32_t)T0 >> T1;
293: RETURN();
294: }
295:
296: void op_srl (void)
297: {
298: T0 = T0 >> T1;
299: RETURN();
300: }
301:
302: void op_sllv (void)
303: {
304: T0 = T1 << (T0 & 0x1F);
305: RETURN();
306: }
307:
308: void op_srav (void)
309: {
310: T0 = (int32_t)T1 >> (T0 & 0x1F);
311: RETURN();
312: }
313:
314: void op_srlv (void)
315: {
316: T0 = T1 >> (T0 & 0x1F);
317: RETURN();
318: }
319:
320: void op_clo (void)
321: {
322: int n;
323:
324: if (T0 == (target_ulong)-1) {
325: T0 = 32;
326: } else {
327: for (n = 0; n < 32; n++) {
328: if (!(T0 & (1 << 31)))
329: break;
330: T0 = T0 << 1;
331: }
332: T0 = n;
333: }
334: RETURN();
335: }
336:
337: void op_clz (void)
338: {
339: int n;
340:
341: if (T0 == 0) {
342: T0 = 32;
343: } else {
344: for (n = 0; n < 32; n++) {
345: if (T0 & (1 << 31))
346: break;
347: T0 = T0 << 1;
348: }
349: T0 = n;
350: }
351: RETURN();
352: }
353:
354: /* 64 bits arithmetic */
355: #if (HOST_LONG_BITS == 64)
356: static inline uint64_t get_HILO (void)
357: {
358: return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
359: }
360:
361: static inline void set_HILO (uint64_t HILO)
362: {
363: env->LO = HILO & 0xFFFFFFFF;
364: env->HI = HILO >> 32;
365: }
366:
367: void op_mult (void)
368: {
1.1.1.2 root 369: set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 370: RETURN();
371: }
372:
373: void op_multu (void)
374: {
375: set_HILO((uint64_t)T0 * (uint64_t)T1);
376: RETURN();
377: }
378:
379: void op_madd (void)
380: {
381: int64_t tmp;
382:
1.1.1.2 root 383: tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 384: set_HILO((int64_t)get_HILO() + tmp);
385: RETURN();
386: }
387:
388: void op_maddu (void)
389: {
390: uint64_t tmp;
391:
392: tmp = ((uint64_t)T0 * (uint64_t)T1);
393: set_HILO(get_HILO() + tmp);
394: RETURN();
395: }
396:
397: void op_msub (void)
398: {
399: int64_t tmp;
400:
1.1.1.2 root 401: tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1 root 402: set_HILO((int64_t)get_HILO() - tmp);
403: RETURN();
404: }
405:
406: void op_msubu (void)
407: {
408: uint64_t tmp;
409:
410: tmp = ((uint64_t)T0 * (uint64_t)T1);
411: set_HILO(get_HILO() - tmp);
412: RETURN();
413: }
414: #else
415: void op_mult (void)
416: {
417: CALL_FROM_TB0(do_mult);
418: RETURN();
419: }
420:
421: void op_multu (void)
422: {
423: CALL_FROM_TB0(do_multu);
424: RETURN();
425: }
426:
427: void op_madd (void)
428: {
429: CALL_FROM_TB0(do_madd);
430: RETURN();
431: }
432:
433: void op_maddu (void)
434: {
435: CALL_FROM_TB0(do_maddu);
436: RETURN();
437: }
438:
439: void op_msub (void)
440: {
441: CALL_FROM_TB0(do_msub);
442: RETURN();
443: }
444:
445: void op_msubu (void)
446: {
447: CALL_FROM_TB0(do_msubu);
448: RETURN();
449: }
450: #endif
451:
452: /* Conditional moves */
453: void op_movn (void)
454: {
455: if (T1 != 0)
456: env->gpr[PARAM1] = T0;
457: RETURN();
458: }
459:
460: void op_movz (void)
461: {
462: if (T1 == 0)
463: env->gpr[PARAM1] = T0;
464: RETURN();
465: }
466:
467: /* Tests */
468: #define OP_COND(name, cond) \
469: void glue(op_, name) (void) \
470: { \
471: if (cond) { \
472: T0 = 1; \
473: } else { \
474: T0 = 0; \
475: } \
476: RETURN(); \
477: }
478:
479: OP_COND(eq, T0 == T1);
480: OP_COND(ne, T0 != T1);
481: OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
482: OP_COND(geu, T0 >= T1);
483: OP_COND(lt, (int32_t)T0 < (int32_t)T1);
484: OP_COND(ltu, T0 < T1);
485: OP_COND(gez, (int32_t)T0 >= 0);
486: OP_COND(gtz, (int32_t)T0 > 0);
487: OP_COND(lez, (int32_t)T0 <= 0);
488: OP_COND(ltz, (int32_t)T0 < 0);
489:
490: /* Branchs */
491: //#undef USE_DIRECT_JUMP
1.1.1.2 root 492:
493: void OPPROTO op_goto_tb0(void)
494: {
495: GOTO_TB(op_goto_tb0, PARAM1, 0);
496: }
497:
498: void OPPROTO op_goto_tb1(void)
499: {
500: GOTO_TB(op_goto_tb1, PARAM1, 1);
501: }
1.1 root 502:
503: /* Branch to register */
504: void op_save_breg_target (void)
505: {
506: env->btarget = T2;
507: }
508:
509: void op_restore_breg_target (void)
510: {
511: T2 = env->btarget;
512: }
513:
514: void op_breg (void)
515: {
516: env->PC = T2;
517: RETURN();
518: }
519:
520: void op_save_btarget (void)
521: {
522: env->btarget = PARAM1;
523: RETURN();
524: }
525:
526: /* Conditional branch */
527: void op_set_bcond (void)
528: {
529: T2 = T0;
530: RETURN();
531: }
532:
533: void op_save_bcond (void)
534: {
535: env->bcond = T2;
536: RETURN();
537: }
538:
539: void op_restore_bcond (void)
540: {
541: T2 = env->bcond;
542: RETURN();
543: }
544:
1.1.1.2 root 545: void op_jnz_T2 (void)
1.1 root 546: {
1.1.1.2 root 547: if (T2)
548: GOTO_LABEL_PARAM(1);
1.1 root 549: RETURN();
550: }
551:
552: /* CP0 functions */
553: void op_mfc0 (void)
554: {
555: CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
556: RETURN();
557: }
558:
559: void op_mtc0 (void)
560: {
561: CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
562: RETURN();
563: }
564:
565: #if defined(MIPS_USES_R4K_TLB)
566: void op_tlbwi (void)
567: {
568: CALL_FROM_TB0(do_tlbwi);
569: RETURN();
570: }
571:
572: void op_tlbwr (void)
573: {
574: CALL_FROM_TB0(do_tlbwr);
575: RETURN();
576: }
577:
578: void op_tlbp (void)
579: {
580: CALL_FROM_TB0(do_tlbp);
581: RETURN();
582: }
583:
584: void op_tlbr (void)
585: {
586: CALL_FROM_TB0(do_tlbr);
587: RETURN();
588: }
589: #endif
590:
591: /* Specials */
592: void op_pmon (void)
593: {
594: CALL_FROM_TB1(do_pmon, PARAM1);
595: }
596:
597: void op_trap (void)
598: {
599: if (T0) {
1.1.1.2 root 600: CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1.1 root 601: }
602: RETURN();
603: }
604:
1.1.1.2 root 605: void op_debug (void)
606: {
1.1.1.3 ! root 607: CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1.1.1.2 root 608: }
609:
1.1 root 610: void op_set_lladdr (void)
611: {
612: env->CP0_LLAddr = T2;
613: }
614:
615: void debug_eret (void);
616: void op_eret (void)
617: {
618: CALL_FROM_TB0(debug_eret);
619: if (env->hflags & MIPS_HFLAG_ERL) {
620: env->PC = env->CP0_ErrorEPC;
621: env->hflags &= ~MIPS_HFLAG_ERL;
622: } else {
623: env->PC = env->CP0_EPC;
624: env->hflags &= ~MIPS_HFLAG_EXL;
625: }
626: env->CP0_LLAddr = 1;
627: }
628:
629: void op_deret (void)
630: {
631: CALL_FROM_TB0(debug_eret);
632: env->PC = env->CP0_DEPC;
633: }
634:
635: void op_save_state (void)
636: {
637: env->hflags = PARAM1;
638: RETURN();
639: }
640:
641: void op_save_pc (void)
642: {
643: env->PC = PARAM1;
644: RETURN();
645: }
646:
647: void op_raise_exception (void)
648: {
649: CALL_FROM_TB1(do_raise_exception, PARAM1);
650: RETURN();
651: }
652:
653: void op_raise_exception_err (void)
654: {
655: CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
656: RETURN();
657: }
658:
659: void op_exit_tb (void)
660: {
661: EXIT_TB();
662: }
663:
1.1.1.2 root 664: void op_wait (void)
665: {
666: env->halted = 1;
667: CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
668: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.