|
|
1.1 root 1: /*
2: SPARC translation
3:
4: Copyright (C) 2003 Thomas M. Ogrisegg <[email protected]>
5: Copyright (C) 2003-2005 Fabrice Bellard
6:
7: This library is free software; you can redistribute it and/or
8: modify it under the terms of the GNU Lesser General Public
9: License as published by the Free Software Foundation; either
10: version 2 of the License, or (at your option) any later version.
11:
12: This library is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: Lesser General Public License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public
18: License along with this library; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20: */
21:
22: /*
23: TODO-list:
24:
25: Rest of V9 instructions, VIS instructions
26: NPC/PC static optimisations (use JUMP_TB when possible)
27: Optimize synthetic instructions
28: Optional alignment check
29: 128-bit float
30: Tagged add/sub
31: */
32:
33: #include <stdarg.h>
34: #include <stdlib.h>
35: #include <stdio.h>
36: #include <string.h>
37: #include <inttypes.h>
38:
39: #include "cpu.h"
40: #include "exec-all.h"
41: #include "disas.h"
42:
43: #define DEBUG_DISAS
44:
45: #define DYNAMIC_PC 1 /* dynamic pc value */
46: #define JUMP_PC 2 /* dynamic pc value which takes only two values
47: according to jump_pc[T2] */
48:
49: typedef struct DisasContext {
50: target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
51: target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
52: target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
53: int is_br;
54: int mem_idx;
55: struct TranslationBlock *tb;
56: } DisasContext;
57:
58: static uint16_t *gen_opc_ptr;
59: static uint32_t *gen_opparam_ptr;
60: extern FILE *logfile;
61: extern int loglevel;
62:
63: enum {
64: #define DEF(s,n,copy_size) INDEX_op_ ## s,
65: #include "opc.h"
66: #undef DEF
67: NB_OPS
68: };
69:
70: #include "gen-op.h"
71:
72: // This function uses non-native bit order
73: #define GET_FIELD(X, FROM, TO) \
74: ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
75:
76: // This function uses the order in the manuals, i.e. bit 0 is 2^0
77: #define GET_FIELD_SP(X, FROM, TO) \
78: GET_FIELD(X, 31 - (TO), 31 - (FROM))
79:
80: #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
81: #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))
82:
83: #ifdef TARGET_SPARC64
84: #define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))
85: #else
86: #define DFPREG(r) (r)
87: #endif
88:
89: #ifdef USE_DIRECT_JUMP
90: #define TBPARAM(x)
91: #else
92: #define TBPARAM(x) (long)(x)
93: #endif
94:
95: static int sign_extend(int x, int len)
96: {
97: len = 32 - len;
98: return (x << len) >> len;
99: }
100:
101: #define IS_IMM (insn & (1<<13))
102:
103: static void disas_sparc_insn(DisasContext * dc);
104:
105: static GenOpFunc *gen_op_movl_TN_reg[2][32] = {
106: {
107: gen_op_movl_g0_T0,
108: gen_op_movl_g1_T0,
109: gen_op_movl_g2_T0,
110: gen_op_movl_g3_T0,
111: gen_op_movl_g4_T0,
112: gen_op_movl_g5_T0,
113: gen_op_movl_g6_T0,
114: gen_op_movl_g7_T0,
115: gen_op_movl_o0_T0,
116: gen_op_movl_o1_T0,
117: gen_op_movl_o2_T0,
118: gen_op_movl_o3_T0,
119: gen_op_movl_o4_T0,
120: gen_op_movl_o5_T0,
121: gen_op_movl_o6_T0,
122: gen_op_movl_o7_T0,
123: gen_op_movl_l0_T0,
124: gen_op_movl_l1_T0,
125: gen_op_movl_l2_T0,
126: gen_op_movl_l3_T0,
127: gen_op_movl_l4_T0,
128: gen_op_movl_l5_T0,
129: gen_op_movl_l6_T0,
130: gen_op_movl_l7_T0,
131: gen_op_movl_i0_T0,
132: gen_op_movl_i1_T0,
133: gen_op_movl_i2_T0,
134: gen_op_movl_i3_T0,
135: gen_op_movl_i4_T0,
136: gen_op_movl_i5_T0,
137: gen_op_movl_i6_T0,
138: gen_op_movl_i7_T0,
139: },
140: {
141: gen_op_movl_g0_T1,
142: gen_op_movl_g1_T1,
143: gen_op_movl_g2_T1,
144: gen_op_movl_g3_T1,
145: gen_op_movl_g4_T1,
146: gen_op_movl_g5_T1,
147: gen_op_movl_g6_T1,
148: gen_op_movl_g7_T1,
149: gen_op_movl_o0_T1,
150: gen_op_movl_o1_T1,
151: gen_op_movl_o2_T1,
152: gen_op_movl_o3_T1,
153: gen_op_movl_o4_T1,
154: gen_op_movl_o5_T1,
155: gen_op_movl_o6_T1,
156: gen_op_movl_o7_T1,
157: gen_op_movl_l0_T1,
158: gen_op_movl_l1_T1,
159: gen_op_movl_l2_T1,
160: gen_op_movl_l3_T1,
161: gen_op_movl_l4_T1,
162: gen_op_movl_l5_T1,
163: gen_op_movl_l6_T1,
164: gen_op_movl_l7_T1,
165: gen_op_movl_i0_T1,
166: gen_op_movl_i1_T1,
167: gen_op_movl_i2_T1,
168: gen_op_movl_i3_T1,
169: gen_op_movl_i4_T1,
170: gen_op_movl_i5_T1,
171: gen_op_movl_i6_T1,
172: gen_op_movl_i7_T1,
173: }
174: };
175:
176: static GenOpFunc *gen_op_movl_reg_TN[3][32] = {
177: {
178: gen_op_movl_T0_g0,
179: gen_op_movl_T0_g1,
180: gen_op_movl_T0_g2,
181: gen_op_movl_T0_g3,
182: gen_op_movl_T0_g4,
183: gen_op_movl_T0_g5,
184: gen_op_movl_T0_g6,
185: gen_op_movl_T0_g7,
186: gen_op_movl_T0_o0,
187: gen_op_movl_T0_o1,
188: gen_op_movl_T0_o2,
189: gen_op_movl_T0_o3,
190: gen_op_movl_T0_o4,
191: gen_op_movl_T0_o5,
192: gen_op_movl_T0_o6,
193: gen_op_movl_T0_o7,
194: gen_op_movl_T0_l0,
195: gen_op_movl_T0_l1,
196: gen_op_movl_T0_l2,
197: gen_op_movl_T0_l3,
198: gen_op_movl_T0_l4,
199: gen_op_movl_T0_l5,
200: gen_op_movl_T0_l6,
201: gen_op_movl_T0_l7,
202: gen_op_movl_T0_i0,
203: gen_op_movl_T0_i1,
204: gen_op_movl_T0_i2,
205: gen_op_movl_T0_i3,
206: gen_op_movl_T0_i4,
207: gen_op_movl_T0_i5,
208: gen_op_movl_T0_i6,
209: gen_op_movl_T0_i7,
210: },
211: {
212: gen_op_movl_T1_g0,
213: gen_op_movl_T1_g1,
214: gen_op_movl_T1_g2,
215: gen_op_movl_T1_g3,
216: gen_op_movl_T1_g4,
217: gen_op_movl_T1_g5,
218: gen_op_movl_T1_g6,
219: gen_op_movl_T1_g7,
220: gen_op_movl_T1_o0,
221: gen_op_movl_T1_o1,
222: gen_op_movl_T1_o2,
223: gen_op_movl_T1_o3,
224: gen_op_movl_T1_o4,
225: gen_op_movl_T1_o5,
226: gen_op_movl_T1_o6,
227: gen_op_movl_T1_o7,
228: gen_op_movl_T1_l0,
229: gen_op_movl_T1_l1,
230: gen_op_movl_T1_l2,
231: gen_op_movl_T1_l3,
232: gen_op_movl_T1_l4,
233: gen_op_movl_T1_l5,
234: gen_op_movl_T1_l6,
235: gen_op_movl_T1_l7,
236: gen_op_movl_T1_i0,
237: gen_op_movl_T1_i1,
238: gen_op_movl_T1_i2,
239: gen_op_movl_T1_i3,
240: gen_op_movl_T1_i4,
241: gen_op_movl_T1_i5,
242: gen_op_movl_T1_i6,
243: gen_op_movl_T1_i7,
244: },
245: {
246: gen_op_movl_T2_g0,
247: gen_op_movl_T2_g1,
248: gen_op_movl_T2_g2,
249: gen_op_movl_T2_g3,
250: gen_op_movl_T2_g4,
251: gen_op_movl_T2_g5,
252: gen_op_movl_T2_g6,
253: gen_op_movl_T2_g7,
254: gen_op_movl_T2_o0,
255: gen_op_movl_T2_o1,
256: gen_op_movl_T2_o2,
257: gen_op_movl_T2_o3,
258: gen_op_movl_T2_o4,
259: gen_op_movl_T2_o5,
260: gen_op_movl_T2_o6,
261: gen_op_movl_T2_o7,
262: gen_op_movl_T2_l0,
263: gen_op_movl_T2_l1,
264: gen_op_movl_T2_l2,
265: gen_op_movl_T2_l3,
266: gen_op_movl_T2_l4,
267: gen_op_movl_T2_l5,
268: gen_op_movl_T2_l6,
269: gen_op_movl_T2_l7,
270: gen_op_movl_T2_i0,
271: gen_op_movl_T2_i1,
272: gen_op_movl_T2_i2,
273: gen_op_movl_T2_i3,
274: gen_op_movl_T2_i4,
275: gen_op_movl_T2_i5,
276: gen_op_movl_T2_i6,
277: gen_op_movl_T2_i7,
278: }
279: };
280:
281: static GenOpFunc1 *gen_op_movl_TN_im[3] = {
282: gen_op_movl_T0_im,
283: gen_op_movl_T1_im,
284: gen_op_movl_T2_im
285: };
286:
287: // Sign extending version
288: static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
289: gen_op_movl_T0_sim,
290: gen_op_movl_T1_sim,
291: gen_op_movl_T2_sim
292: };
293:
294: #ifdef TARGET_SPARC64
295: #define GEN32(func, NAME) \
296: static GenOpFunc *NAME ## _table [64] = { \
297: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
298: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
299: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
300: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
301: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
302: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
303: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
304: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
305: NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0, \
306: NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0, \
307: NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0, \
308: NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0, \
309: }; \
310: static inline void func(int n) \
311: { \
312: NAME ## _table[n](); \
313: }
314: #else
315: #define GEN32(func, NAME) \
316: static GenOpFunc *NAME ## _table [32] = { \
317: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
318: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
319: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
320: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
321: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
322: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
323: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
324: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
325: }; \
326: static inline void func(int n) \
327: { \
328: NAME ## _table[n](); \
329: }
330: #endif
331:
332: /* floating point registers moves */
333: GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
334: GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
335: GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
336: GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
337:
338: GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
339: GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
340: GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
341: GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
342:
343: #ifdef TARGET_SPARC64
344: // 'a' versions allowed to user depending on asi
345: #if defined(CONFIG_USER_ONLY)
346: #define supervisor(dc) 0
347: #define gen_op_ldst(name) gen_op_##name##_raw()
348: #define OP_LD_TABLE(width) \
349: static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
350: { \
351: int asi, offset; \
352: \
353: if (IS_IMM) { \
354: offset = GET_FIELD(insn, 25, 31); \
355: if (is_ld) \
356: gen_op_ld_asi_reg(offset, size, sign); \
357: else \
358: gen_op_st_asi_reg(offset, size, sign); \
359: return; \
360: } \
361: asi = GET_FIELD(insn, 19, 26); \
362: switch (asi) { \
363: case 0x80: /* Primary address space */ \
364: gen_op_##width##_raw(); \
365: break; \
366: default: \
367: break; \
368: } \
369: }
370:
371: #else
372: #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
373: #define OP_LD_TABLE(width) \
374: static GenOpFunc *gen_op_##width[] = { \
375: &gen_op_##width##_user, \
376: &gen_op_##width##_kernel, \
377: }; \
378: \
379: static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
380: { \
381: int asi, offset; \
382: \
383: if (IS_IMM) { \
384: offset = GET_FIELD(insn, 25, 31); \
385: if (is_ld) \
386: gen_op_ld_asi_reg(offset, size, sign); \
387: else \
388: gen_op_st_asi_reg(offset, size, sign); \
389: return; \
390: } \
391: asi = GET_FIELD(insn, 19, 26); \
392: if (is_ld) \
393: gen_op_ld_asi(asi, size, sign); \
394: else \
395: gen_op_st_asi(asi, size, sign); \
396: }
397:
398: #define supervisor(dc) (dc->mem_idx == 1)
399: #endif
400: #else
401: #if defined(CONFIG_USER_ONLY)
402: #define gen_op_ldst(name) gen_op_##name##_raw()
403: #define OP_LD_TABLE(width)
404: #define supervisor(dc) 0
405: #else
406: #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
407: #define OP_LD_TABLE(width) \
408: static GenOpFunc *gen_op_##width[] = { \
409: &gen_op_##width##_user, \
410: &gen_op_##width##_kernel, \
411: }; \
412: \
413: static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
414: { \
415: int asi; \
416: \
417: asi = GET_FIELD(insn, 19, 26); \
418: switch (asi) { \
419: case 10: /* User data access */ \
420: gen_op_##width##_user(); \
421: break; \
422: case 11: /* Supervisor data access */ \
423: gen_op_##width##_kernel(); \
424: break; \
425: case 0x20 ... 0x2f: /* MMU passthrough */ \
426: if (is_ld) \
427: gen_op_ld_asi(asi, size, sign); \
428: else \
429: gen_op_st_asi(asi, size, sign); \
430: break; \
431: default: \
432: if (is_ld) \
433: gen_op_ld_asi(asi, size, sign); \
434: else \
435: gen_op_st_asi(asi, size, sign); \
436: break; \
437: } \
438: }
439:
440: #define supervisor(dc) (dc->mem_idx == 1)
441: #endif
442: #endif
443:
444: OP_LD_TABLE(ld);
445: OP_LD_TABLE(st);
446: OP_LD_TABLE(ldub);
447: OP_LD_TABLE(lduh);
448: OP_LD_TABLE(ldsb);
449: OP_LD_TABLE(ldsh);
450: OP_LD_TABLE(stb);
451: OP_LD_TABLE(sth);
452: OP_LD_TABLE(std);
453: OP_LD_TABLE(ldstub);
454: OP_LD_TABLE(swap);
455: OP_LD_TABLE(ldd);
456: OP_LD_TABLE(stf);
457: OP_LD_TABLE(stdf);
458: OP_LD_TABLE(ldf);
459: OP_LD_TABLE(lddf);
460:
461: #ifdef TARGET_SPARC64
462: OP_LD_TABLE(ldsw);
463: OP_LD_TABLE(ldx);
464: OP_LD_TABLE(stx);
465: OP_LD_TABLE(cas);
466: OP_LD_TABLE(casx);
467: #endif
468:
469: static inline void gen_movl_imm_TN(int reg, uint32_t imm)
470: {
471: gen_op_movl_TN_im[reg](imm);
472: }
473:
474: static inline void gen_movl_imm_T1(uint32_t val)
475: {
476: gen_movl_imm_TN(1, val);
477: }
478:
479: static inline void gen_movl_imm_T0(uint32_t val)
480: {
481: gen_movl_imm_TN(0, val);
482: }
483:
484: static inline void gen_movl_simm_TN(int reg, int32_t imm)
485: {
486: gen_op_movl_TN_sim[reg](imm);
487: }
488:
489: static inline void gen_movl_simm_T1(int32_t val)
490: {
491: gen_movl_simm_TN(1, val);
492: }
493:
494: static inline void gen_movl_simm_T0(int32_t val)
495: {
496: gen_movl_simm_TN(0, val);
497: }
498:
499: static inline void gen_movl_reg_TN(int reg, int t)
500: {
501: if (reg)
502: gen_op_movl_reg_TN[t][reg] ();
503: else
504: gen_movl_imm_TN(t, 0);
505: }
506:
507: static inline void gen_movl_reg_T0(int reg)
508: {
509: gen_movl_reg_TN(reg, 0);
510: }
511:
512: static inline void gen_movl_reg_T1(int reg)
513: {
514: gen_movl_reg_TN(reg, 1);
515: }
516:
517: static inline void gen_movl_reg_T2(int reg)
518: {
519: gen_movl_reg_TN(reg, 2);
520: }
521:
522: static inline void gen_movl_TN_reg(int reg, int t)
523: {
524: if (reg)
525: gen_op_movl_TN_reg[t][reg] ();
526: }
527:
528: static inline void gen_movl_T0_reg(int reg)
529: {
530: gen_movl_TN_reg(reg, 0);
531: }
532:
533: static inline void gen_movl_T1_reg(int reg)
534: {
535: gen_movl_TN_reg(reg, 1);
536: }
537:
538: static inline void gen_jmp_im(target_ulong pc)
539: {
540: #ifdef TARGET_SPARC64
541: if (pc == (uint32_t)pc) {
542: gen_op_jmp_im(pc);
543: } else {
544: gen_op_jmp_im64(pc >> 32, pc);
545: }
546: #else
547: gen_op_jmp_im(pc);
548: #endif
549: }
550:
551: static inline void gen_movl_npc_im(target_ulong npc)
552: {
553: #ifdef TARGET_SPARC64
554: if (npc == (uint32_t)npc) {
555: gen_op_movl_npc_im(npc);
556: } else {
557: gen_op_movq_npc_im64(npc >> 32, npc);
558: }
559: #else
560: gen_op_movl_npc_im(npc);
561: #endif
562: }
563:
564: static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
565: {
566: int l1;
567:
568: l1 = gen_new_label();
569:
570: gen_op_jz_T2_label(l1);
571:
572: gen_op_goto_tb0(TBPARAM(tb));
573: gen_jmp_im(pc1);
574: gen_movl_npc_im(pc1 + 4);
575: gen_op_movl_T0_im((long)tb + 0);
576: gen_op_exit_tb();
577:
578: gen_set_label(l1);
579: gen_op_goto_tb1(TBPARAM(tb));
580: gen_jmp_im(pc2);
581: gen_movl_npc_im(pc2 + 4);
582: gen_op_movl_T0_im((long)tb + 1);
583: gen_op_exit_tb();
584: }
585:
586: static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2)
587: {
588: int l1;
589:
590: l1 = gen_new_label();
591:
592: gen_op_jz_T2_label(l1);
593:
594: gen_op_goto_tb0(TBPARAM(tb));
595: gen_jmp_im(pc2);
596: gen_movl_npc_im(pc1);
597: gen_op_movl_T0_im((long)tb + 0);
598: gen_op_exit_tb();
599:
600: gen_set_label(l1);
601: gen_op_goto_tb1(TBPARAM(tb));
602: gen_jmp_im(pc2 + 4);
603: gen_movl_npc_im(pc2 + 8);
604: gen_op_movl_T0_im((long)tb + 1);
605: gen_op_exit_tb();
606: }
607:
608: static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc)
609: {
610: gen_op_goto_tb0(TBPARAM(tb));
611: gen_jmp_im(pc);
612: gen_movl_npc_im(npc);
613: gen_op_movl_T0_im((long)tb + 0);
614: gen_op_exit_tb();
615: }
616:
617: static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2)
618: {
619: int l1, l2;
620:
621: l1 = gen_new_label();
622: l2 = gen_new_label();
623: gen_op_jz_T2_label(l1);
624:
625: gen_movl_npc_im(npc1);
626: gen_op_jmp_label(l2);
627:
628: gen_set_label(l1);
629: gen_movl_npc_im(npc2);
630: gen_set_label(l2);
631: }
632:
633: /* call this function before using T2 as it may have been set for a jump */
634: static inline void flush_T2(DisasContext * dc)
635: {
636: if (dc->npc == JUMP_PC) {
637: gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
638: dc->npc = DYNAMIC_PC;
639: }
640: }
641:
642: static inline void save_npc(DisasContext * dc)
643: {
644: if (dc->npc == JUMP_PC) {
645: gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
646: dc->npc = DYNAMIC_PC;
647: } else if (dc->npc != DYNAMIC_PC) {
648: gen_movl_npc_im(dc->npc);
649: }
650: }
651:
652: static inline void save_state(DisasContext * dc)
653: {
654: gen_jmp_im(dc->pc);
655: save_npc(dc);
656: }
657:
658: static inline void gen_mov_pc_npc(DisasContext * dc)
659: {
660: if (dc->npc == JUMP_PC) {
661: gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]);
662: gen_op_mov_pc_npc();
663: dc->pc = DYNAMIC_PC;
664: } else if (dc->npc == DYNAMIC_PC) {
665: gen_op_mov_pc_npc();
666: dc->pc = DYNAMIC_PC;
667: } else {
668: dc->pc = dc->npc;
669: }
670: }
671:
672: static GenOpFunc * const gen_cond[2][16] = {
673: {
674: gen_op_eval_ba,
675: gen_op_eval_be,
676: gen_op_eval_ble,
677: gen_op_eval_bl,
678: gen_op_eval_bleu,
679: gen_op_eval_bcs,
680: gen_op_eval_bneg,
681: gen_op_eval_bvs,
682: gen_op_eval_bn,
683: gen_op_eval_bne,
684: gen_op_eval_bg,
685: gen_op_eval_bge,
686: gen_op_eval_bgu,
687: gen_op_eval_bcc,
688: gen_op_eval_bpos,
689: gen_op_eval_bvc,
690: },
691: {
692: #ifdef TARGET_SPARC64
693: gen_op_eval_ba,
694: gen_op_eval_xbe,
695: gen_op_eval_xble,
696: gen_op_eval_xbl,
697: gen_op_eval_xbleu,
698: gen_op_eval_xbcs,
699: gen_op_eval_xbneg,
700: gen_op_eval_xbvs,
701: gen_op_eval_bn,
702: gen_op_eval_xbne,
703: gen_op_eval_xbg,
704: gen_op_eval_xbge,
705: gen_op_eval_xbgu,
706: gen_op_eval_xbcc,
707: gen_op_eval_xbpos,
708: gen_op_eval_xbvc,
709: #endif
710: },
711: };
712:
713: static GenOpFunc * const gen_fcond[4][16] = {
714: {
715: gen_op_eval_ba,
716: gen_op_eval_fbne,
717: gen_op_eval_fblg,
718: gen_op_eval_fbul,
719: gen_op_eval_fbl,
720: gen_op_eval_fbug,
721: gen_op_eval_fbg,
722: gen_op_eval_fbu,
723: gen_op_eval_bn,
724: gen_op_eval_fbe,
725: gen_op_eval_fbue,
726: gen_op_eval_fbge,
727: gen_op_eval_fbuge,
728: gen_op_eval_fble,
729: gen_op_eval_fbule,
730: gen_op_eval_fbo,
731: },
732: #ifdef TARGET_SPARC64
733: {
734: gen_op_eval_ba,
735: gen_op_eval_fbne_fcc1,
736: gen_op_eval_fblg_fcc1,
737: gen_op_eval_fbul_fcc1,
738: gen_op_eval_fbl_fcc1,
739: gen_op_eval_fbug_fcc1,
740: gen_op_eval_fbg_fcc1,
741: gen_op_eval_fbu_fcc1,
742: gen_op_eval_bn,
743: gen_op_eval_fbe_fcc1,
744: gen_op_eval_fbue_fcc1,
745: gen_op_eval_fbge_fcc1,
746: gen_op_eval_fbuge_fcc1,
747: gen_op_eval_fble_fcc1,
748: gen_op_eval_fbule_fcc1,
749: gen_op_eval_fbo_fcc1,
750: },
751: {
752: gen_op_eval_ba,
753: gen_op_eval_fbne_fcc2,
754: gen_op_eval_fblg_fcc2,
755: gen_op_eval_fbul_fcc2,
756: gen_op_eval_fbl_fcc2,
757: gen_op_eval_fbug_fcc2,
758: gen_op_eval_fbg_fcc2,
759: gen_op_eval_fbu_fcc2,
760: gen_op_eval_bn,
761: gen_op_eval_fbe_fcc2,
762: gen_op_eval_fbue_fcc2,
763: gen_op_eval_fbge_fcc2,
764: gen_op_eval_fbuge_fcc2,
765: gen_op_eval_fble_fcc2,
766: gen_op_eval_fbule_fcc2,
767: gen_op_eval_fbo_fcc2,
768: },
769: {
770: gen_op_eval_ba,
771: gen_op_eval_fbne_fcc3,
772: gen_op_eval_fblg_fcc3,
773: gen_op_eval_fbul_fcc3,
774: gen_op_eval_fbl_fcc3,
775: gen_op_eval_fbug_fcc3,
776: gen_op_eval_fbg_fcc3,
777: gen_op_eval_fbu_fcc3,
778: gen_op_eval_bn,
779: gen_op_eval_fbe_fcc3,
780: gen_op_eval_fbue_fcc3,
781: gen_op_eval_fbge_fcc3,
782: gen_op_eval_fbuge_fcc3,
783: gen_op_eval_fble_fcc3,
784: gen_op_eval_fbule_fcc3,
785: gen_op_eval_fbo_fcc3,
786: },
787: #else
788: {}, {}, {},
789: #endif
790: };
791:
792: #ifdef TARGET_SPARC64
793: static void gen_cond_reg(int cond)
794: {
795: switch (cond) {
796: case 0x1:
797: gen_op_eval_brz();
798: break;
799: case 0x2:
800: gen_op_eval_brlez();
801: break;
802: case 0x3:
803: gen_op_eval_brlz();
804: break;
805: case 0x5:
806: gen_op_eval_brnz();
807: break;
808: case 0x6:
809: gen_op_eval_brgz();
810: break;
811: default:
812: case 0x7:
813: gen_op_eval_brgez();
814: break;
815: }
816: }
817: #endif
818:
819: /* XXX: potentially incorrect if dynamic npc */
820: static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
821: {
822: unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
823: target_ulong target = dc->pc + offset;
824:
825: if (cond == 0x0) {
826: /* unconditional not taken */
827: if (a) {
828: dc->pc = dc->npc + 4;
829: dc->npc = dc->pc + 4;
830: } else {
831: dc->pc = dc->npc;
832: dc->npc = dc->pc + 4;
833: }
834: } else if (cond == 0x8) {
835: /* unconditional taken */
836: if (a) {
837: dc->pc = target;
838: dc->npc = dc->pc + 4;
839: } else {
840: dc->pc = dc->npc;
841: dc->npc = target;
842: }
843: } else {
844: flush_T2(dc);
845: gen_cond[cc][cond]();
846: if (a) {
847: gen_branch_a(dc, (long)dc->tb, target, dc->npc);
848: dc->is_br = 1;
849: } else {
850: dc->pc = dc->npc;
851: dc->jump_pc[0] = target;
852: dc->jump_pc[1] = dc->npc + 4;
853: dc->npc = JUMP_PC;
854: }
855: }
856: }
857:
858: /* XXX: potentially incorrect if dynamic npc */
859: static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
860: {
861: unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
862: target_ulong target = dc->pc + offset;
863:
864: if (cond == 0x0) {
865: /* unconditional not taken */
866: if (a) {
867: dc->pc = dc->npc + 4;
868: dc->npc = dc->pc + 4;
869: } else {
870: dc->pc = dc->npc;
871: dc->npc = dc->pc + 4;
872: }
873: } else if (cond == 0x8) {
874: /* unconditional taken */
875: if (a) {
876: dc->pc = target;
877: dc->npc = dc->pc + 4;
878: } else {
879: dc->pc = dc->npc;
880: dc->npc = target;
881: }
882: } else {
883: flush_T2(dc);
884: gen_fcond[cc][cond]();
885: if (a) {
886: gen_branch_a(dc, (long)dc->tb, target, dc->npc);
887: dc->is_br = 1;
888: } else {
889: dc->pc = dc->npc;
890: dc->jump_pc[0] = target;
891: dc->jump_pc[1] = dc->npc + 4;
892: dc->npc = JUMP_PC;
893: }
894: }
895: }
896:
897: #ifdef TARGET_SPARC64
898: /* XXX: potentially incorrect if dynamic npc */
899: static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
900: {
901: unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
902: target_ulong target = dc->pc + offset;
903:
904: flush_T2(dc);
905: gen_cond_reg(cond);
906: if (a) {
907: gen_branch_a(dc, (long)dc->tb, target, dc->npc);
908: dc->is_br = 1;
909: } else {
910: dc->pc = dc->npc;
911: dc->jump_pc[0] = target;
912: dc->jump_pc[1] = dc->npc + 4;
913: dc->npc = JUMP_PC;
914: }
915: }
916:
917: static GenOpFunc * const gen_fcmps[4] = {
918: gen_op_fcmps,
919: gen_op_fcmps_fcc1,
920: gen_op_fcmps_fcc2,
921: gen_op_fcmps_fcc3,
922: };
923:
924: static GenOpFunc * const gen_fcmpd[4] = {
925: gen_op_fcmpd,
926: gen_op_fcmpd_fcc1,
927: gen_op_fcmpd_fcc2,
928: gen_op_fcmpd_fcc3,
929: };
930: #endif
931:
932: /* before an instruction, dc->pc must be static */
933: static void disas_sparc_insn(DisasContext * dc)
934: {
935: unsigned int insn, opc, rs1, rs2, rd;
936:
937: insn = ldl_code(dc->pc);
938: opc = GET_FIELD(insn, 0, 1);
939:
940: rd = GET_FIELD(insn, 2, 6);
941: switch (opc) {
942: case 0: /* branches/sethi */
943: {
944: unsigned int xop = GET_FIELD(insn, 7, 9);
945: int32_t target;
946: switch (xop) {
947: #ifdef TARGET_SPARC64
948: case 0x1: /* V9 BPcc */
949: {
950: int cc;
951:
952: target = GET_FIELD_SP(insn, 0, 18);
953: target <<= 2;
954: target = sign_extend(target, 18);
955: cc = GET_FIELD_SP(insn, 20, 21);
956: if (cc == 0)
957: do_branch(dc, target, insn, 0);
958: else if (cc == 2)
959: do_branch(dc, target, insn, 1);
960: else
961: goto illegal_insn;
962: goto jmp_insn;
963: }
964: case 0x3: /* V9 BPr */
965: {
966: target = GET_FIELD_SP(insn, 0, 13) |
967: (GET_FIELD_SP(insn, 20, 21) >> 7);
968: target <<= 2;
969: target = sign_extend(target, 16);
970: rs1 = GET_FIELD(insn, 13, 17);
971: gen_movl_reg_T0(rs1);
972: do_branch_reg(dc, target, insn);
973: goto jmp_insn;
974: }
975: case 0x5: /* V9 FBPcc */
976: {
977: int cc = GET_FIELD_SP(insn, 20, 21);
978: #if !defined(CONFIG_USER_ONLY)
979: gen_op_trap_ifnofpu();
980: #endif
981: target = GET_FIELD_SP(insn, 0, 18);
982: target <<= 2;
983: target = sign_extend(target, 19);
984: do_fbranch(dc, target, insn, cc);
985: goto jmp_insn;
986: }
987: #endif
988: case 0x2: /* BN+x */
989: {
990: target = GET_FIELD(insn, 10, 31);
991: target <<= 2;
992: target = sign_extend(target, 22);
993: do_branch(dc, target, insn, 0);
994: goto jmp_insn;
995: }
996: case 0x6: /* FBN+x */
997: {
998: #if !defined(CONFIG_USER_ONLY)
999: gen_op_trap_ifnofpu();
1000: #endif
1001: target = GET_FIELD(insn, 10, 31);
1002: target <<= 2;
1003: target = sign_extend(target, 22);
1004: do_fbranch(dc, target, insn, 0);
1005: goto jmp_insn;
1006: }
1007: case 0x4: /* SETHI */
1008: #define OPTIM
1009: #if defined(OPTIM)
1010: if (rd) { // nop
1011: #endif
1012: uint32_t value = GET_FIELD(insn, 10, 31);
1013: gen_movl_imm_T0(value << 10);
1014: gen_movl_T0_reg(rd);
1015: #if defined(OPTIM)
1016: }
1017: #endif
1018: break;
1019: case 0x0: /* UNIMPL */
1020: default:
1021: goto illegal_insn;
1022: }
1023: break;
1024: }
1025: break;
1026: case 1:
1027: /*CALL*/ {
1028: target_long target = GET_FIELDs(insn, 2, 31) << 2;
1029:
1030: #ifdef TARGET_SPARC64
1031: if (dc->pc == (uint32_t)dc->pc) {
1032: gen_op_movl_T0_im(dc->pc);
1033: } else {
1034: gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
1035: }
1036: #else
1037: gen_op_movl_T0_im(dc->pc);
1038: #endif
1039: gen_movl_T0_reg(15);
1040: target += dc->pc;
1041: gen_mov_pc_npc(dc);
1042: dc->npc = target;
1043: }
1044: goto jmp_insn;
1045: case 2: /* FPU & Logical Operations */
1046: {
1047: unsigned int xop = GET_FIELD(insn, 7, 12);
1048: if (xop == 0x3a) { /* generate trap */
1049: int cond;
1050:
1051: rs1 = GET_FIELD(insn, 13, 17);
1052: gen_movl_reg_T0(rs1);
1053: if (IS_IMM) {
1054: rs2 = GET_FIELD(insn, 25, 31);
1055: #if defined(OPTIM)
1056: if (rs2 != 0) {
1057: #endif
1058: gen_movl_simm_T1(rs2);
1059: gen_op_add_T1_T0();
1060: #if defined(OPTIM)
1061: }
1062: #endif
1063: } else {
1064: rs2 = GET_FIELD(insn, 27, 31);
1065: #if defined(OPTIM)
1066: if (rs2 != 0) {
1067: #endif
1068: gen_movl_reg_T1(rs2);
1069: gen_op_add_T1_T0();
1070: #if defined(OPTIM)
1071: }
1072: #endif
1073: }
1074: save_state(dc);
1075: cond = GET_FIELD(insn, 3, 6);
1076: if (cond == 0x8) {
1077: gen_op_trap_T0();
1078: dc->is_br = 1;
1079: goto jmp_insn;
1080: } else if (cond != 0) {
1081: #ifdef TARGET_SPARC64
1082: /* V9 icc/xcc */
1083: int cc = GET_FIELD_SP(insn, 11, 12);
1084: if (cc == 0)
1085: gen_cond[0][cond]();
1086: else if (cc == 2)
1087: gen_cond[1][cond]();
1088: else
1089: goto illegal_insn;
1090: #else
1091: gen_cond[0][cond]();
1092: #endif
1093: gen_op_trapcc_T0();
1094: }
1095: } else if (xop == 0x28) {
1096: rs1 = GET_FIELD(insn, 13, 17);
1097: switch(rs1) {
1098: case 0: /* rdy */
1099: gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
1100: gen_movl_T0_reg(rd);
1101: break;
1102: case 15: /* stbar / V9 membar */
1103: break; /* no effect? */
1104: #ifdef TARGET_SPARC64
1105: case 0x2: /* V9 rdccr */
1106: gen_op_rdccr();
1107: gen_movl_T0_reg(rd);
1108: break;
1109: case 0x3: /* V9 rdasi */
1110: gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
1111: gen_movl_T0_reg(rd);
1112: break;
1113: case 0x4: /* V9 rdtick */
1114: gen_op_rdtick();
1115: gen_movl_T0_reg(rd);
1116: break;
1117: case 0x5: /* V9 rdpc */
1118: gen_op_movl_T0_im(dc->pc);
1119: gen_movl_T0_reg(rd);
1120: break;
1121: case 0x6: /* V9 rdfprs */
1122: gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
1123: gen_movl_T0_reg(rd);
1124: break;
1125: case 0x17: /* Tick compare */
1126: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
1127: gen_movl_T0_reg(rd);
1128: break;
1129: case 0x18: /* System tick */
1130: gen_op_rdtick(); // XXX
1131: gen_movl_T0_reg(rd);
1132: break;
1133: case 0x19: /* System tick compare */
1134: gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
1135: gen_movl_T0_reg(rd);
1136: break;
1137: case 0x10: /* Performance Control */
1138: case 0x11: /* Performance Instrumentation Counter */
1139: case 0x12: /* Dispatch Control */
1140: case 0x13: /* Graphics Status */
1141: case 0x14: /* Softint set, WO */
1142: case 0x15: /* Softint clear, WO */
1143: case 0x16: /* Softint write */
1144: #endif
1145: default:
1146: goto illegal_insn;
1147: }
1148: #if !defined(CONFIG_USER_ONLY)
1149: #ifndef TARGET_SPARC64
1150: } else if (xop == 0x29) { /* rdpsr / V9 unimp */
1151: if (!supervisor(dc))
1152: goto priv_insn;
1153: gen_op_rdpsr();
1154: gen_movl_T0_reg(rd);
1155: break;
1156: #endif
1157: } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1158: if (!supervisor(dc))
1159: goto priv_insn;
1160: #ifdef TARGET_SPARC64
1161: rs1 = GET_FIELD(insn, 13, 17);
1162: switch (rs1) {
1163: case 0: // tpc
1164: gen_op_rdtpc();
1165: break;
1166: case 1: // tnpc
1167: gen_op_rdtnpc();
1168: break;
1169: case 2: // tstate
1170: gen_op_rdtstate();
1171: break;
1172: case 3: // tt
1173: gen_op_rdtt();
1174: break;
1175: case 4: // tick
1176: gen_op_rdtick();
1177: break;
1178: case 5: // tba
1179: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1180: break;
1181: case 6: // pstate
1182: gen_op_rdpstate();
1183: break;
1184: case 7: // tl
1185: gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
1186: break;
1187: case 8: // pil
1188: gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
1189: break;
1190: case 9: // cwp
1191: gen_op_rdcwp();
1192: break;
1193: case 10: // cansave
1194: gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
1195: break;
1196: case 11: // canrestore
1197: gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
1198: break;
1199: case 12: // cleanwin
1200: gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
1201: break;
1202: case 13: // otherwin
1203: gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
1204: break;
1205: case 14: // wstate
1206: gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
1207: break;
1208: case 31: // ver
1209: gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
1210: break;
1211: case 15: // fq
1212: default:
1213: goto illegal_insn;
1214: }
1215: #else
1216: gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
1217: #endif
1218: gen_movl_T0_reg(rd);
1219: break;
1220: } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
1221: #ifdef TARGET_SPARC64
1222: gen_op_flushw();
1223: #else
1224: if (!supervisor(dc))
1225: goto priv_insn;
1226: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1227: gen_movl_T0_reg(rd);
1228: #endif
1229: break;
1230: #endif
1231: } else if (xop == 0x34) { /* FPU Operations */
1232: #if !defined(CONFIG_USER_ONLY)
1233: gen_op_trap_ifnofpu();
1234: #endif
1235: rs1 = GET_FIELD(insn, 13, 17);
1236: rs2 = GET_FIELD(insn, 27, 31);
1237: xop = GET_FIELD(insn, 18, 26);
1238: switch (xop) {
1239: case 0x1: /* fmovs */
1240: gen_op_load_fpr_FT0(rs2);
1241: gen_op_store_FT0_fpr(rd);
1242: break;
1243: case 0x5: /* fnegs */
1244: gen_op_load_fpr_FT1(rs2);
1245: gen_op_fnegs();
1246: gen_op_store_FT0_fpr(rd);
1247: break;
1248: case 0x9: /* fabss */
1249: gen_op_load_fpr_FT1(rs2);
1250: gen_op_fabss();
1251: gen_op_store_FT0_fpr(rd);
1252: break;
1253: case 0x29: /* fsqrts */
1254: gen_op_load_fpr_FT1(rs2);
1255: gen_op_fsqrts();
1256: gen_op_store_FT0_fpr(rd);
1257: break;
1258: case 0x2a: /* fsqrtd */
1259: gen_op_load_fpr_DT1(DFPREG(rs2));
1260: gen_op_fsqrtd();
1261: gen_op_store_DT0_fpr(DFPREG(rd));
1262: break;
1263: case 0x2b: /* fsqrtq */
1264: goto nfpu_insn;
1265: case 0x41:
1266: gen_op_load_fpr_FT0(rs1);
1267: gen_op_load_fpr_FT1(rs2);
1268: gen_op_fadds();
1269: gen_op_store_FT0_fpr(rd);
1270: break;
1271: case 0x42:
1272: gen_op_load_fpr_DT0(DFPREG(rs1));
1273: gen_op_load_fpr_DT1(DFPREG(rs2));
1274: gen_op_faddd();
1275: gen_op_store_DT0_fpr(DFPREG(rd));
1276: break;
1277: case 0x43: /* faddq */
1278: goto nfpu_insn;
1279: case 0x45:
1280: gen_op_load_fpr_FT0(rs1);
1281: gen_op_load_fpr_FT1(rs2);
1282: gen_op_fsubs();
1283: gen_op_store_FT0_fpr(rd);
1284: break;
1285: case 0x46:
1286: gen_op_load_fpr_DT0(DFPREG(rs1));
1287: gen_op_load_fpr_DT1(DFPREG(rs2));
1288: gen_op_fsubd();
1289: gen_op_store_DT0_fpr(DFPREG(rd));
1290: break;
1291: case 0x47: /* fsubq */
1292: goto nfpu_insn;
1293: case 0x49:
1294: gen_op_load_fpr_FT0(rs1);
1295: gen_op_load_fpr_FT1(rs2);
1296: gen_op_fmuls();
1297: gen_op_store_FT0_fpr(rd);
1298: break;
1299: case 0x4a:
1300: gen_op_load_fpr_DT0(DFPREG(rs1));
1301: gen_op_load_fpr_DT1(DFPREG(rs2));
1302: gen_op_fmuld();
1303: gen_op_store_DT0_fpr(rd);
1304: break;
1305: case 0x4b: /* fmulq */
1306: goto nfpu_insn;
1307: case 0x4d:
1308: gen_op_load_fpr_FT0(rs1);
1309: gen_op_load_fpr_FT1(rs2);
1310: gen_op_fdivs();
1311: gen_op_store_FT0_fpr(rd);
1312: break;
1313: case 0x4e:
1314: gen_op_load_fpr_DT0(DFPREG(rs1));
1315: gen_op_load_fpr_DT1(DFPREG(rs2));
1316: gen_op_fdivd();
1317: gen_op_store_DT0_fpr(DFPREG(rd));
1318: break;
1319: case 0x4f: /* fdivq */
1320: goto nfpu_insn;
1321: case 0x69:
1322: gen_op_load_fpr_FT0(rs1);
1323: gen_op_load_fpr_FT1(rs2);
1324: gen_op_fsmuld();
1325: gen_op_store_DT0_fpr(DFPREG(rd));
1326: break;
1327: case 0x6e: /* fdmulq */
1328: goto nfpu_insn;
1329: case 0xc4:
1330: gen_op_load_fpr_FT1(rs2);
1331: gen_op_fitos();
1332: gen_op_store_FT0_fpr(rd);
1333: break;
1334: case 0xc6:
1335: gen_op_load_fpr_DT1(DFPREG(rs2));
1336: gen_op_fdtos();
1337: gen_op_store_FT0_fpr(rd);
1338: break;
1339: case 0xc7: /* fqtos */
1340: goto nfpu_insn;
1341: case 0xc8:
1342: gen_op_load_fpr_FT1(rs2);
1343: gen_op_fitod();
1344: gen_op_store_DT0_fpr(DFPREG(rd));
1345: break;
1346: case 0xc9:
1347: gen_op_load_fpr_FT1(rs2);
1348: gen_op_fstod();
1349: gen_op_store_DT0_fpr(DFPREG(rd));
1350: break;
1351: case 0xcb: /* fqtod */
1352: goto nfpu_insn;
1353: case 0xcc: /* fitoq */
1354: goto nfpu_insn;
1355: case 0xcd: /* fstoq */
1356: goto nfpu_insn;
1357: case 0xce: /* fdtoq */
1358: goto nfpu_insn;
1359: case 0xd1:
1360: gen_op_load_fpr_FT1(rs2);
1361: gen_op_fstoi();
1362: gen_op_store_FT0_fpr(rd);
1363: break;
1364: case 0xd2:
1365: gen_op_load_fpr_DT1(rs2);
1366: gen_op_fdtoi();
1367: gen_op_store_FT0_fpr(rd);
1368: break;
1369: case 0xd3: /* fqtoi */
1370: goto nfpu_insn;
1371: #ifdef TARGET_SPARC64
1372: case 0x2: /* V9 fmovd */
1373: gen_op_load_fpr_DT0(DFPREG(rs2));
1374: gen_op_store_DT0_fpr(DFPREG(rd));
1375: break;
1376: case 0x6: /* V9 fnegd */
1377: gen_op_load_fpr_DT1(DFPREG(rs2));
1378: gen_op_fnegd();
1379: gen_op_store_DT0_fpr(DFPREG(rd));
1380: break;
1381: case 0xa: /* V9 fabsd */
1382: gen_op_load_fpr_DT1(DFPREG(rs2));
1383: gen_op_fabsd();
1384: gen_op_store_DT0_fpr(DFPREG(rd));
1385: break;
1386: case 0x81: /* V9 fstox */
1387: gen_op_load_fpr_FT1(rs2);
1388: gen_op_fstox();
1389: gen_op_store_DT0_fpr(DFPREG(rd));
1390: break;
1391: case 0x82: /* V9 fdtox */
1392: gen_op_load_fpr_DT1(DFPREG(rs2));
1393: gen_op_fdtox();
1394: gen_op_store_DT0_fpr(DFPREG(rd));
1395: break;
1396: case 0x84: /* V9 fxtos */
1397: gen_op_load_fpr_DT1(DFPREG(rs2));
1398: gen_op_fxtos();
1399: gen_op_store_FT0_fpr(rd);
1400: break;
1401: case 0x88: /* V9 fxtod */
1402: gen_op_load_fpr_DT1(DFPREG(rs2));
1403: gen_op_fxtod();
1404: gen_op_store_DT0_fpr(DFPREG(rd));
1405: break;
1406: case 0x3: /* V9 fmovq */
1407: case 0x7: /* V9 fnegq */
1408: case 0xb: /* V9 fabsq */
1409: case 0x83: /* V9 fqtox */
1410: case 0x8c: /* V9 fxtoq */
1411: goto nfpu_insn;
1412: #endif
1413: default:
1414: goto illegal_insn;
1415: }
1416: } else if (xop == 0x35) { /* FPU Operations */
1417: #ifdef TARGET_SPARC64
1418: int cond;
1419: #endif
1420: #if !defined(CONFIG_USER_ONLY)
1421: gen_op_trap_ifnofpu();
1422: #endif
1423: rs1 = GET_FIELD(insn, 13, 17);
1424: rs2 = GET_FIELD(insn, 27, 31);
1425: xop = GET_FIELD(insn, 18, 26);
1426: #ifdef TARGET_SPARC64
1427: if ((xop & 0x11f) == 0x005) { // V9 fmovsr
1428: cond = GET_FIELD_SP(insn, 14, 17);
1429: gen_op_load_fpr_FT0(rd);
1430: gen_op_load_fpr_FT1(rs2);
1431: rs1 = GET_FIELD(insn, 13, 17);
1432: gen_movl_reg_T0(rs1);
1433: flush_T2(dc);
1434: gen_cond_reg(cond);
1435: gen_op_fmovs_cc();
1436: gen_op_store_FT0_fpr(rd);
1437: break;
1438: } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
1439: cond = GET_FIELD_SP(insn, 14, 17);
1440: gen_op_load_fpr_DT0(rd);
1441: gen_op_load_fpr_DT1(rs2);
1442: flush_T2(dc);
1443: rs1 = GET_FIELD(insn, 13, 17);
1444: gen_movl_reg_T0(rs1);
1445: gen_cond_reg(cond);
1446: gen_op_fmovs_cc();
1447: gen_op_store_DT0_fpr(rd);
1448: break;
1449: } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
1450: goto nfpu_insn;
1451: }
1452: #endif
1453: switch (xop) {
1454: #ifdef TARGET_SPARC64
1455: case 0x001: /* V9 fmovscc %fcc0 */
1456: cond = GET_FIELD_SP(insn, 14, 17);
1457: gen_op_load_fpr_FT0(rd);
1458: gen_op_load_fpr_FT1(rs2);
1459: flush_T2(dc);
1460: gen_fcond[0][cond]();
1461: gen_op_fmovs_cc();
1462: gen_op_store_FT0_fpr(rd);
1463: break;
1464: case 0x002: /* V9 fmovdcc %fcc0 */
1465: cond = GET_FIELD_SP(insn, 14, 17);
1466: gen_op_load_fpr_DT0(rd);
1467: gen_op_load_fpr_DT1(rs2);
1468: flush_T2(dc);
1469: gen_fcond[0][cond]();
1470: gen_op_fmovd_cc();
1471: gen_op_store_DT0_fpr(rd);
1472: break;
1473: case 0x003: /* V9 fmovqcc %fcc0 */
1474: goto nfpu_insn;
1475: case 0x041: /* V9 fmovscc %fcc1 */
1476: cond = GET_FIELD_SP(insn, 14, 17);
1477: gen_op_load_fpr_FT0(rd);
1478: gen_op_load_fpr_FT1(rs2);
1479: flush_T2(dc);
1480: gen_fcond[1][cond]();
1481: gen_op_fmovs_cc();
1482: gen_op_store_FT0_fpr(rd);
1483: break;
1484: case 0x042: /* V9 fmovdcc %fcc1 */
1485: cond = GET_FIELD_SP(insn, 14, 17);
1486: gen_op_load_fpr_DT0(rd);
1487: gen_op_load_fpr_DT1(rs2);
1488: flush_T2(dc);
1489: gen_fcond[1][cond]();
1490: gen_op_fmovd_cc();
1491: gen_op_store_DT0_fpr(rd);
1492: break;
1493: case 0x043: /* V9 fmovqcc %fcc1 */
1494: goto nfpu_insn;
1495: case 0x081: /* V9 fmovscc %fcc2 */
1496: cond = GET_FIELD_SP(insn, 14, 17);
1497: gen_op_load_fpr_FT0(rd);
1498: gen_op_load_fpr_FT1(rs2);
1499: flush_T2(dc);
1500: gen_fcond[2][cond]();
1501: gen_op_fmovs_cc();
1502: gen_op_store_FT0_fpr(rd);
1503: break;
1504: case 0x082: /* V9 fmovdcc %fcc2 */
1505: cond = GET_FIELD_SP(insn, 14, 17);
1506: gen_op_load_fpr_DT0(rd);
1507: gen_op_load_fpr_DT1(rs2);
1508: flush_T2(dc);
1509: gen_fcond[2][cond]();
1510: gen_op_fmovd_cc();
1511: gen_op_store_DT0_fpr(rd);
1512: break;
1513: case 0x083: /* V9 fmovqcc %fcc2 */
1514: goto nfpu_insn;
1515: case 0x0c1: /* V9 fmovscc %fcc3 */
1516: cond = GET_FIELD_SP(insn, 14, 17);
1517: gen_op_load_fpr_FT0(rd);
1518: gen_op_load_fpr_FT1(rs2);
1519: flush_T2(dc);
1520: gen_fcond[3][cond]();
1521: gen_op_fmovs_cc();
1522: gen_op_store_FT0_fpr(rd);
1523: break;
1524: case 0x0c2: /* V9 fmovdcc %fcc3 */
1525: cond = GET_FIELD_SP(insn, 14, 17);
1526: gen_op_load_fpr_DT0(rd);
1527: gen_op_load_fpr_DT1(rs2);
1528: flush_T2(dc);
1529: gen_fcond[3][cond]();
1530: gen_op_fmovd_cc();
1531: gen_op_store_DT0_fpr(rd);
1532: break;
1533: case 0x0c3: /* V9 fmovqcc %fcc3 */
1534: goto nfpu_insn;
1535: case 0x101: /* V9 fmovscc %icc */
1536: cond = GET_FIELD_SP(insn, 14, 17);
1537: gen_op_load_fpr_FT0(rd);
1538: gen_op_load_fpr_FT1(rs2);
1539: flush_T2(dc);
1540: gen_cond[0][cond]();
1541: gen_op_fmovs_cc();
1542: gen_op_store_FT0_fpr(rd);
1543: break;
1544: case 0x102: /* V9 fmovdcc %icc */
1545: cond = GET_FIELD_SP(insn, 14, 17);
1546: gen_op_load_fpr_DT0(rd);
1547: gen_op_load_fpr_DT1(rs2);
1548: flush_T2(dc);
1549: gen_cond[0][cond]();
1550: gen_op_fmovd_cc();
1551: gen_op_store_DT0_fpr(rd);
1552: break;
1553: case 0x103: /* V9 fmovqcc %icc */
1554: goto nfpu_insn;
1555: case 0x181: /* V9 fmovscc %xcc */
1556: cond = GET_FIELD_SP(insn, 14, 17);
1557: gen_op_load_fpr_FT0(rd);
1558: gen_op_load_fpr_FT1(rs2);
1559: flush_T2(dc);
1560: gen_cond[1][cond]();
1561: gen_op_fmovs_cc();
1562: gen_op_store_FT0_fpr(rd);
1563: break;
1564: case 0x182: /* V9 fmovdcc %xcc */
1565: cond = GET_FIELD_SP(insn, 14, 17);
1566: gen_op_load_fpr_DT0(rd);
1567: gen_op_load_fpr_DT1(rs2);
1568: flush_T2(dc);
1569: gen_cond[1][cond]();
1570: gen_op_fmovd_cc();
1571: gen_op_store_DT0_fpr(rd);
1572: break;
1573: case 0x183: /* V9 fmovqcc %xcc */
1574: goto nfpu_insn;
1575: #endif
1576: case 0x51: /* V9 %fcc */
1577: gen_op_load_fpr_FT0(rs1);
1578: gen_op_load_fpr_FT1(rs2);
1579: #ifdef TARGET_SPARC64
1580: gen_fcmps[rd & 3]();
1581: #else
1582: gen_op_fcmps();
1583: #endif
1584: break;
1585: case 0x52: /* V9 %fcc */
1586: gen_op_load_fpr_DT0(DFPREG(rs1));
1587: gen_op_load_fpr_DT1(DFPREG(rs2));
1588: #ifdef TARGET_SPARC64
1589: gen_fcmpd[rd & 3]();
1590: #else
1591: gen_op_fcmpd();
1592: #endif
1593: break;
1594: case 0x53: /* fcmpq */
1595: goto nfpu_insn;
1596: case 0x55: /* fcmpes, V9 %fcc */
1597: gen_op_load_fpr_FT0(rs1);
1598: gen_op_load_fpr_FT1(rs2);
1599: #ifdef TARGET_SPARC64
1600: gen_fcmps[rd & 3]();
1601: #else
1602: gen_op_fcmps(); /* XXX should trap if qNaN or sNaN */
1603: #endif
1604: break;
1605: case 0x56: /* fcmped, V9 %fcc */
1606: gen_op_load_fpr_DT0(DFPREG(rs1));
1607: gen_op_load_fpr_DT1(DFPREG(rs2));
1608: #ifdef TARGET_SPARC64
1609: gen_fcmpd[rd & 3]();
1610: #else
1611: gen_op_fcmpd(); /* XXX should trap if qNaN or sNaN */
1612: #endif
1613: break;
1614: case 0x57: /* fcmpeq */
1615: goto nfpu_insn;
1616: default:
1617: goto illegal_insn;
1618: }
1619: #if defined(OPTIM)
1620: } else if (xop == 0x2) {
1621: // clr/mov shortcut
1622:
1623: rs1 = GET_FIELD(insn, 13, 17);
1624: if (rs1 == 0) {
1625: // or %g0, x, y -> mov T1, x; mov y, T1
1626: if (IS_IMM) { /* immediate */
1627: rs2 = GET_FIELDs(insn, 19, 31);
1628: gen_movl_simm_T1(rs2);
1629: } else { /* register */
1630: rs2 = GET_FIELD(insn, 27, 31);
1631: gen_movl_reg_T1(rs2);
1632: }
1633: gen_movl_T1_reg(rd);
1634: } else {
1635: gen_movl_reg_T0(rs1);
1636: if (IS_IMM) { /* immediate */
1637: // or x, #0, y -> mov T1, x; mov y, T1
1638: rs2 = GET_FIELDs(insn, 19, 31);
1639: if (rs2 != 0) {
1640: gen_movl_simm_T1(rs2);
1641: gen_op_or_T1_T0();
1642: }
1643: } else { /* register */
1644: // or x, %g0, y -> mov T1, x; mov y, T1
1645: rs2 = GET_FIELD(insn, 27, 31);
1646: if (rs2 != 0) {
1647: gen_movl_reg_T1(rs2);
1648: gen_op_or_T1_T0();
1649: }
1650: }
1651: gen_movl_T0_reg(rd);
1652: }
1653: #endif
1654: #ifdef TARGET_SPARC64
1655: } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */
1656: rs1 = GET_FIELD(insn, 13, 17);
1657: gen_movl_reg_T0(rs1);
1658: if (IS_IMM) { /* immediate */
1659: rs2 = GET_FIELDs(insn, 20, 31);
1660: gen_movl_simm_T1(rs2);
1661: } else { /* register */
1662: rs2 = GET_FIELD(insn, 27, 31);
1663: gen_movl_reg_T1(rs2);
1664: }
1665: gen_op_sll();
1666: gen_movl_T0_reg(rd);
1667: } else if (xop == 0x26) { /* srl, V9 srlx */
1668: rs1 = GET_FIELD(insn, 13, 17);
1669: gen_movl_reg_T0(rs1);
1670: if (IS_IMM) { /* immediate */
1671: rs2 = GET_FIELDs(insn, 20, 31);
1672: gen_movl_simm_T1(rs2);
1673: } else { /* register */
1674: rs2 = GET_FIELD(insn, 27, 31);
1675: gen_movl_reg_T1(rs2);
1676: }
1677: if (insn & (1 << 12))
1678: gen_op_srlx();
1679: else
1680: gen_op_srl();
1681: gen_movl_T0_reg(rd);
1682: } else if (xop == 0x27) { /* sra, V9 srax */
1683: rs1 = GET_FIELD(insn, 13, 17);
1684: gen_movl_reg_T0(rs1);
1685: if (IS_IMM) { /* immediate */
1686: rs2 = GET_FIELDs(insn, 20, 31);
1687: gen_movl_simm_T1(rs2);
1688: } else { /* register */
1689: rs2 = GET_FIELD(insn, 27, 31);
1690: gen_movl_reg_T1(rs2);
1691: }
1692: if (insn & (1 << 12))
1693: gen_op_srax();
1694: else
1695: gen_op_sra();
1696: gen_movl_T0_reg(rd);
1697: #endif
1698: } else if (xop < 0x38) {
1699: rs1 = GET_FIELD(insn, 13, 17);
1700: gen_movl_reg_T0(rs1);
1701: if (IS_IMM) { /* immediate */
1702: rs2 = GET_FIELDs(insn, 19, 31);
1703: gen_movl_simm_T1(rs2);
1704: } else { /* register */
1705: rs2 = GET_FIELD(insn, 27, 31);
1706: gen_movl_reg_T1(rs2);
1707: }
1708: if (xop < 0x20) {
1709: switch (xop & ~0x10) {
1710: case 0x0:
1711: if (xop & 0x10)
1712: gen_op_add_T1_T0_cc();
1713: else
1714: gen_op_add_T1_T0();
1715: break;
1716: case 0x1:
1717: gen_op_and_T1_T0();
1718: if (xop & 0x10)
1719: gen_op_logic_T0_cc();
1720: break;
1721: case 0x2:
1722: gen_op_or_T1_T0();
1723: if (xop & 0x10)
1724: gen_op_logic_T0_cc();
1725: break;
1726: case 0x3:
1727: gen_op_xor_T1_T0();
1728: if (xop & 0x10)
1729: gen_op_logic_T0_cc();
1730: break;
1731: case 0x4:
1732: if (xop & 0x10)
1733: gen_op_sub_T1_T0_cc();
1734: else
1735: gen_op_sub_T1_T0();
1736: break;
1737: case 0x5:
1738: gen_op_andn_T1_T0();
1739: if (xop & 0x10)
1740: gen_op_logic_T0_cc();
1741: break;
1742: case 0x6:
1743: gen_op_orn_T1_T0();
1744: if (xop & 0x10)
1745: gen_op_logic_T0_cc();
1746: break;
1747: case 0x7:
1748: gen_op_xnor_T1_T0();
1749: if (xop & 0x10)
1750: gen_op_logic_T0_cc();
1751: break;
1752: case 0x8:
1753: if (xop & 0x10)
1754: gen_op_addx_T1_T0_cc();
1755: else
1756: gen_op_addx_T1_T0();
1757: break;
1758: case 0xa:
1759: gen_op_umul_T1_T0();
1760: if (xop & 0x10)
1761: gen_op_logic_T0_cc();
1762: break;
1763: case 0xb:
1764: gen_op_smul_T1_T0();
1765: if (xop & 0x10)
1766: gen_op_logic_T0_cc();
1767: break;
1768: case 0xc:
1769: if (xop & 0x10)
1770: gen_op_subx_T1_T0_cc();
1771: else
1772: gen_op_subx_T1_T0();
1773: break;
1774: case 0xe:
1775: gen_op_udiv_T1_T0();
1776: if (xop & 0x10)
1777: gen_op_div_cc();
1778: break;
1779: case 0xf:
1780: gen_op_sdiv_T1_T0();
1781: if (xop & 0x10)
1782: gen_op_div_cc();
1783: break;
1784: default:
1785: goto illegal_insn;
1786: }
1787: gen_movl_T0_reg(rd);
1788: } else {
1789: switch (xop) {
1790: #ifdef TARGET_SPARC64
1791: case 0x9: /* V9 mulx */
1792: gen_op_mulx_T1_T0();
1793: gen_movl_T0_reg(rd);
1794: break;
1795: case 0xd: /* V9 udivx */
1796: gen_op_udivx_T1_T0();
1797: gen_movl_T0_reg(rd);
1798: break;
1799: #endif
1800: case 0x20: /* taddcc */
1801: case 0x21: /* tsubcc */
1802: case 0x22: /* taddcctv */
1803: case 0x23: /* tsubcctv */
1804: goto illegal_insn;
1805: case 0x24: /* mulscc */
1806: gen_op_mulscc_T1_T0();
1807: gen_movl_T0_reg(rd);
1808: break;
1809: #ifndef TARGET_SPARC64
1810: case 0x25: /* sll */
1811: gen_op_sll();
1812: gen_movl_T0_reg(rd);
1813: break;
1814: case 0x26: /* srl */
1815: gen_op_srl();
1816: gen_movl_T0_reg(rd);
1817: break;
1818: case 0x27: /* sra */
1819: gen_op_sra();
1820: gen_movl_T0_reg(rd);
1821: break;
1822: #endif
1823: case 0x30:
1824: {
1825: switch(rd) {
1826: case 0: /* wry */
1827: gen_op_xor_T1_T0();
1828: gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1829: break;
1830: #ifdef TARGET_SPARC64
1831: case 0x2: /* V9 wrccr */
1832: gen_op_wrccr();
1833: break;
1834: case 0x3: /* V9 wrasi */
1835: gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
1836: break;
1837: case 0x6: /* V9 wrfprs */
1838: gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
1839: break;
1840: case 0xf: /* V9 sir, nop if user */
1841: #if !defined(CONFIG_USER_ONLY)
1842: if (supervisor(dc))
1843: gen_op_sir();
1844: #endif
1845: break;
1846: case 0x17: /* Tick compare */
1847: #if !defined(CONFIG_USER_ONLY)
1848: if (!supervisor(dc))
1849: goto illegal_insn;
1850: #endif
1851: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
1852: break;
1853: case 0x18: /* System tick */
1854: #if !defined(CONFIG_USER_ONLY)
1855: if (!supervisor(dc))
1856: goto illegal_insn;
1857: #endif
1858: gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1859: break;
1860: case 0x19: /* System tick compare */
1861: #if !defined(CONFIG_USER_ONLY)
1862: if (!supervisor(dc))
1863: goto illegal_insn;
1864: #endif
1865: gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
1866: break;
1867:
1868: case 0x10: /* Performance Control */
1869: case 0x11: /* Performance Instrumentation Counter */
1870: case 0x12: /* Dispatch Control */
1871: case 0x13: /* Graphics Status */
1872: case 0x14: /* Softint set */
1873: case 0x15: /* Softint clear */
1874: case 0x16: /* Softint write */
1875: #endif
1876: default:
1877: goto illegal_insn;
1878: }
1879: }
1880: break;
1881: #if !defined(CONFIG_USER_ONLY)
1882: case 0x31: /* wrpsr, V9 saved, restored */
1883: {
1884: if (!supervisor(dc))
1885: goto priv_insn;
1886: #ifdef TARGET_SPARC64
1887: switch (rd) {
1888: case 0:
1889: gen_op_saved();
1890: break;
1891: case 1:
1892: gen_op_restored();
1893: break;
1894: default:
1895: goto illegal_insn;
1896: }
1897: #else
1898: gen_op_xor_T1_T0();
1899: gen_op_wrpsr();
1900: #endif
1901: }
1902: break;
1903: case 0x32: /* wrwim, V9 wrpr */
1904: {
1905: if (!supervisor(dc))
1906: goto priv_insn;
1907: gen_op_xor_T1_T0();
1908: #ifdef TARGET_SPARC64
1909: switch (rd) {
1910: case 0: // tpc
1911: gen_op_wrtpc();
1912: break;
1913: case 1: // tnpc
1914: gen_op_wrtnpc();
1915: break;
1916: case 2: // tstate
1917: gen_op_wrtstate();
1918: break;
1919: case 3: // tt
1920: gen_op_wrtt();
1921: break;
1922: case 4: // tick
1923: gen_op_wrtick();
1924: break;
1925: case 5: // tba
1926: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
1927: break;
1928: case 6: // pstate
1929: gen_op_wrpstate();
1930: break;
1931: case 7: // tl
1932: gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
1933: break;
1934: case 8: // pil
1935: gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
1936: break;
1937: case 9: // cwp
1938: gen_op_wrcwp();
1939: break;
1940: case 10: // cansave
1941: gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
1942: break;
1943: case 11: // canrestore
1944: gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
1945: break;
1946: case 12: // cleanwin
1947: gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
1948: break;
1949: case 13: // otherwin
1950: gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
1951: break;
1952: case 14: // wstate
1953: gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
1954: break;
1955: default:
1956: goto illegal_insn;
1957: }
1958: #else
1959: gen_op_movl_env_T0(offsetof(CPUSPARCState, wim));
1960: #endif
1961: }
1962: break;
1963: #ifndef TARGET_SPARC64
1964: case 0x33: /* wrtbr, V9 unimp */
1965: {
1966: if (!supervisor(dc))
1967: goto priv_insn;
1968: gen_op_xor_T1_T0();
1969: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
1970: }
1971: break;
1972: #endif
1973: #endif
1974: #ifdef TARGET_SPARC64
1975: case 0x2c: /* V9 movcc */
1976: {
1977: int cc = GET_FIELD_SP(insn, 11, 12);
1978: int cond = GET_FIELD_SP(insn, 14, 17);
1979: if (IS_IMM) { /* immediate */
1980: rs2 = GET_FIELD_SPs(insn, 0, 10);
1981: gen_movl_simm_T1(rs2);
1982: }
1983: else {
1984: rs2 = GET_FIELD_SP(insn, 0, 4);
1985: gen_movl_reg_T1(rs2);
1986: }
1987: gen_movl_reg_T0(rd);
1988: flush_T2(dc);
1989: if (insn & (1 << 18)) {
1990: if (cc == 0)
1991: gen_cond[0][cond]();
1992: else if (cc == 2)
1993: gen_cond[1][cond]();
1994: else
1995: goto illegal_insn;
1996: } else {
1997: gen_fcond[cc][cond]();
1998: }
1999: gen_op_mov_cc();
2000: gen_movl_T0_reg(rd);
2001: break;
2002: }
2003: case 0x2d: /* V9 sdivx */
2004: gen_op_sdivx_T1_T0();
2005: gen_movl_T0_reg(rd);
2006: break;
2007: case 0x2e: /* V9 popc */
2008: {
2009: if (IS_IMM) { /* immediate */
2010: rs2 = GET_FIELD_SPs(insn, 0, 12);
2011: gen_movl_simm_T1(rs2);
2012: // XXX optimize: popc(constant)
2013: }
2014: else {
2015: rs2 = GET_FIELD_SP(insn, 0, 4);
2016: gen_movl_reg_T1(rs2);
2017: }
2018: gen_op_popc();
2019: gen_movl_T0_reg(rd);
2020: }
2021: case 0x2f: /* V9 movr */
2022: {
2023: int cond = GET_FIELD_SP(insn, 10, 12);
2024: rs1 = GET_FIELD(insn, 13, 17);
2025: flush_T2(dc);
2026: gen_movl_reg_T0(rs1);
2027: gen_cond_reg(cond);
2028: if (IS_IMM) { /* immediate */
2029: rs2 = GET_FIELD_SPs(insn, 0, 10);
2030: gen_movl_simm_T1(rs2);
2031: }
2032: else {
2033: rs2 = GET_FIELD_SP(insn, 0, 4);
2034: gen_movl_reg_T1(rs2);
2035: }
2036: gen_movl_reg_T0(rd);
2037: gen_op_mov_cc();
2038: gen_movl_T0_reg(rd);
2039: break;
2040: }
2041: case 0x36: /* UltraSparc shutdown, VIS */
2042: {
2043: // XXX
2044: }
2045: #endif
2046: default:
2047: goto illegal_insn;
2048: }
2049: }
2050: #ifdef TARGET_SPARC64
2051: } else if (xop == 0x39) { /* V9 return */
2052: rs1 = GET_FIELD(insn, 13, 17);
2053: gen_movl_reg_T0(rs1);
2054: if (IS_IMM) { /* immediate */
2055: rs2 = GET_FIELDs(insn, 19, 31);
2056: #if defined(OPTIM)
2057: if (rs2) {
2058: #endif
2059: gen_movl_simm_T1(rs2);
2060: gen_op_add_T1_T0();
2061: #if defined(OPTIM)
2062: }
2063: #endif
2064: } else { /* register */
2065: rs2 = GET_FIELD(insn, 27, 31);
2066: #if defined(OPTIM)
2067: if (rs2) {
2068: #endif
2069: gen_movl_reg_T1(rs2);
2070: gen_op_add_T1_T0();
2071: #if defined(OPTIM)
2072: }
2073: #endif
2074: }
2075: gen_op_restore();
2076: gen_mov_pc_npc(dc);
2077: gen_op_movl_npc_T0();
2078: dc->npc = DYNAMIC_PC;
2079: goto jmp_insn;
2080: #endif
2081: } else {
2082: rs1 = GET_FIELD(insn, 13, 17);
2083: gen_movl_reg_T0(rs1);
2084: if (IS_IMM) { /* immediate */
2085: rs2 = GET_FIELDs(insn, 19, 31);
2086: #if defined(OPTIM)
2087: if (rs2) {
2088: #endif
2089: gen_movl_simm_T1(rs2);
2090: gen_op_add_T1_T0();
2091: #if defined(OPTIM)
2092: }
2093: #endif
2094: } else { /* register */
2095: rs2 = GET_FIELD(insn, 27, 31);
2096: #if defined(OPTIM)
2097: if (rs2) {
2098: #endif
2099: gen_movl_reg_T1(rs2);
2100: gen_op_add_T1_T0();
2101: #if defined(OPTIM)
2102: }
2103: #endif
2104: }
2105: switch (xop) {
2106: case 0x38: /* jmpl */
2107: {
2108: if (rd != 0) {
2109: gen_op_movl_T1_im(dc->pc);
2110: gen_movl_T1_reg(rd);
2111: }
2112: gen_mov_pc_npc(dc);
2113: gen_op_movl_npc_T0();
2114: dc->npc = DYNAMIC_PC;
2115: }
2116: goto jmp_insn;
2117: #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
2118: case 0x39: /* rett, V9 return */
2119: {
2120: if (!supervisor(dc))
2121: goto priv_insn;
2122: gen_mov_pc_npc(dc);
2123: gen_op_movl_npc_T0();
2124: dc->npc = DYNAMIC_PC;
2125: gen_op_rett();
2126: }
2127: goto jmp_insn;
2128: #endif
2129: case 0x3b: /* flush */
2130: gen_op_flush_T0();
2131: break;
2132: case 0x3c: /* save */
2133: save_state(dc);
2134: gen_op_save();
2135: gen_movl_T0_reg(rd);
2136: break;
2137: case 0x3d: /* restore */
2138: save_state(dc);
2139: gen_op_restore();
2140: gen_movl_T0_reg(rd);
2141: break;
2142: #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
2143: case 0x3e: /* V9 done/retry */
2144: {
2145: switch (rd) {
2146: case 0:
2147: if (!supervisor(dc))
2148: goto priv_insn;
2149: dc->npc = DYNAMIC_PC;
2150: dc->pc = DYNAMIC_PC;
2151: gen_op_done();
2152: goto jmp_insn;
2153: case 1:
2154: if (!supervisor(dc))
2155: goto priv_insn;
2156: dc->npc = DYNAMIC_PC;
2157: dc->pc = DYNAMIC_PC;
2158: gen_op_retry();
2159: goto jmp_insn;
2160: default:
2161: goto illegal_insn;
2162: }
2163: }
2164: break;
2165: #endif
2166: default:
2167: goto illegal_insn;
2168: }
2169: }
2170: break;
2171: }
2172: break;
2173: case 3: /* load/store instructions */
2174: {
2175: unsigned int xop = GET_FIELD(insn, 7, 12);
2176: rs1 = GET_FIELD(insn, 13, 17);
2177: gen_movl_reg_T0(rs1);
2178: if (IS_IMM) { /* immediate */
2179: rs2 = GET_FIELDs(insn, 19, 31);
2180: #if defined(OPTIM)
2181: if (rs2 != 0) {
2182: #endif
2183: gen_movl_simm_T1(rs2);
2184: gen_op_add_T1_T0();
2185: #if defined(OPTIM)
2186: }
2187: #endif
2188: } else { /* register */
2189: rs2 = GET_FIELD(insn, 27, 31);
2190: #if defined(OPTIM)
2191: if (rs2 != 0) {
2192: #endif
2193: gen_movl_reg_T1(rs2);
2194: gen_op_add_T1_T0();
2195: #if defined(OPTIM)
2196: }
2197: #endif
2198: }
2199: if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || \
2200: (xop > 0x17 && xop < 0x1d ) || \
2201: (xop > 0x2c && xop < 0x33) || xop == 0x1f) {
2202: switch (xop) {
2203: case 0x0: /* load word */
2204: gen_op_ldst(ld);
2205: break;
2206: case 0x1: /* load unsigned byte */
2207: gen_op_ldst(ldub);
2208: break;
2209: case 0x2: /* load unsigned halfword */
2210: gen_op_ldst(lduh);
2211: break;
2212: case 0x3: /* load double word */
2213: gen_op_ldst(ldd);
2214: gen_movl_T0_reg(rd + 1);
2215: break;
2216: case 0x9: /* load signed byte */
2217: gen_op_ldst(ldsb);
2218: break;
2219: case 0xa: /* load signed halfword */
2220: gen_op_ldst(ldsh);
2221: break;
2222: case 0xd: /* ldstub -- XXX: should be atomically */
2223: gen_op_ldst(ldstub);
2224: break;
2225: case 0x0f: /* swap register with memory. Also atomically */
2226: gen_movl_reg_T1(rd);
2227: gen_op_ldst(swap);
2228: break;
2229: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2230: case 0x10: /* load word alternate */
2231: #ifndef TARGET_SPARC64
2232: if (!supervisor(dc))
2233: goto priv_insn;
2234: #endif
2235: gen_op_lda(insn, 1, 4, 0);
2236: break;
2237: case 0x11: /* load unsigned byte alternate */
2238: #ifndef TARGET_SPARC64
2239: if (!supervisor(dc))
2240: goto priv_insn;
2241: #endif
2242: gen_op_lduba(insn, 1, 1, 0);
2243: break;
2244: case 0x12: /* load unsigned halfword alternate */
2245: #ifndef TARGET_SPARC64
2246: if (!supervisor(dc))
2247: goto priv_insn;
2248: #endif
2249: gen_op_lduha(insn, 1, 2, 0);
2250: break;
2251: case 0x13: /* load double word alternate */
2252: #ifndef TARGET_SPARC64
2253: if (!supervisor(dc))
2254: goto priv_insn;
2255: #endif
2256: gen_op_ldda(insn, 1, 8, 0);
2257: gen_movl_T0_reg(rd + 1);
2258: break;
2259: case 0x19: /* load signed byte alternate */
2260: #ifndef TARGET_SPARC64
2261: if (!supervisor(dc))
2262: goto priv_insn;
2263: #endif
2264: gen_op_ldsba(insn, 1, 1, 1);
2265: break;
2266: case 0x1a: /* load signed halfword alternate */
2267: #ifndef TARGET_SPARC64
2268: if (!supervisor(dc))
2269: goto priv_insn;
2270: #endif
2271: gen_op_ldsha(insn, 1, 2 ,1);
2272: break;
2273: case 0x1d: /* ldstuba -- XXX: should be atomically */
2274: #ifndef TARGET_SPARC64
2275: if (!supervisor(dc))
2276: goto priv_insn;
2277: #endif
2278: gen_op_ldstuba(insn, 1, 1, 0);
2279: break;
2280: case 0x1f: /* swap reg with alt. memory. Also atomically */
2281: #ifndef TARGET_SPARC64
2282: if (!supervisor(dc))
2283: goto priv_insn;
2284: #endif
2285: gen_movl_reg_T1(rd);
2286: gen_op_swapa(insn, 1, 4, 0);
2287: break;
2288:
2289: #ifndef TARGET_SPARC64
2290: /* avoid warnings */
2291: (void) &gen_op_stfa;
2292: (void) &gen_op_stdfa;
2293: (void) &gen_op_ldfa;
2294: (void) &gen_op_lddfa;
2295: #else
2296: #if !defined(CONFIG_USER_ONLY)
2297: (void) &gen_op_cas;
2298: (void) &gen_op_casx;
2299: #endif
2300: #endif
2301: #endif
2302: #ifdef TARGET_SPARC64
2303: case 0x08: /* V9 ldsw */
2304: gen_op_ldst(ldsw);
2305: break;
2306: case 0x0b: /* V9 ldx */
2307: gen_op_ldst(ldx);
2308: break;
2309: case 0x18: /* V9 ldswa */
2310: gen_op_ldswa(insn, 1, 4, 1);
2311: break;
2312: case 0x1b: /* V9 ldxa */
2313: gen_op_ldxa(insn, 1, 8, 0);
2314: break;
2315: case 0x2d: /* V9 prefetch, no effect */
2316: goto skip_move;
2317: case 0x30: /* V9 ldfa */
2318: gen_op_ldfa(insn, 1, 8, 0); // XXX
2319: break;
2320: case 0x33: /* V9 lddfa */
2321: gen_op_lddfa(insn, 1, 8, 0); // XXX
2322:
2323: break;
2324: case 0x3d: /* V9 prefetcha, no effect */
2325: goto skip_move;
2326: case 0x32: /* V9 ldqfa */
2327: goto nfpu_insn;
2328: #endif
2329: default:
2330: goto illegal_insn;
2331: }
2332: gen_movl_T1_reg(rd);
2333: #ifdef TARGET_SPARC64
2334: skip_move: ;
2335: #endif
2336: } else if (xop >= 0x20 && xop < 0x24) {
2337: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2338: gen_op_trap_ifnofpu();
2339: #endif
2340: switch (xop) {
2341: case 0x20: /* load fpreg */
2342: gen_op_ldst(ldf);
2343: gen_op_store_FT0_fpr(rd);
2344: break;
2345: case 0x21: /* load fsr */
2346: gen_op_ldfsr();
2347: gen_op_store_FT0_fpr(rd);
2348: break;
2349: case 0x22: /* load quad fpreg */
2350: goto nfpu_insn;
2351: case 0x23: /* load double fpreg */
2352: gen_op_ldst(lddf);
2353: gen_op_store_DT0_fpr(DFPREG(rd));
2354: break;
2355: default:
2356: goto illegal_insn;
2357: }
2358: } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
2359: xop == 0xe || xop == 0x1e) {
2360: gen_movl_reg_T1(rd);
2361: switch (xop) {
2362: case 0x4:
2363: gen_op_ldst(st);
2364: break;
2365: case 0x5:
2366: gen_op_ldst(stb);
2367: break;
2368: case 0x6:
2369: gen_op_ldst(sth);
2370: break;
2371: case 0x7:
2372: flush_T2(dc);
2373: gen_movl_reg_T2(rd + 1);
2374: gen_op_ldst(std);
2375: break;
2376: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2377: case 0x14:
2378: #ifndef TARGET_SPARC64
2379: if (!supervisor(dc))
2380: goto priv_insn;
2381: #endif
2382: gen_op_sta(insn, 0, 4, 0);
2383: break;
2384: case 0x15:
2385: #ifndef TARGET_SPARC64
2386: if (!supervisor(dc))
2387: goto priv_insn;
2388: #endif
2389: gen_op_stba(insn, 0, 1, 0);
2390: break;
2391: case 0x16:
2392: #ifndef TARGET_SPARC64
2393: if (!supervisor(dc))
2394: goto priv_insn;
2395: #endif
2396: gen_op_stha(insn, 0, 2, 0);
2397: break;
2398: case 0x17:
2399: #ifndef TARGET_SPARC64
2400: if (!supervisor(dc))
2401: goto priv_insn;
2402: #endif
2403: flush_T2(dc);
2404: gen_movl_reg_T2(rd + 1);
2405: gen_op_stda(insn, 0, 8, 0);
2406: break;
2407: #endif
2408: #ifdef TARGET_SPARC64
2409: case 0x0e: /* V9 stx */
2410: gen_op_ldst(stx);
2411: break;
2412: case 0x1e: /* V9 stxa */
2413: gen_op_stxa(insn, 0, 8, 0); // XXX
2414: break;
2415: #endif
2416: default:
2417: goto illegal_insn;
2418: }
2419: } else if (xop > 0x23 && xop < 0x28) {
2420: #if !defined(CONFIG_USER_ONLY)
2421: gen_op_trap_ifnofpu();
2422: #endif
2423: switch (xop) {
2424: case 0x24:
2425: gen_op_load_fpr_FT0(rd);
2426: gen_op_ldst(stf);
2427: break;
2428: case 0x25: /* stfsr, V9 stxfsr */
2429: gen_op_load_fpr_FT0(rd);
2430: // XXX
2431: gen_op_stfsr();
2432: break;
2433: case 0x26: /* stdfq */
2434: goto nfpu_insn;
2435: case 0x27:
2436: gen_op_load_fpr_DT0(DFPREG(rd));
2437: gen_op_ldst(stdf);
2438: break;
2439: default:
2440: goto illegal_insn;
2441: }
2442: } else if (xop > 0x33 && xop < 0x3f) {
2443: #ifdef TARGET_SPARC64
2444: switch (xop) {
2445: case 0x34: /* V9 stfa */
2446: gen_op_stfa(insn, 0, 0, 0); // XXX
2447: break;
2448: case 0x37: /* V9 stdfa */
2449: gen_op_stdfa(insn, 0, 0, 0); // XXX
2450: break;
2451: case 0x3c: /* V9 casa */
2452: gen_op_casa(insn, 0, 4, 0); // XXX
2453: break;
2454: case 0x3e: /* V9 casxa */
2455: gen_op_casxa(insn, 0, 8, 0); // XXX
2456: break;
2457: case 0x36: /* V9 stqfa */
2458: goto nfpu_insn;
2459: default:
2460: goto illegal_insn;
2461: }
2462: #else
2463: goto illegal_insn;
2464: #endif
2465: }
2466: else
2467: goto illegal_insn;
2468: }
2469: break;
2470: }
2471: /* default case for non jump instructions */
2472: if (dc->npc == DYNAMIC_PC) {
2473: dc->pc = DYNAMIC_PC;
2474: gen_op_next_insn();
2475: } else if (dc->npc == JUMP_PC) {
2476: /* we can do a static jump */
2477: gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]);
2478: dc->is_br = 1;
2479: } else {
2480: dc->pc = dc->npc;
2481: dc->npc = dc->npc + 4;
2482: }
2483: jmp_insn:
2484: return;
2485: illegal_insn:
2486: save_state(dc);
2487: gen_op_exception(TT_ILL_INSN);
2488: dc->is_br = 1;
2489: return;
2490: #if !defined(CONFIG_USER_ONLY)
2491: priv_insn:
2492: save_state(dc);
2493: gen_op_exception(TT_PRIV_INSN);
2494: dc->is_br = 1;
2495: return;
2496: #endif
2497: nfpu_insn:
2498: save_state(dc);
2499: gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
2500: dc->is_br = 1;
2501: }
2502:
2503: static inline int gen_intermediate_code_internal(TranslationBlock * tb,
2504: int spc, CPUSPARCState *env)
2505: {
2506: target_ulong pc_start, last_pc;
2507: uint16_t *gen_opc_end;
2508: DisasContext dc1, *dc = &dc1;
2509: int j, lj = -1;
2510:
2511: memset(dc, 0, sizeof(DisasContext));
2512: dc->tb = tb;
2513: pc_start = tb->pc;
2514: dc->pc = pc_start;
2515: last_pc = dc->pc;
2516: dc->npc = (target_ulong) tb->cs_base;
2517: #if defined(CONFIG_USER_ONLY)
2518: dc->mem_idx = 0;
2519: #else
2520: dc->mem_idx = ((env->psrs) != 0);
2521: #endif
2522: gen_opc_ptr = gen_opc_buf;
2523: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2524: gen_opparam_ptr = gen_opparam_buf;
2525: nb_gen_labels = 0;
2526:
2527: do {
2528: if (env->nb_breakpoints > 0) {
2529: for(j = 0; j < env->nb_breakpoints; j++) {
2530: if (env->breakpoints[j] == dc->pc) {
2531: if (dc->pc != pc_start)
2532: save_state(dc);
2533: gen_op_debug();
2534: gen_op_movl_T0_0();
2535: gen_op_exit_tb();
2536: dc->is_br = 1;
2537: goto exit_gen_loop;
2538: }
2539: }
2540: }
2541: if (spc) {
2542: if (loglevel > 0)
2543: fprintf(logfile, "Search PC...\n");
2544: j = gen_opc_ptr - gen_opc_buf;
2545: if (lj < j) {
2546: lj++;
2547: while (lj < j)
2548: gen_opc_instr_start[lj++] = 0;
2549: gen_opc_pc[lj] = dc->pc;
2550: gen_opc_npc[lj] = dc->npc;
2551: gen_opc_instr_start[lj] = 1;
2552: }
2553: }
2554: last_pc = dc->pc;
2555: disas_sparc_insn(dc);
2556:
2557: if (dc->is_br)
2558: break;
2559: /* if the next PC is different, we abort now */
2560: if (dc->pc != (last_pc + 4))
2561: break;
2562: /* if we reach a page boundary, we stop generation so that the
2563: PC of a TT_TFAULT exception is always in the right page */
2564: if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
2565: break;
2566: /* if single step mode, we generate only one instruction and
2567: generate an exception */
2568: if (env->singlestep_enabled) {
2569: gen_jmp_im(dc->pc);
2570: gen_op_movl_T0_0();
2571: gen_op_exit_tb();
2572: break;
2573: }
2574: } while ((gen_opc_ptr < gen_opc_end) &&
2575: (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2576:
2577: exit_gen_loop:
2578: if (!dc->is_br) {
2579: if (dc->pc != DYNAMIC_PC &&
2580: (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
2581: /* static PC and NPC: we can use direct chaining */
2582: gen_branch(dc, (long)tb, dc->pc, dc->npc);
2583: } else {
2584: if (dc->pc != DYNAMIC_PC)
2585: gen_jmp_im(dc->pc);
2586: save_npc(dc);
2587: gen_op_movl_T0_0();
2588: gen_op_exit_tb();
2589: }
2590: }
2591: *gen_opc_ptr = INDEX_op_end;
2592: if (spc) {
2593: j = gen_opc_ptr - gen_opc_buf;
2594: lj++;
2595: while (lj <= j)
2596: gen_opc_instr_start[lj++] = 0;
2597: tb->size = 0;
2598: #if 0
2599: if (loglevel > 0) {
2600: page_dump(logfile);
2601: }
2602: #endif
2603: gen_opc_jump_pc[0] = dc->jump_pc[0];
2604: gen_opc_jump_pc[1] = dc->jump_pc[1];
2605: } else {
2606: tb->size = last_pc + 4 - pc_start;
2607: }
2608: #ifdef DEBUG_DISAS
2609: if (loglevel & CPU_LOG_TB_IN_ASM) {
2610: fprintf(logfile, "--------------\n");
2611: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2612: target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
2613: fprintf(logfile, "\n");
2614: if (loglevel & CPU_LOG_TB_OP) {
2615: fprintf(logfile, "OP:\n");
2616: dump_ops(gen_opc_buf, gen_opparam_buf);
2617: fprintf(logfile, "\n");
2618: }
2619: }
2620: #endif
2621: return 0;
2622: }
2623:
2624: int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
2625: {
2626: return gen_intermediate_code_internal(tb, 0, env);
2627: }
2628:
2629: int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
2630: {
2631: return gen_intermediate_code_internal(tb, 1, env);
2632: }
2633:
2634: extern int ram_size;
2635:
2636: void cpu_reset(CPUSPARCState *env)
2637: {
2638: memset(env, 0, sizeof(*env));
2639: tlb_flush(env, 1);
2640: env->cwp = 0;
2641: env->wim = 1;
2642: env->regwptr = env->regbase + (env->cwp * 16);
2643: #if defined(CONFIG_USER_ONLY)
2644: env->user_mode_only = 1;
2645: #else
2646: env->psrs = 1;
2647: env->psrps = 1;
2648: env->gregs[1] = ram_size;
2649: #ifdef TARGET_SPARC64
2650: env->pstate = PS_PRIV;
2651: env->version = GET_VER(env);
2652: env->pc = 0x1fff0000000ULL;
2653: #else
2654: env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */
2655: env->pc = 0xffd00000;
2656: #endif
2657: env->npc = env->pc + 4;
2658: #endif
2659: }
2660:
2661: CPUSPARCState *cpu_sparc_init(void)
2662: {
2663: CPUSPARCState *env;
2664:
2665: cpu_exec_init();
2666:
2667: if (!(env = malloc(sizeof(CPUSPARCState))))
2668: return (NULL);
2669: cpu_single_env = env;
2670: cpu_reset(env);
2671: return (env);
2672: }
2673:
2674: #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
2675:
2676: void cpu_dump_state(CPUState *env, FILE *f,
2677: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2678: int flags)
2679: {
2680: int i, x;
2681:
2682: cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
2683: cpu_fprintf(f, "General Registers:\n");
2684: for (i = 0; i < 4; i++)
2685: cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2686: cpu_fprintf(f, "\n");
2687: for (; i < 8; i++)
2688: cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
2689: cpu_fprintf(f, "\nCurrent Register Window:\n");
2690: for (x = 0; x < 3; x++) {
2691: for (i = 0; i < 4; i++)
2692: cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2693: (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
2694: env->regwptr[i + x * 8]);
2695: cpu_fprintf(f, "\n");
2696: for (; i < 8; i++)
2697: cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
2698: (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
2699: env->regwptr[i + x * 8]);
2700: cpu_fprintf(f, "\n");
2701: }
2702: cpu_fprintf(f, "\nFloating Point Registers:\n");
2703: for (i = 0; i < 32; i++) {
2704: if ((i & 3) == 0)
2705: cpu_fprintf(f, "%%f%02d:", i);
2706: cpu_fprintf(f, " %016lf", env->fpr[i]);
2707: if ((i & 3) == 3)
2708: cpu_fprintf(f, "\n");
2709: }
2710: cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
2711: GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
2712: GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
2713: env->psrs?'S':'-', env->psrps?'P':'-',
2714: env->psret?'E':'-', env->wim);
2715: cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
2716: }
2717:
2718: #if defined(CONFIG_USER_ONLY)
2719: target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2720: {
2721: return addr;
2722: }
2723:
2724: #else
2725: extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
2726: int *access_index, target_ulong address, int rw,
2727: int is_user);
2728:
2729: target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2730: {
2731: target_phys_addr_t phys_addr;
2732: int prot, access_index;
2733:
2734: if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
2735: return -1;
2736: return phys_addr;
2737: }
2738: #endif
2739:
2740: void helper_flush(target_ulong addr)
2741: {
2742: addr &= ~7;
2743: tb_invalidate_page_range(addr, addr + 8);
2744: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.