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