|
|
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: */
29:
30: #include <stdarg.h>
31: #include <stdlib.h>
32: #include <stdio.h>
33: #include <string.h>
34: #include <inttypes.h>
35:
36: #include "cpu.h"
37: #include "exec-all.h"
38: #include "disas.h"
39:
40: #define DEBUG_DISAS
41:
42: #define DYNAMIC_PC 1 /* dynamic pc value */
43: #define JUMP_PC 2 /* dynamic pc value which takes only two values
44: according to jump_pc[T2] */
45:
46: typedef struct DisasContext {
1.1.1.5 ! root 47: target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */
! 48: target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
1.1 root 49: target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
50: int is_br;
51: int mem_idx;
1.1.1.3 root 52: int fpu_enabled;
1.1 root 53: struct TranslationBlock *tb;
54: } DisasContext;
55:
1.1.1.5 ! root 56: typedef struct sparc_def_t sparc_def_t;
! 57:
! 58: struct sparc_def_t {
! 59: const unsigned char *name;
! 60: target_ulong iu_version;
! 61: uint32_t fpu_version;
! 62: uint32_t mmu_version;
! 63: uint32_t mmu_bm;
! 64: };
! 65:
! 66: static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name);
! 67:
1.1 root 68: static uint16_t *gen_opc_ptr;
69: static uint32_t *gen_opparam_ptr;
70: extern FILE *logfile;
71: extern int loglevel;
72:
73: enum {
74: #define DEF(s,n,copy_size) INDEX_op_ ## s,
75: #include "opc.h"
76: #undef DEF
77: NB_OPS
78: };
79:
80: #include "gen-op.h"
81:
82: // This function uses non-native bit order
83: #define GET_FIELD(X, FROM, TO) \
84: ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
85:
86: // This function uses the order in the manuals, i.e. bit 0 is 2^0
87: #define GET_FIELD_SP(X, FROM, TO) \
88: GET_FIELD(X, 31 - (TO), 31 - (FROM))
89:
90: #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
1.1.1.5 ! root 91: #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
1.1 root 92:
93: #ifdef TARGET_SPARC64
1.1.1.5 ! root 94: #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
! 95: #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
1.1 root 96: #else
1.1.1.5 ! root 97: #define DFPREG(r) (r & 0x1e)
! 98: #define QFPREG(r) (r & 0x1c)
1.1 root 99: #endif
100:
101: #ifdef USE_DIRECT_JUMP
102: #define TBPARAM(x)
103: #else
104: #define TBPARAM(x) (long)(x)
105: #endif
106:
107: static int sign_extend(int x, int len)
108: {
109: len = 32 - len;
110: return (x << len) >> len;
111: }
112:
113: #define IS_IMM (insn & (1<<13))
114:
115: static void disas_sparc_insn(DisasContext * dc);
116:
1.1.1.5 ! root 117: static GenOpFunc * const gen_op_movl_TN_reg[2][32] = {
1.1 root 118: {
119: gen_op_movl_g0_T0,
120: gen_op_movl_g1_T0,
121: gen_op_movl_g2_T0,
122: gen_op_movl_g3_T0,
123: gen_op_movl_g4_T0,
124: gen_op_movl_g5_T0,
125: gen_op_movl_g6_T0,
126: gen_op_movl_g7_T0,
127: gen_op_movl_o0_T0,
128: gen_op_movl_o1_T0,
129: gen_op_movl_o2_T0,
130: gen_op_movl_o3_T0,
131: gen_op_movl_o4_T0,
132: gen_op_movl_o5_T0,
133: gen_op_movl_o6_T0,
134: gen_op_movl_o7_T0,
135: gen_op_movl_l0_T0,
136: gen_op_movl_l1_T0,
137: gen_op_movl_l2_T0,
138: gen_op_movl_l3_T0,
139: gen_op_movl_l4_T0,
140: gen_op_movl_l5_T0,
141: gen_op_movl_l6_T0,
142: gen_op_movl_l7_T0,
143: gen_op_movl_i0_T0,
144: gen_op_movl_i1_T0,
145: gen_op_movl_i2_T0,
146: gen_op_movl_i3_T0,
147: gen_op_movl_i4_T0,
148: gen_op_movl_i5_T0,
149: gen_op_movl_i6_T0,
150: gen_op_movl_i7_T0,
151: },
152: {
153: gen_op_movl_g0_T1,
154: gen_op_movl_g1_T1,
155: gen_op_movl_g2_T1,
156: gen_op_movl_g3_T1,
157: gen_op_movl_g4_T1,
158: gen_op_movl_g5_T1,
159: gen_op_movl_g6_T1,
160: gen_op_movl_g7_T1,
161: gen_op_movl_o0_T1,
162: gen_op_movl_o1_T1,
163: gen_op_movl_o2_T1,
164: gen_op_movl_o3_T1,
165: gen_op_movl_o4_T1,
166: gen_op_movl_o5_T1,
167: gen_op_movl_o6_T1,
168: gen_op_movl_o7_T1,
169: gen_op_movl_l0_T1,
170: gen_op_movl_l1_T1,
171: gen_op_movl_l2_T1,
172: gen_op_movl_l3_T1,
173: gen_op_movl_l4_T1,
174: gen_op_movl_l5_T1,
175: gen_op_movl_l6_T1,
176: gen_op_movl_l7_T1,
177: gen_op_movl_i0_T1,
178: gen_op_movl_i1_T1,
179: gen_op_movl_i2_T1,
180: gen_op_movl_i3_T1,
181: gen_op_movl_i4_T1,
182: gen_op_movl_i5_T1,
183: gen_op_movl_i6_T1,
184: gen_op_movl_i7_T1,
185: }
186: };
187:
1.1.1.5 ! root 188: static GenOpFunc * const gen_op_movl_reg_TN[3][32] = {
1.1 root 189: {
190: gen_op_movl_T0_g0,
191: gen_op_movl_T0_g1,
192: gen_op_movl_T0_g2,
193: gen_op_movl_T0_g3,
194: gen_op_movl_T0_g4,
195: gen_op_movl_T0_g5,
196: gen_op_movl_T0_g6,
197: gen_op_movl_T0_g7,
198: gen_op_movl_T0_o0,
199: gen_op_movl_T0_o1,
200: gen_op_movl_T0_o2,
201: gen_op_movl_T0_o3,
202: gen_op_movl_T0_o4,
203: gen_op_movl_T0_o5,
204: gen_op_movl_T0_o6,
205: gen_op_movl_T0_o7,
206: gen_op_movl_T0_l0,
207: gen_op_movl_T0_l1,
208: gen_op_movl_T0_l2,
209: gen_op_movl_T0_l3,
210: gen_op_movl_T0_l4,
211: gen_op_movl_T0_l5,
212: gen_op_movl_T0_l6,
213: gen_op_movl_T0_l7,
214: gen_op_movl_T0_i0,
215: gen_op_movl_T0_i1,
216: gen_op_movl_T0_i2,
217: gen_op_movl_T0_i3,
218: gen_op_movl_T0_i4,
219: gen_op_movl_T0_i5,
220: gen_op_movl_T0_i6,
221: gen_op_movl_T0_i7,
222: },
223: {
224: gen_op_movl_T1_g0,
225: gen_op_movl_T1_g1,
226: gen_op_movl_T1_g2,
227: gen_op_movl_T1_g3,
228: gen_op_movl_T1_g4,
229: gen_op_movl_T1_g5,
230: gen_op_movl_T1_g6,
231: gen_op_movl_T1_g7,
232: gen_op_movl_T1_o0,
233: gen_op_movl_T1_o1,
234: gen_op_movl_T1_o2,
235: gen_op_movl_T1_o3,
236: gen_op_movl_T1_o4,
237: gen_op_movl_T1_o5,
238: gen_op_movl_T1_o6,
239: gen_op_movl_T1_o7,
240: gen_op_movl_T1_l0,
241: gen_op_movl_T1_l1,
242: gen_op_movl_T1_l2,
243: gen_op_movl_T1_l3,
244: gen_op_movl_T1_l4,
245: gen_op_movl_T1_l5,
246: gen_op_movl_T1_l6,
247: gen_op_movl_T1_l7,
248: gen_op_movl_T1_i0,
249: gen_op_movl_T1_i1,
250: gen_op_movl_T1_i2,
251: gen_op_movl_T1_i3,
252: gen_op_movl_T1_i4,
253: gen_op_movl_T1_i5,
254: gen_op_movl_T1_i6,
255: gen_op_movl_T1_i7,
256: },
257: {
258: gen_op_movl_T2_g0,
259: gen_op_movl_T2_g1,
260: gen_op_movl_T2_g2,
261: gen_op_movl_T2_g3,
262: gen_op_movl_T2_g4,
263: gen_op_movl_T2_g5,
264: gen_op_movl_T2_g6,
265: gen_op_movl_T2_g7,
266: gen_op_movl_T2_o0,
267: gen_op_movl_T2_o1,
268: gen_op_movl_T2_o2,
269: gen_op_movl_T2_o3,
270: gen_op_movl_T2_o4,
271: gen_op_movl_T2_o5,
272: gen_op_movl_T2_o6,
273: gen_op_movl_T2_o7,
274: gen_op_movl_T2_l0,
275: gen_op_movl_T2_l1,
276: gen_op_movl_T2_l2,
277: gen_op_movl_T2_l3,
278: gen_op_movl_T2_l4,
279: gen_op_movl_T2_l5,
280: gen_op_movl_T2_l6,
281: gen_op_movl_T2_l7,
282: gen_op_movl_T2_i0,
283: gen_op_movl_T2_i1,
284: gen_op_movl_T2_i2,
285: gen_op_movl_T2_i3,
286: gen_op_movl_T2_i4,
287: gen_op_movl_T2_i5,
288: gen_op_movl_T2_i6,
289: gen_op_movl_T2_i7,
290: }
291: };
292:
1.1.1.5 ! root 293: static GenOpFunc1 * const gen_op_movl_TN_im[3] = {
1.1 root 294: gen_op_movl_T0_im,
295: gen_op_movl_T1_im,
296: gen_op_movl_T2_im
297: };
298:
299: // Sign extending version
300: static GenOpFunc1 * const gen_op_movl_TN_sim[3] = {
301: gen_op_movl_T0_sim,
302: gen_op_movl_T1_sim,
303: gen_op_movl_T2_sim
304: };
305:
306: #ifdef TARGET_SPARC64
307: #define GEN32(func, NAME) \
1.1.1.5 ! root 308: static GenOpFunc * const NAME ## _table [64] = { \
1.1 root 309: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
310: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
311: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
312: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
313: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
314: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
315: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
316: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
317: NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0, \
318: NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0, \
319: NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0, \
320: NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0, \
321: }; \
322: static inline void func(int n) \
323: { \
324: NAME ## _table[n](); \
325: }
326: #else
327: #define GEN32(func, NAME) \
1.1.1.5 ! root 328: static GenOpFunc *const NAME ## _table [32] = { \
1.1 root 329: NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
330: NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
331: NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
332: NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
333: NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
334: NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
335: NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
336: NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
337: }; \
338: static inline void func(int n) \
339: { \
340: NAME ## _table[n](); \
341: }
342: #endif
343:
344: /* floating point registers moves */
345: GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
346: GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
347: GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
348: GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
349:
350: GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
351: GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
352: GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
353: GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
354:
355: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 356: GEN32(gen_op_load_fpr_QT0, gen_op_load_fpr_QT0_fprf);
! 357: GEN32(gen_op_load_fpr_QT1, gen_op_load_fpr_QT1_fprf);
! 358: GEN32(gen_op_store_QT0_fpr, gen_op_store_QT0_fpr_fprf);
! 359: GEN32(gen_op_store_QT1_fpr, gen_op_store_QT1_fpr_fprf);
! 360: #endif
1.1 root 361:
1.1.1.5 ! root 362: /* moves */
! 363: #ifdef CONFIG_USER_ONLY
! 364: #define supervisor(dc) 0
! 365: #ifdef TARGET_SPARC64
! 366: #define hypervisor(dc) 0
1.1 root 367: #endif
368: #define gen_op_ldst(name) gen_op_##name##_raw()
369: #else
1.1.1.5 ! root 370: #define supervisor(dc) (dc->mem_idx >= 1)
! 371: #ifdef TARGET_SPARC64
! 372: #define hypervisor(dc) (dc->mem_idx == 2)
! 373: #define OP_LD_TABLE(width) \
! 374: static GenOpFunc * const gen_op_##width[] = { \
! 375: &gen_op_##width##_user, \
! 376: &gen_op_##width##_kernel, \
! 377: &gen_op_##width##_hypv, \
! 378: };
! 379: #else
! 380: #define OP_LD_TABLE(width) \
! 381: static GenOpFunc * const gen_op_##width[] = { \
! 382: &gen_op_##width##_user, \
! 383: &gen_op_##width##_kernel, \
! 384: };
1.1 root 385: #endif
1.1.1.5 ! root 386: #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
1.1 root 387: #endif
388:
1.1.1.5 ! root 389: #ifndef CONFIG_USER_ONLY
1.1 root 390: OP_LD_TABLE(ld);
391: OP_LD_TABLE(st);
392: OP_LD_TABLE(ldub);
393: OP_LD_TABLE(lduh);
394: OP_LD_TABLE(ldsb);
395: OP_LD_TABLE(ldsh);
396: OP_LD_TABLE(stb);
397: OP_LD_TABLE(sth);
398: OP_LD_TABLE(std);
399: OP_LD_TABLE(ldstub);
400: OP_LD_TABLE(swap);
401: OP_LD_TABLE(ldd);
402: OP_LD_TABLE(stf);
403: OP_LD_TABLE(stdf);
404: OP_LD_TABLE(ldf);
405: OP_LD_TABLE(lddf);
406:
407: #ifdef TARGET_SPARC64
1.1.1.5 ! root 408: OP_LD_TABLE(lduw);
1.1 root 409: OP_LD_TABLE(ldsw);
410: OP_LD_TABLE(ldx);
411: OP_LD_TABLE(stx);
1.1.1.5 ! root 412: #endif
! 413: #endif
! 414:
! 415: /* asi moves */
! 416: #ifdef TARGET_SPARC64
! 417: static inline void gen_ld_asi(int insn, int size, int sign)
! 418: {
! 419: int asi, offset;
! 420:
! 421: if (IS_IMM) {
! 422: offset = GET_FIELD(insn, 25, 31);
! 423: gen_op_ld_asi_reg(offset, size, sign);
! 424: } else {
! 425: asi = GET_FIELD(insn, 19, 26);
! 426: gen_op_ld_asi(asi, size, sign);
! 427: }
! 428: }
! 429:
! 430: static inline void gen_st_asi(int insn, int size)
! 431: {
! 432: int asi, offset;
! 433:
! 434: if (IS_IMM) {
! 435: offset = GET_FIELD(insn, 25, 31);
! 436: gen_op_st_asi_reg(offset, size);
! 437: } else {
! 438: asi = GET_FIELD(insn, 19, 26);
! 439: gen_op_st_asi(asi, size);
! 440: }
! 441: }
! 442:
! 443: static inline void gen_ldf_asi(int insn, int size, int rd)
! 444: {
! 445: int asi, offset;
! 446:
! 447: if (IS_IMM) {
! 448: offset = GET_FIELD(insn, 25, 31);
! 449: gen_op_ldf_asi_reg(offset, size, rd);
! 450: } else {
! 451: asi = GET_FIELD(insn, 19, 26);
! 452: gen_op_ldf_asi(asi, size, rd);
! 453: }
! 454: }
! 455:
! 456: static inline void gen_stf_asi(int insn, int size, int rd)
! 457: {
! 458: int asi, offset;
! 459:
! 460: if (IS_IMM) {
! 461: offset = GET_FIELD(insn, 25, 31);
! 462: gen_op_stf_asi_reg(offset, size, rd);
! 463: } else {
! 464: asi = GET_FIELD(insn, 19, 26);
! 465: gen_op_stf_asi(asi, size, rd);
! 466: }
! 467: }
! 468:
! 469: static inline void gen_swap_asi(int insn)
! 470: {
! 471: int asi, offset;
! 472:
! 473: if (IS_IMM) {
! 474: offset = GET_FIELD(insn, 25, 31);
! 475: gen_op_swap_asi_reg(offset);
! 476: } else {
! 477: asi = GET_FIELD(insn, 19, 26);
! 478: gen_op_swap_asi(asi);
! 479: }
! 480: }
! 481:
! 482: static inline void gen_ldstub_asi(int insn)
! 483: {
! 484: int asi, offset;
! 485:
! 486: if (IS_IMM) {
! 487: offset = GET_FIELD(insn, 25, 31);
! 488: gen_op_ldstub_asi_reg(offset);
! 489: } else {
! 490: asi = GET_FIELD(insn, 19, 26);
! 491: gen_op_ldstub_asi(asi);
! 492: }
! 493: }
! 494:
! 495: static inline void gen_ldda_asi(int insn)
! 496: {
! 497: int asi, offset;
! 498:
! 499: if (IS_IMM) {
! 500: offset = GET_FIELD(insn, 25, 31);
! 501: gen_op_ldda_asi_reg(offset);
! 502: } else {
! 503: asi = GET_FIELD(insn, 19, 26);
! 504: gen_op_ldda_asi(asi);
! 505: }
! 506: }
! 507:
! 508: static inline void gen_stda_asi(int insn)
! 509: {
! 510: int asi, offset;
! 511:
! 512: if (IS_IMM) {
! 513: offset = GET_FIELD(insn, 25, 31);
! 514: gen_op_stda_asi_reg(offset);
! 515: } else {
! 516: asi = GET_FIELD(insn, 19, 26);
! 517: gen_op_stda_asi(asi);
! 518: }
! 519: }
! 520:
! 521: static inline void gen_cas_asi(int insn)
! 522: {
! 523: int asi, offset;
! 524:
! 525: if (IS_IMM) {
! 526: offset = GET_FIELD(insn, 25, 31);
! 527: gen_op_cas_asi_reg(offset);
! 528: } else {
! 529: asi = GET_FIELD(insn, 19, 26);
! 530: gen_op_cas_asi(asi);
! 531: }
! 532: }
! 533:
! 534: static inline void gen_casx_asi(int insn)
! 535: {
! 536: int asi, offset;
! 537:
! 538: if (IS_IMM) {
! 539: offset = GET_FIELD(insn, 25, 31);
! 540: gen_op_casx_asi_reg(offset);
! 541: } else {
! 542: asi = GET_FIELD(insn, 19, 26);
! 543: gen_op_casx_asi(asi);
! 544: }
! 545: }
! 546:
! 547: #elif !defined(CONFIG_USER_ONLY)
! 548:
! 549: static inline void gen_ld_asi(int insn, int size, int sign)
! 550: {
! 551: int asi;
! 552:
! 553: asi = GET_FIELD(insn, 19, 26);
! 554: gen_op_ld_asi(asi, size, sign);
! 555: }
! 556:
! 557: static inline void gen_st_asi(int insn, int size)
! 558: {
! 559: int asi;
! 560:
! 561: asi = GET_FIELD(insn, 19, 26);
! 562: gen_op_st_asi(asi, size);
! 563: }
! 564:
! 565: static inline void gen_ldstub_asi(int insn)
! 566: {
! 567: int asi;
! 568:
! 569: asi = GET_FIELD(insn, 19, 26);
! 570: gen_op_ldstub_asi(asi);
! 571: }
! 572:
! 573: static inline void gen_swap_asi(int insn)
! 574: {
! 575: int asi;
! 576:
! 577: asi = GET_FIELD(insn, 19, 26);
! 578: gen_op_swap_asi(asi);
! 579: }
! 580:
! 581: static inline void gen_ldda_asi(int insn)
! 582: {
! 583: int asi;
! 584:
! 585: asi = GET_FIELD(insn, 19, 26);
! 586: gen_op_ld_asi(asi, 8, 0);
! 587: }
! 588:
! 589: static inline void gen_stda_asi(int insn)
! 590: {
! 591: int asi;
! 592:
! 593: asi = GET_FIELD(insn, 19, 26);
! 594: gen_op_st_asi(asi, 8);
! 595: }
1.1 root 596: #endif
597:
598: static inline void gen_movl_imm_TN(int reg, uint32_t imm)
599: {
600: gen_op_movl_TN_im[reg](imm);
601: }
602:
603: static inline void gen_movl_imm_T1(uint32_t val)
604: {
605: gen_movl_imm_TN(1, val);
606: }
607:
608: static inline void gen_movl_imm_T0(uint32_t val)
609: {
610: gen_movl_imm_TN(0, val);
611: }
612:
613: static inline void gen_movl_simm_TN(int reg, int32_t imm)
614: {
615: gen_op_movl_TN_sim[reg](imm);
616: }
617:
618: static inline void gen_movl_simm_T1(int32_t val)
619: {
620: gen_movl_simm_TN(1, val);
621: }
622:
623: static inline void gen_movl_simm_T0(int32_t val)
624: {
625: gen_movl_simm_TN(0, val);
626: }
627:
628: static inline void gen_movl_reg_TN(int reg, int t)
629: {
630: if (reg)
1.1.1.5 ! root 631: gen_op_movl_reg_TN[t][reg] ();
1.1 root 632: else
1.1.1.5 ! root 633: gen_movl_imm_TN(t, 0);
1.1 root 634: }
635:
636: static inline void gen_movl_reg_T0(int reg)
637: {
638: gen_movl_reg_TN(reg, 0);
639: }
640:
641: static inline void gen_movl_reg_T1(int reg)
642: {
643: gen_movl_reg_TN(reg, 1);
644: }
645:
646: static inline void gen_movl_reg_T2(int reg)
647: {
648: gen_movl_reg_TN(reg, 2);
649: }
650:
651: static inline void gen_movl_TN_reg(int reg, int t)
652: {
653: if (reg)
1.1.1.5 ! root 654: gen_op_movl_TN_reg[t][reg] ();
1.1 root 655: }
656:
657: static inline void gen_movl_T0_reg(int reg)
658: {
659: gen_movl_TN_reg(reg, 0);
660: }
661:
662: static inline void gen_movl_T1_reg(int reg)
663: {
664: gen_movl_TN_reg(reg, 1);
665: }
666:
667: static inline void gen_jmp_im(target_ulong pc)
668: {
669: #ifdef TARGET_SPARC64
670: if (pc == (uint32_t)pc) {
671: gen_op_jmp_im(pc);
672: } else {
673: gen_op_jmp_im64(pc >> 32, pc);
674: }
675: #else
676: gen_op_jmp_im(pc);
677: #endif
678: }
679:
680: static inline void gen_movl_npc_im(target_ulong npc)
681: {
682: #ifdef TARGET_SPARC64
683: if (npc == (uint32_t)npc) {
684: gen_op_movl_npc_im(npc);
685: } else {
686: gen_op_movq_npc_im64(npc >> 32, npc);
687: }
688: #else
689: gen_op_movl_npc_im(npc);
690: #endif
691: }
692:
1.1.1.5 ! root 693: static inline void gen_goto_tb(DisasContext *s, int tb_num,
1.1.1.2 root 694: target_ulong pc, target_ulong npc)
695: {
696: TranslationBlock *tb;
697:
698: tb = s->tb;
699: if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
700: (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) {
701: /* jump to same page: we can use a direct jump */
702: if (tb_num == 0)
703: gen_op_goto_tb0(TBPARAM(tb));
704: else
705: gen_op_goto_tb1(TBPARAM(tb));
706: gen_jmp_im(pc);
707: gen_movl_npc_im(npc);
708: gen_op_movl_T0_im((long)tb + tb_num);
709: gen_op_exit_tb();
710: } else {
711: /* jump to another page: currently not optimized */
712: gen_jmp_im(pc);
713: gen_movl_npc_im(npc);
714: gen_op_movl_T0_0();
715: gen_op_exit_tb();
716: }
717: }
718:
1.1.1.5 ! root 719: static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
! 720: target_ulong pc2)
1.1 root 721: {
722: int l1;
723:
724: l1 = gen_new_label();
725:
726: gen_op_jz_T2_label(l1);
727:
1.1.1.2 root 728: gen_goto_tb(dc, 0, pc1, pc1 + 4);
1.1 root 729:
730: gen_set_label(l1);
1.1.1.2 root 731: gen_goto_tb(dc, 1, pc2, pc2 + 4);
1.1 root 732: }
733:
1.1.1.5 ! root 734: static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
! 735: target_ulong pc2)
1.1 root 736: {
737: int l1;
738:
739: l1 = gen_new_label();
740:
741: gen_op_jz_T2_label(l1);
742:
1.1.1.2 root 743: gen_goto_tb(dc, 0, pc2, pc1);
1.1 root 744:
745: gen_set_label(l1);
1.1.1.2 root 746: gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
1.1 root 747: }
748:
1.1.1.5 ! root 749: static inline void gen_branch(DisasContext *dc, target_ulong pc,
! 750: target_ulong npc)
1.1 root 751: {
1.1.1.2 root 752: gen_goto_tb(dc, 0, pc, npc);
1.1 root 753: }
754:
1.1.1.5 ! root 755: static inline void gen_generic_branch(target_ulong npc1, target_ulong npc2)
1.1 root 756: {
757: int l1, l2;
758:
759: l1 = gen_new_label();
760: l2 = gen_new_label();
761: gen_op_jz_T2_label(l1);
762:
763: gen_movl_npc_im(npc1);
764: gen_op_jmp_label(l2);
765:
766: gen_set_label(l1);
767: gen_movl_npc_im(npc2);
768: gen_set_label(l2);
769: }
770:
771: /* call this function before using T2 as it may have been set for a jump */
772: static inline void flush_T2(DisasContext * dc)
773: {
774: if (dc->npc == JUMP_PC) {
1.1.1.5 ! root 775: gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
1.1 root 776: dc->npc = DYNAMIC_PC;
777: }
778: }
779:
780: static inline void save_npc(DisasContext * dc)
781: {
782: if (dc->npc == JUMP_PC) {
1.1.1.5 ! root 783: gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
1.1 root 784: dc->npc = DYNAMIC_PC;
785: } else if (dc->npc != DYNAMIC_PC) {
786: gen_movl_npc_im(dc->npc);
787: }
788: }
789:
790: static inline void save_state(DisasContext * dc)
791: {
792: gen_jmp_im(dc->pc);
793: save_npc(dc);
794: }
795:
796: static inline void gen_mov_pc_npc(DisasContext * dc)
797: {
798: if (dc->npc == JUMP_PC) {
1.1.1.5 ! root 799: gen_generic_branch(dc->jump_pc[0], dc->jump_pc[1]);
1.1 root 800: gen_op_mov_pc_npc();
801: dc->pc = DYNAMIC_PC;
802: } else if (dc->npc == DYNAMIC_PC) {
803: gen_op_mov_pc_npc();
804: dc->pc = DYNAMIC_PC;
805: } else {
806: dc->pc = dc->npc;
807: }
808: }
809:
810: static GenOpFunc * const gen_cond[2][16] = {
811: {
1.1.1.5 ! root 812: gen_op_eval_bn,
! 813: gen_op_eval_be,
! 814: gen_op_eval_ble,
! 815: gen_op_eval_bl,
! 816: gen_op_eval_bleu,
! 817: gen_op_eval_bcs,
! 818: gen_op_eval_bneg,
! 819: gen_op_eval_bvs,
! 820: gen_op_eval_ba,
! 821: gen_op_eval_bne,
! 822: gen_op_eval_bg,
! 823: gen_op_eval_bge,
! 824: gen_op_eval_bgu,
! 825: gen_op_eval_bcc,
! 826: gen_op_eval_bpos,
! 827: gen_op_eval_bvc,
1.1 root 828: },
829: {
830: #ifdef TARGET_SPARC64
1.1.1.5 ! root 831: gen_op_eval_bn,
! 832: gen_op_eval_xbe,
! 833: gen_op_eval_xble,
! 834: gen_op_eval_xbl,
! 835: gen_op_eval_xbleu,
! 836: gen_op_eval_xbcs,
! 837: gen_op_eval_xbneg,
! 838: gen_op_eval_xbvs,
! 839: gen_op_eval_ba,
! 840: gen_op_eval_xbne,
! 841: gen_op_eval_xbg,
! 842: gen_op_eval_xbge,
! 843: gen_op_eval_xbgu,
! 844: gen_op_eval_xbcc,
! 845: gen_op_eval_xbpos,
! 846: gen_op_eval_xbvc,
1.1 root 847: #endif
848: },
849: };
850:
851: static GenOpFunc * const gen_fcond[4][16] = {
852: {
1.1.1.5 ! root 853: gen_op_eval_bn,
! 854: gen_op_eval_fbne,
! 855: gen_op_eval_fblg,
! 856: gen_op_eval_fbul,
! 857: gen_op_eval_fbl,
! 858: gen_op_eval_fbug,
! 859: gen_op_eval_fbg,
! 860: gen_op_eval_fbu,
! 861: gen_op_eval_ba,
! 862: gen_op_eval_fbe,
! 863: gen_op_eval_fbue,
! 864: gen_op_eval_fbge,
! 865: gen_op_eval_fbuge,
! 866: gen_op_eval_fble,
! 867: gen_op_eval_fbule,
! 868: gen_op_eval_fbo,
! 869: },
! 870: #ifdef TARGET_SPARC64
! 871: {
! 872: gen_op_eval_bn,
! 873: gen_op_eval_fbne_fcc1,
! 874: gen_op_eval_fblg_fcc1,
! 875: gen_op_eval_fbul_fcc1,
! 876: gen_op_eval_fbl_fcc1,
! 877: gen_op_eval_fbug_fcc1,
! 878: gen_op_eval_fbg_fcc1,
! 879: gen_op_eval_fbu_fcc1,
! 880: gen_op_eval_ba,
! 881: gen_op_eval_fbe_fcc1,
! 882: gen_op_eval_fbue_fcc1,
! 883: gen_op_eval_fbge_fcc1,
! 884: gen_op_eval_fbuge_fcc1,
! 885: gen_op_eval_fble_fcc1,
! 886: gen_op_eval_fbule_fcc1,
! 887: gen_op_eval_fbo_fcc1,
! 888: },
! 889: {
! 890: gen_op_eval_bn,
! 891: gen_op_eval_fbne_fcc2,
! 892: gen_op_eval_fblg_fcc2,
! 893: gen_op_eval_fbul_fcc2,
! 894: gen_op_eval_fbl_fcc2,
! 895: gen_op_eval_fbug_fcc2,
! 896: gen_op_eval_fbg_fcc2,
! 897: gen_op_eval_fbu_fcc2,
! 898: gen_op_eval_ba,
! 899: gen_op_eval_fbe_fcc2,
! 900: gen_op_eval_fbue_fcc2,
! 901: gen_op_eval_fbge_fcc2,
! 902: gen_op_eval_fbuge_fcc2,
! 903: gen_op_eval_fble_fcc2,
! 904: gen_op_eval_fbule_fcc2,
! 905: gen_op_eval_fbo_fcc2,
! 906: },
! 907: {
! 908: gen_op_eval_bn,
! 909: gen_op_eval_fbne_fcc3,
! 910: gen_op_eval_fblg_fcc3,
! 911: gen_op_eval_fbul_fcc3,
! 912: gen_op_eval_fbl_fcc3,
! 913: gen_op_eval_fbug_fcc3,
! 914: gen_op_eval_fbg_fcc3,
! 915: gen_op_eval_fbu_fcc3,
! 916: gen_op_eval_ba,
! 917: gen_op_eval_fbe_fcc3,
! 918: gen_op_eval_fbue_fcc3,
! 919: gen_op_eval_fbge_fcc3,
! 920: gen_op_eval_fbuge_fcc3,
! 921: gen_op_eval_fble_fcc3,
! 922: gen_op_eval_fbule_fcc3,
! 923: gen_op_eval_fbo_fcc3,
1.1 root 924: },
925: #else
926: {}, {}, {},
927: #endif
928: };
929:
930: #ifdef TARGET_SPARC64
931: static void gen_cond_reg(int cond)
932: {
1.1.1.5 ! root 933: switch (cond) {
! 934: case 0x1:
! 935: gen_op_eval_brz();
! 936: break;
! 937: case 0x2:
! 938: gen_op_eval_brlez();
! 939: break;
! 940: case 0x3:
! 941: gen_op_eval_brlz();
! 942: break;
! 943: case 0x5:
! 944: gen_op_eval_brnz();
! 945: break;
! 946: case 0x6:
! 947: gen_op_eval_brgz();
! 948: break;
1.1 root 949: default:
1.1.1.5 ! root 950: case 0x7:
! 951: gen_op_eval_brgez();
! 952: break;
! 953: }
1.1 root 954: }
955: #endif
956:
957: /* XXX: potentially incorrect if dynamic npc */
958: static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
959: {
960: unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
961: target_ulong target = dc->pc + offset;
1.1.1.5 ! root 962:
1.1 root 963: if (cond == 0x0) {
1.1.1.5 ! root 964: /* unconditional not taken */
! 965: if (a) {
! 966: dc->pc = dc->npc + 4;
! 967: dc->npc = dc->pc + 4;
! 968: } else {
! 969: dc->pc = dc->npc;
! 970: dc->npc = dc->pc + 4;
! 971: }
1.1 root 972: } else if (cond == 0x8) {
1.1.1.5 ! root 973: /* unconditional taken */
! 974: if (a) {
! 975: dc->pc = target;
! 976: dc->npc = dc->pc + 4;
! 977: } else {
! 978: dc->pc = dc->npc;
! 979: dc->npc = target;
! 980: }
1.1 root 981: } else {
982: flush_T2(dc);
983: gen_cond[cc][cond]();
1.1.1.5 ! root 984: if (a) {
! 985: gen_branch_a(dc, target, dc->npc);
1.1 root 986: dc->is_br = 1;
1.1.1.5 ! root 987: } else {
1.1 root 988: dc->pc = dc->npc;
989: dc->jump_pc[0] = target;
990: dc->jump_pc[1] = dc->npc + 4;
991: dc->npc = JUMP_PC;
1.1.1.5 ! root 992: }
1.1 root 993: }
994: }
995:
996: /* XXX: potentially incorrect if dynamic npc */
997: static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc)
998: {
999: unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
1000: target_ulong target = dc->pc + offset;
1001:
1002: if (cond == 0x0) {
1.1.1.5 ! root 1003: /* unconditional not taken */
! 1004: if (a) {
! 1005: dc->pc = dc->npc + 4;
! 1006: dc->npc = dc->pc + 4;
! 1007: } else {
! 1008: dc->pc = dc->npc;
! 1009: dc->npc = dc->pc + 4;
! 1010: }
1.1 root 1011: } else if (cond == 0x8) {
1.1.1.5 ! root 1012: /* unconditional taken */
! 1013: if (a) {
! 1014: dc->pc = target;
! 1015: dc->npc = dc->pc + 4;
! 1016: } else {
! 1017: dc->pc = dc->npc;
! 1018: dc->npc = target;
! 1019: }
1.1 root 1020: } else {
1021: flush_T2(dc);
1022: gen_fcond[cc][cond]();
1.1.1.5 ! root 1023: if (a) {
! 1024: gen_branch_a(dc, target, dc->npc);
1.1 root 1025: dc->is_br = 1;
1.1.1.5 ! root 1026: } else {
1.1 root 1027: dc->pc = dc->npc;
1028: dc->jump_pc[0] = target;
1029: dc->jump_pc[1] = dc->npc + 4;
1030: dc->npc = JUMP_PC;
1.1.1.5 ! root 1031: }
1.1 root 1032: }
1033: }
1034:
1035: #ifdef TARGET_SPARC64
1036: /* XXX: potentially incorrect if dynamic npc */
1037: static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn)
1038: {
1039: unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29));
1040: target_ulong target = dc->pc + offset;
1041:
1042: flush_T2(dc);
1043: gen_cond_reg(cond);
1044: if (a) {
1.1.1.5 ! root 1045: gen_branch_a(dc, target, dc->npc);
! 1046: dc->is_br = 1;
1.1 root 1047: } else {
1.1.1.5 ! root 1048: dc->pc = dc->npc;
! 1049: dc->jump_pc[0] = target;
! 1050: dc->jump_pc[1] = dc->npc + 4;
! 1051: dc->npc = JUMP_PC;
1.1 root 1052: }
1053: }
1054:
1055: static GenOpFunc * const gen_fcmps[4] = {
1056: gen_op_fcmps,
1057: gen_op_fcmps_fcc1,
1058: gen_op_fcmps_fcc2,
1059: gen_op_fcmps_fcc3,
1060: };
1061:
1062: static GenOpFunc * const gen_fcmpd[4] = {
1063: gen_op_fcmpd,
1064: gen_op_fcmpd_fcc1,
1065: gen_op_fcmpd_fcc2,
1066: gen_op_fcmpd_fcc3,
1067: };
1.1.1.5 ! root 1068:
! 1069: #if defined(CONFIG_USER_ONLY)
! 1070: static GenOpFunc * const gen_fcmpq[4] = {
! 1071: gen_op_fcmpq,
! 1072: gen_op_fcmpq_fcc1,
! 1073: gen_op_fcmpq_fcc2,
! 1074: gen_op_fcmpq_fcc3,
! 1075: };
! 1076: #endif
! 1077:
! 1078: static GenOpFunc * const gen_fcmpes[4] = {
! 1079: gen_op_fcmpes,
! 1080: gen_op_fcmpes_fcc1,
! 1081: gen_op_fcmpes_fcc2,
! 1082: gen_op_fcmpes_fcc3,
! 1083: };
! 1084:
! 1085: static GenOpFunc * const gen_fcmped[4] = {
! 1086: gen_op_fcmped,
! 1087: gen_op_fcmped_fcc1,
! 1088: gen_op_fcmped_fcc2,
! 1089: gen_op_fcmped_fcc3,
! 1090: };
! 1091:
! 1092: #if defined(CONFIG_USER_ONLY)
! 1093: static GenOpFunc * const gen_fcmpeq[4] = {
! 1094: gen_op_fcmpeq,
! 1095: gen_op_fcmpeq_fcc1,
! 1096: gen_op_fcmpeq_fcc2,
! 1097: gen_op_fcmpeq_fcc3,
! 1098: };
! 1099: #endif
1.1 root 1100: #endif
1101:
1.1.1.3 root 1102: static int gen_trap_ifnofpu(DisasContext * dc)
1103: {
1104: #if !defined(CONFIG_USER_ONLY)
1105: if (!dc->fpu_enabled) {
1106: save_state(dc);
1107: gen_op_exception(TT_NFPU_INSN);
1108: dc->is_br = 1;
1109: return 1;
1110: }
1111: #endif
1112: return 0;
1113: }
1114:
1.1 root 1115: /* before an instruction, dc->pc must be static */
1116: static void disas_sparc_insn(DisasContext * dc)
1117: {
1118: unsigned int insn, opc, rs1, rs2, rd;
1119:
1120: insn = ldl_code(dc->pc);
1121: opc = GET_FIELD(insn, 0, 1);
1122:
1123: rd = GET_FIELD(insn, 2, 6);
1124: switch (opc) {
1.1.1.5 ! root 1125: case 0: /* branches/sethi */
! 1126: {
! 1127: unsigned int xop = GET_FIELD(insn, 7, 9);
! 1128: int32_t target;
! 1129: switch (xop) {
! 1130: #ifdef TARGET_SPARC64
! 1131: case 0x1: /* V9 BPcc */
! 1132: {
! 1133: int cc;
! 1134:
! 1135: target = GET_FIELD_SP(insn, 0, 18);
! 1136: target = sign_extend(target, 18);
! 1137: target <<= 2;
! 1138: cc = GET_FIELD_SP(insn, 20, 21);
! 1139: if (cc == 0)
! 1140: do_branch(dc, target, insn, 0);
! 1141: else if (cc == 2)
! 1142: do_branch(dc, target, insn, 1);
! 1143: else
! 1144: goto illegal_insn;
! 1145: goto jmp_insn;
! 1146: }
! 1147: case 0x3: /* V9 BPr */
! 1148: {
! 1149: target = GET_FIELD_SP(insn, 0, 13) |
1.1.1.3 root 1150: (GET_FIELD_SP(insn, 20, 21) << 14);
1.1.1.5 ! root 1151: target = sign_extend(target, 16);
! 1152: target <<= 2;
! 1153: rs1 = GET_FIELD(insn, 13, 17);
! 1154: gen_movl_reg_T0(rs1);
! 1155: do_branch_reg(dc, target, insn);
! 1156: goto jmp_insn;
! 1157: }
! 1158: case 0x5: /* V9 FBPcc */
! 1159: {
! 1160: int cc = GET_FIELD_SP(insn, 20, 21);
1.1.1.3 root 1161: if (gen_trap_ifnofpu(dc))
1162: goto jmp_insn;
1.1.1.5 ! root 1163: target = GET_FIELD_SP(insn, 0, 18);
! 1164: target = sign_extend(target, 19);
! 1165: target <<= 2;
! 1166: do_fbranch(dc, target, insn, cc);
! 1167: goto jmp_insn;
! 1168: }
! 1169: #else
! 1170: case 0x7: /* CBN+x */
! 1171: {
! 1172: goto ncp_insn;
! 1173: }
! 1174: #endif
! 1175: case 0x2: /* BN+x */
! 1176: {
! 1177: target = GET_FIELD(insn, 10, 31);
! 1178: target = sign_extend(target, 22);
! 1179: target <<= 2;
! 1180: do_branch(dc, target, insn, 0);
! 1181: goto jmp_insn;
! 1182: }
! 1183: case 0x6: /* FBN+x */
! 1184: {
1.1.1.3 root 1185: if (gen_trap_ifnofpu(dc))
1186: goto jmp_insn;
1.1.1.5 ! root 1187: target = GET_FIELD(insn, 10, 31);
! 1188: target = sign_extend(target, 22);
! 1189: target <<= 2;
! 1190: do_fbranch(dc, target, insn, 0);
! 1191: goto jmp_insn;
! 1192: }
! 1193: case 0x4: /* SETHI */
1.1 root 1194: #define OPTIM
1195: #if defined(OPTIM)
1.1.1.5 ! root 1196: if (rd) { // nop
1.1 root 1197: #endif
1.1.1.5 ! root 1198: uint32_t value = GET_FIELD(insn, 10, 31);
! 1199: gen_movl_imm_T0(value << 10);
! 1200: gen_movl_T0_reg(rd);
1.1 root 1201: #if defined(OPTIM)
1.1.1.5 ! root 1202: }
1.1 root 1203: #endif
1.1.1.5 ! root 1204: break;
! 1205: case 0x0: /* UNIMPL */
! 1206: default:
1.1 root 1207: goto illegal_insn;
1.1.1.5 ! root 1208: }
! 1209: break;
! 1210: }
! 1211: break;
1.1 root 1212: case 1:
1.1.1.5 ! root 1213: /*CALL*/ {
! 1214: target_long target = GET_FIELDs(insn, 2, 31) << 2;
1.1 root 1215:
1216: #ifdef TARGET_SPARC64
1.1.1.5 ! root 1217: if (dc->pc == (uint32_t)dc->pc) {
! 1218: gen_op_movl_T0_im(dc->pc);
! 1219: } else {
! 1220: gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
! 1221: }
1.1 root 1222: #else
1.1.1.5 ! root 1223: gen_op_movl_T0_im(dc->pc);
1.1 root 1224: #endif
1.1.1.5 ! root 1225: gen_movl_T0_reg(15);
! 1226: target += dc->pc;
1.1 root 1227: gen_mov_pc_npc(dc);
1.1.1.5 ! root 1228: dc->npc = target;
! 1229: }
! 1230: goto jmp_insn;
! 1231: case 2: /* FPU & Logical Operations */
! 1232: {
! 1233: unsigned int xop = GET_FIELD(insn, 7, 12);
! 1234: if (xop == 0x3a) { /* generate trap */
1.1 root 1235: int cond;
1236:
1237: rs1 = GET_FIELD(insn, 13, 17);
1238: gen_movl_reg_T0(rs1);
1.1.1.5 ! root 1239: if (IS_IMM) {
! 1240: rs2 = GET_FIELD(insn, 25, 31);
1.1 root 1241: #if defined(OPTIM)
1.1.1.5 ! root 1242: if (rs2 != 0) {
1.1 root 1243: #endif
1.1.1.5 ! root 1244: gen_movl_simm_T1(rs2);
! 1245: gen_op_add_T1_T0();
1.1 root 1246: #if defined(OPTIM)
1.1.1.5 ! root 1247: }
1.1 root 1248: #endif
1249: } else {
1250: rs2 = GET_FIELD(insn, 27, 31);
1251: #if defined(OPTIM)
1.1.1.5 ! root 1252: if (rs2 != 0) {
1.1 root 1253: #endif
1.1.1.5 ! root 1254: gen_movl_reg_T1(rs2);
! 1255: gen_op_add_T1_T0();
1.1 root 1256: #if defined(OPTIM)
1.1.1.5 ! root 1257: }
1.1 root 1258: #endif
1259: }
1260: cond = GET_FIELD(insn, 3, 6);
1261: if (cond == 0x8) {
1.1.1.3 root 1262: save_state(dc);
1.1 root 1263: gen_op_trap_T0();
1264: } else if (cond != 0) {
1265: #ifdef TARGET_SPARC64
1.1.1.5 ! root 1266: /* V9 icc/xcc */
! 1267: int cc = GET_FIELD_SP(insn, 11, 12);
! 1268: flush_T2(dc);
1.1.1.3 root 1269: save_state(dc);
1.1.1.5 ! root 1270: if (cc == 0)
! 1271: gen_cond[0][cond]();
! 1272: else if (cc == 2)
! 1273: gen_cond[1][cond]();
! 1274: else
! 1275: goto illegal_insn;
1.1 root 1276: #else
1.1.1.5 ! root 1277: flush_T2(dc);
1.1.1.3 root 1278: save_state(dc);
1.1.1.5 ! root 1279: gen_cond[0][cond]();
1.1 root 1280: #endif
1281: gen_op_trapcc_T0();
1282: }
1.1.1.3 root 1283: gen_op_next_insn();
1284: gen_op_movl_T0_0();
1285: gen_op_exit_tb();
1286: dc->is_br = 1;
1287: goto jmp_insn;
1.1 root 1288: } else if (xop == 0x28) {
1289: rs1 = GET_FIELD(insn, 13, 17);
1290: switch(rs1) {
1291: case 0: /* rdy */
1.1.1.5 ! root 1292: #ifndef TARGET_SPARC64
! 1293: case 0x01 ... 0x0e: /* undefined in the SPARCv8
! 1294: manual, rdy on the microSPARC
! 1295: II */
! 1296: case 0x0f: /* stbar in the SPARCv8 manual,
! 1297: rdy on the microSPARC II */
! 1298: case 0x10 ... 0x1f: /* implementation-dependent in the
! 1299: SPARCv8 manual, rdy on the
! 1300: microSPARC II */
! 1301: #endif
! 1302: gen_op_movtl_T0_env(offsetof(CPUSPARCState, y));
1.1 root 1303: gen_movl_T0_reg(rd);
1304: break;
1305: #ifdef TARGET_SPARC64
1.1.1.5 ! root 1306: case 0x2: /* V9 rdccr */
1.1 root 1307: gen_op_rdccr();
1308: gen_movl_T0_reg(rd);
1309: break;
1.1.1.5 ! root 1310: case 0x3: /* V9 rdasi */
! 1311: gen_op_movl_T0_env(offsetof(CPUSPARCState, asi));
1.1 root 1312: gen_movl_T0_reg(rd);
1313: break;
1.1.1.5 ! root 1314: case 0x4: /* V9 rdtick */
1.1 root 1315: gen_op_rdtick();
1316: gen_movl_T0_reg(rd);
1317: break;
1.1.1.5 ! root 1318: case 0x5: /* V9 rdpc */
! 1319: if (dc->pc == (uint32_t)dc->pc) {
! 1320: gen_op_movl_T0_im(dc->pc);
! 1321: } else {
! 1322: gen_op_movq_T0_im64(dc->pc >> 32, dc->pc);
! 1323: }
! 1324: gen_movl_T0_reg(rd);
! 1325: break;
! 1326: case 0x6: /* V9 rdfprs */
! 1327: gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs));
1.1 root 1328: gen_movl_T0_reg(rd);
1329: break;
1.1.1.5 ! root 1330: case 0xf: /* V9 membar */
! 1331: break; /* no effect */
! 1332: case 0x13: /* Graphics Status */
1.1.1.3 root 1333: if (gen_trap_ifnofpu(dc))
1334: goto jmp_insn;
1.1.1.5 ! root 1335: gen_op_movtl_T0_env(offsetof(CPUSPARCState, gsr));
1.1.1.3 root 1336: gen_movl_T0_reg(rd);
1337: break;
1.1.1.5 ! root 1338: case 0x17: /* Tick compare */
! 1339: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr));
1.1 root 1340: gen_movl_T0_reg(rd);
1341: break;
1.1.1.5 ! root 1342: case 0x18: /* System tick */
! 1343: gen_op_rdstick();
1.1 root 1344: gen_movl_T0_reg(rd);
1345: break;
1.1.1.5 ! root 1346: case 0x19: /* System tick compare */
! 1347: gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr));
1.1 root 1348: gen_movl_T0_reg(rd);
1349: break;
1.1.1.5 ! root 1350: case 0x10: /* Performance Control */
! 1351: case 0x11: /* Performance Instrumentation Counter */
! 1352: case 0x12: /* Dispatch Control */
! 1353: case 0x14: /* Softint set, WO */
! 1354: case 0x15: /* Softint clear, WO */
! 1355: case 0x16: /* Softint write */
1.1 root 1356: #endif
1357: default:
1358: goto illegal_insn;
1359: }
1360: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 1361: } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
1.1 root 1362: #ifndef TARGET_SPARC64
1.1.1.5 ! root 1363: if (!supervisor(dc))
! 1364: goto priv_insn;
1.1 root 1365: gen_op_rdpsr();
1.1.1.5 ! root 1366: #else
! 1367: if (!hypervisor(dc))
! 1368: goto priv_insn;
! 1369: rs1 = GET_FIELD(insn, 13, 17);
! 1370: switch (rs1) {
! 1371: case 0: // hpstate
! 1372: // gen_op_rdhpstate();
! 1373: break;
! 1374: case 1: // htstate
! 1375: // gen_op_rdhtstate();
! 1376: break;
! 1377: case 3: // hintp
! 1378: gen_op_movl_T0_env(offsetof(CPUSPARCState, hintp));
! 1379: break;
! 1380: case 5: // htba
! 1381: gen_op_movl_T0_env(offsetof(CPUSPARCState, htba));
! 1382: break;
! 1383: case 6: // hver
! 1384: gen_op_movl_T0_env(offsetof(CPUSPARCState, hver));
! 1385: break;
! 1386: case 31: // hstick_cmpr
! 1387: gen_op_movl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
! 1388: break;
! 1389: default:
! 1390: goto illegal_insn;
! 1391: }
! 1392: #endif
1.1 root 1393: gen_movl_T0_reg(rd);
1394: break;
1395: } else if (xop == 0x2a) { /* rdwim / V9 rdpr */
1.1.1.5 ! root 1396: if (!supervisor(dc))
! 1397: goto priv_insn;
1.1 root 1398: #ifdef TARGET_SPARC64
1399: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 1400: switch (rs1) {
! 1401: case 0: // tpc
! 1402: gen_op_rdtpc();
! 1403: break;
! 1404: case 1: // tnpc
! 1405: gen_op_rdtnpc();
! 1406: break;
! 1407: case 2: // tstate
! 1408: gen_op_rdtstate();
! 1409: break;
! 1410: case 3: // tt
! 1411: gen_op_rdtt();
! 1412: break;
! 1413: case 4: // tick
! 1414: gen_op_rdtick();
! 1415: break;
! 1416: case 5: // tba
! 1417: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
! 1418: break;
! 1419: case 6: // pstate
! 1420: gen_op_rdpstate();
! 1421: break;
! 1422: case 7: // tl
! 1423: gen_op_movl_T0_env(offsetof(CPUSPARCState, tl));
! 1424: break;
! 1425: case 8: // pil
! 1426: gen_op_movl_T0_env(offsetof(CPUSPARCState, psrpil));
! 1427: break;
! 1428: case 9: // cwp
! 1429: gen_op_rdcwp();
! 1430: break;
! 1431: case 10: // cansave
! 1432: gen_op_movl_T0_env(offsetof(CPUSPARCState, cansave));
! 1433: break;
! 1434: case 11: // canrestore
! 1435: gen_op_movl_T0_env(offsetof(CPUSPARCState, canrestore));
! 1436: break;
! 1437: case 12: // cleanwin
! 1438: gen_op_movl_T0_env(offsetof(CPUSPARCState, cleanwin));
! 1439: break;
! 1440: case 13: // otherwin
! 1441: gen_op_movl_T0_env(offsetof(CPUSPARCState, otherwin));
! 1442: break;
! 1443: case 14: // wstate
! 1444: gen_op_movl_T0_env(offsetof(CPUSPARCState, wstate));
! 1445: break;
! 1446: case 16: // UA2005 gl
! 1447: gen_op_movl_T0_env(offsetof(CPUSPARCState, gl));
! 1448: break;
! 1449: case 26: // UA2005 strand status
! 1450: if (!hypervisor(dc))
! 1451: goto priv_insn;
! 1452: gen_op_movl_T0_env(offsetof(CPUSPARCState, ssr));
! 1453: break;
! 1454: case 31: // ver
! 1455: gen_op_movtl_T0_env(offsetof(CPUSPARCState, version));
! 1456: break;
! 1457: case 15: // fq
! 1458: default:
! 1459: goto illegal_insn;
! 1460: }
1.1 root 1461: #else
1.1.1.5 ! root 1462: gen_op_movl_T0_env(offsetof(CPUSPARCState, wim));
1.1 root 1463: #endif
1464: gen_movl_T0_reg(rd);
1465: break;
1466: } else if (xop == 0x2b) { /* rdtbr / V9 flushw */
1467: #ifdef TARGET_SPARC64
1.1.1.5 ! root 1468: gen_op_flushw();
1.1 root 1469: #else
1.1.1.5 ! root 1470: if (!supervisor(dc))
! 1471: goto priv_insn;
! 1472: gen_op_movtl_T0_env(offsetof(CPUSPARCState, tbr));
1.1 root 1473: gen_movl_T0_reg(rd);
1474: #endif
1475: break;
1476: #endif
1.1.1.5 ! root 1477: } else if (xop == 0x34) { /* FPU Operations */
1.1.1.3 root 1478: if (gen_trap_ifnofpu(dc))
1479: goto jmp_insn;
1.1.1.5 ! root 1480: gen_op_clear_ieee_excp_and_FTT();
1.1 root 1481: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 1482: rs2 = GET_FIELD(insn, 27, 31);
! 1483: xop = GET_FIELD(insn, 18, 26);
! 1484: switch (xop) {
! 1485: case 0x1: /* fmovs */
! 1486: gen_op_load_fpr_FT0(rs2);
! 1487: gen_op_store_FT0_fpr(rd);
! 1488: break;
! 1489: case 0x5: /* fnegs */
! 1490: gen_op_load_fpr_FT1(rs2);
! 1491: gen_op_fnegs();
! 1492: gen_op_store_FT0_fpr(rd);
! 1493: break;
! 1494: case 0x9: /* fabss */
! 1495: gen_op_load_fpr_FT1(rs2);
! 1496: gen_op_fabss();
! 1497: gen_op_store_FT0_fpr(rd);
! 1498: break;
! 1499: case 0x29: /* fsqrts */
! 1500: gen_op_load_fpr_FT1(rs2);
! 1501: gen_op_fsqrts();
! 1502: gen_op_store_FT0_fpr(rd);
! 1503: break;
! 1504: case 0x2a: /* fsqrtd */
! 1505: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1506: gen_op_fsqrtd();
! 1507: gen_op_store_DT0_fpr(DFPREG(rd));
! 1508: break;
! 1509: case 0x2b: /* fsqrtq */
! 1510: #if defined(CONFIG_USER_ONLY)
! 1511: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1512: gen_op_fsqrtq();
! 1513: gen_op_store_QT0_fpr(QFPREG(rd));
! 1514: break;
! 1515: #else
! 1516: goto nfpu_insn;
1.1 root 1517: #endif
1.1.1.5 ! root 1518: case 0x41:
! 1519: gen_op_load_fpr_FT0(rs1);
! 1520: gen_op_load_fpr_FT1(rs2);
! 1521: gen_op_fadds();
! 1522: gen_op_store_FT0_fpr(rd);
! 1523: break;
! 1524: case 0x42:
! 1525: gen_op_load_fpr_DT0(DFPREG(rs1));
! 1526: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1527: gen_op_faddd();
! 1528: gen_op_store_DT0_fpr(DFPREG(rd));
! 1529: break;
! 1530: case 0x43: /* faddq */
! 1531: #if defined(CONFIG_USER_ONLY)
! 1532: gen_op_load_fpr_QT0(QFPREG(rs1));
! 1533: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1534: gen_op_faddq();
! 1535: gen_op_store_QT0_fpr(QFPREG(rd));
! 1536: break;
! 1537: #else
! 1538: goto nfpu_insn;
1.1 root 1539: #endif
1.1.1.5 ! root 1540: case 0x45:
! 1541: gen_op_load_fpr_FT0(rs1);
! 1542: gen_op_load_fpr_FT1(rs2);
! 1543: gen_op_fsubs();
! 1544: gen_op_store_FT0_fpr(rd);
! 1545: break;
! 1546: case 0x46:
! 1547: gen_op_load_fpr_DT0(DFPREG(rs1));
! 1548: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1549: gen_op_fsubd();
! 1550: gen_op_store_DT0_fpr(DFPREG(rd));
! 1551: break;
! 1552: case 0x47: /* fsubq */
! 1553: #if defined(CONFIG_USER_ONLY)
! 1554: gen_op_load_fpr_QT0(QFPREG(rs1));
! 1555: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1556: gen_op_fsubq();
! 1557: gen_op_store_QT0_fpr(QFPREG(rd));
! 1558: break;
! 1559: #else
! 1560: goto nfpu_insn;
! 1561: #endif
! 1562: case 0x49:
! 1563: gen_op_load_fpr_FT0(rs1);
! 1564: gen_op_load_fpr_FT1(rs2);
! 1565: gen_op_fmuls();
! 1566: gen_op_store_FT0_fpr(rd);
! 1567: break;
! 1568: case 0x4a:
! 1569: gen_op_load_fpr_DT0(DFPREG(rs1));
! 1570: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1571: gen_op_fmuld();
! 1572: gen_op_store_DT0_fpr(DFPREG(rd));
! 1573: break;
! 1574: case 0x4b: /* fmulq */
! 1575: #if defined(CONFIG_USER_ONLY)
! 1576: gen_op_load_fpr_QT0(QFPREG(rs1));
! 1577: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1578: gen_op_fmulq();
! 1579: gen_op_store_QT0_fpr(QFPREG(rd));
! 1580: break;
! 1581: #else
! 1582: goto nfpu_insn;
! 1583: #endif
! 1584: case 0x4d:
! 1585: gen_op_load_fpr_FT0(rs1);
! 1586: gen_op_load_fpr_FT1(rs2);
! 1587: gen_op_fdivs();
! 1588: gen_op_store_FT0_fpr(rd);
! 1589: break;
! 1590: case 0x4e:
! 1591: gen_op_load_fpr_DT0(DFPREG(rs1));
! 1592: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1593: gen_op_fdivd();
! 1594: gen_op_store_DT0_fpr(DFPREG(rd));
! 1595: break;
! 1596: case 0x4f: /* fdivq */
! 1597: #if defined(CONFIG_USER_ONLY)
! 1598: gen_op_load_fpr_QT0(QFPREG(rs1));
! 1599: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1600: gen_op_fdivq();
! 1601: gen_op_store_QT0_fpr(QFPREG(rd));
! 1602: break;
! 1603: #else
! 1604: goto nfpu_insn;
! 1605: #endif
! 1606: case 0x69:
! 1607: gen_op_load_fpr_FT0(rs1);
! 1608: gen_op_load_fpr_FT1(rs2);
! 1609: gen_op_fsmuld();
! 1610: gen_op_store_DT0_fpr(DFPREG(rd));
! 1611: break;
! 1612: case 0x6e: /* fdmulq */
! 1613: #if defined(CONFIG_USER_ONLY)
! 1614: gen_op_load_fpr_DT0(DFPREG(rs1));
! 1615: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1616: gen_op_fdmulq();
! 1617: gen_op_store_QT0_fpr(QFPREG(rd));
! 1618: break;
! 1619: #else
! 1620: goto nfpu_insn;
! 1621: #endif
! 1622: case 0xc4:
! 1623: gen_op_load_fpr_FT1(rs2);
! 1624: gen_op_fitos();
! 1625: gen_op_store_FT0_fpr(rd);
! 1626: break;
! 1627: case 0xc6:
! 1628: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1629: gen_op_fdtos();
! 1630: gen_op_store_FT0_fpr(rd);
! 1631: break;
! 1632: case 0xc7: /* fqtos */
! 1633: #if defined(CONFIG_USER_ONLY)
! 1634: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1635: gen_op_fqtos();
! 1636: gen_op_store_FT0_fpr(rd);
! 1637: break;
! 1638: #else
! 1639: goto nfpu_insn;
! 1640: #endif
! 1641: case 0xc8:
! 1642: gen_op_load_fpr_FT1(rs2);
! 1643: gen_op_fitod();
! 1644: gen_op_store_DT0_fpr(DFPREG(rd));
! 1645: break;
! 1646: case 0xc9:
! 1647: gen_op_load_fpr_FT1(rs2);
! 1648: gen_op_fstod();
! 1649: gen_op_store_DT0_fpr(DFPREG(rd));
! 1650: break;
! 1651: case 0xcb: /* fqtod */
! 1652: #if defined(CONFIG_USER_ONLY)
! 1653: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1654: gen_op_fqtod();
! 1655: gen_op_store_DT0_fpr(DFPREG(rd));
! 1656: break;
! 1657: #else
! 1658: goto nfpu_insn;
! 1659: #endif
! 1660: case 0xcc: /* fitoq */
! 1661: #if defined(CONFIG_USER_ONLY)
! 1662: gen_op_load_fpr_FT1(rs2);
! 1663: gen_op_fitoq();
! 1664: gen_op_store_QT0_fpr(QFPREG(rd));
! 1665: break;
! 1666: #else
! 1667: goto nfpu_insn;
! 1668: #endif
! 1669: case 0xcd: /* fstoq */
! 1670: #if defined(CONFIG_USER_ONLY)
! 1671: gen_op_load_fpr_FT1(rs2);
! 1672: gen_op_fstoq();
! 1673: gen_op_store_QT0_fpr(QFPREG(rd));
! 1674: break;
! 1675: #else
! 1676: goto nfpu_insn;
! 1677: #endif
! 1678: case 0xce: /* fdtoq */
! 1679: #if defined(CONFIG_USER_ONLY)
! 1680: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1681: gen_op_fdtoq();
! 1682: gen_op_store_QT0_fpr(QFPREG(rd));
! 1683: break;
! 1684: #else
! 1685: goto nfpu_insn;
! 1686: #endif
! 1687: case 0xd1:
! 1688: gen_op_load_fpr_FT1(rs2);
! 1689: gen_op_fstoi();
! 1690: gen_op_store_FT0_fpr(rd);
! 1691: break;
! 1692: case 0xd2:
! 1693: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1694: gen_op_fdtoi();
! 1695: gen_op_store_FT0_fpr(rd);
! 1696: break;
! 1697: case 0xd3: /* fqtoi */
! 1698: #if defined(CONFIG_USER_ONLY)
! 1699: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1700: gen_op_fqtoi();
! 1701: gen_op_store_FT0_fpr(rd);
! 1702: break;
! 1703: #else
! 1704: goto nfpu_insn;
! 1705: #endif
! 1706: #ifdef TARGET_SPARC64
! 1707: case 0x2: /* V9 fmovd */
! 1708: gen_op_load_fpr_DT0(DFPREG(rs2));
! 1709: gen_op_store_DT0_fpr(DFPREG(rd));
! 1710: break;
! 1711: case 0x3: /* V9 fmovq */
! 1712: #if defined(CONFIG_USER_ONLY)
! 1713: gen_op_load_fpr_QT0(QFPREG(rs2));
! 1714: gen_op_store_QT0_fpr(QFPREG(rd));
! 1715: break;
! 1716: #else
! 1717: goto nfpu_insn;
! 1718: #endif
! 1719: case 0x6: /* V9 fnegd */
! 1720: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1721: gen_op_fnegd();
! 1722: gen_op_store_DT0_fpr(DFPREG(rd));
! 1723: break;
! 1724: case 0x7: /* V9 fnegq */
! 1725: #if defined(CONFIG_USER_ONLY)
! 1726: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1727: gen_op_fnegq();
! 1728: gen_op_store_QT0_fpr(QFPREG(rd));
! 1729: break;
! 1730: #else
! 1731: goto nfpu_insn;
! 1732: #endif
! 1733: case 0xa: /* V9 fabsd */
! 1734: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1735: gen_op_fabsd();
! 1736: gen_op_store_DT0_fpr(DFPREG(rd));
! 1737: break;
! 1738: case 0xb: /* V9 fabsq */
! 1739: #if defined(CONFIG_USER_ONLY)
! 1740: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1741: gen_op_fabsq();
! 1742: gen_op_store_QT0_fpr(QFPREG(rd));
! 1743: break;
! 1744: #else
! 1745: goto nfpu_insn;
! 1746: #endif
! 1747: case 0x81: /* V9 fstox */
! 1748: gen_op_load_fpr_FT1(rs2);
! 1749: gen_op_fstox();
! 1750: gen_op_store_DT0_fpr(DFPREG(rd));
! 1751: break;
! 1752: case 0x82: /* V9 fdtox */
! 1753: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1754: gen_op_fdtox();
! 1755: gen_op_store_DT0_fpr(DFPREG(rd));
! 1756: break;
! 1757: case 0x83: /* V9 fqtox */
! 1758: #if defined(CONFIG_USER_ONLY)
! 1759: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1760: gen_op_fqtox();
! 1761: gen_op_store_DT0_fpr(DFPREG(rd));
! 1762: break;
! 1763: #else
! 1764: goto nfpu_insn;
! 1765: #endif
! 1766: case 0x84: /* V9 fxtos */
! 1767: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1768: gen_op_fxtos();
! 1769: gen_op_store_FT0_fpr(rd);
! 1770: break;
! 1771: case 0x88: /* V9 fxtod */
! 1772: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1773: gen_op_fxtod();
! 1774: gen_op_store_DT0_fpr(DFPREG(rd));
! 1775: break;
! 1776: case 0x8c: /* V9 fxtoq */
! 1777: #if defined(CONFIG_USER_ONLY)
! 1778: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1779: gen_op_fxtoq();
! 1780: gen_op_store_QT0_fpr(QFPREG(rd));
! 1781: break;
! 1782: #else
! 1783: goto nfpu_insn;
! 1784: #endif
! 1785: #endif
! 1786: default:
! 1787: goto illegal_insn;
! 1788: }
! 1789: } else if (xop == 0x35) { /* FPU Operations */
! 1790: #ifdef TARGET_SPARC64
! 1791: int cond;
! 1792: #endif
! 1793: if (gen_trap_ifnofpu(dc))
! 1794: goto jmp_insn;
! 1795: gen_op_clear_ieee_excp_and_FTT();
! 1796: rs1 = GET_FIELD(insn, 13, 17);
! 1797: rs2 = GET_FIELD(insn, 27, 31);
! 1798: xop = GET_FIELD(insn, 18, 26);
! 1799: #ifdef TARGET_SPARC64
! 1800: if ((xop & 0x11f) == 0x005) { // V9 fmovsr
! 1801: cond = GET_FIELD_SP(insn, 14, 17);
! 1802: gen_op_load_fpr_FT0(rd);
! 1803: gen_op_load_fpr_FT1(rs2);
! 1804: rs1 = GET_FIELD(insn, 13, 17);
! 1805: gen_movl_reg_T0(rs1);
! 1806: flush_T2(dc);
! 1807: gen_cond_reg(cond);
! 1808: gen_op_fmovs_cc();
! 1809: gen_op_store_FT0_fpr(rd);
! 1810: break;
! 1811: } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
! 1812: cond = GET_FIELD_SP(insn, 14, 17);
! 1813: gen_op_load_fpr_DT0(DFPREG(rd));
! 1814: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1815: flush_T2(dc);
! 1816: rs1 = GET_FIELD(insn, 13, 17);
! 1817: gen_movl_reg_T0(rs1);
! 1818: gen_cond_reg(cond);
! 1819: gen_op_fmovs_cc();
! 1820: gen_op_store_DT0_fpr(DFPREG(rd));
! 1821: break;
! 1822: } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
! 1823: #if defined(CONFIG_USER_ONLY)
! 1824: cond = GET_FIELD_SP(insn, 14, 17);
! 1825: gen_op_load_fpr_QT0(QFPREG(rd));
! 1826: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1827: flush_T2(dc);
! 1828: rs1 = GET_FIELD(insn, 13, 17);
! 1829: gen_movl_reg_T0(rs1);
! 1830: gen_cond_reg(cond);
! 1831: gen_op_fmovq_cc();
! 1832: gen_op_store_QT0_fpr(QFPREG(rd));
! 1833: break;
! 1834: #else
! 1835: goto nfpu_insn;
! 1836: #endif
! 1837: }
! 1838: #endif
! 1839: switch (xop) {
! 1840: #ifdef TARGET_SPARC64
! 1841: case 0x001: /* V9 fmovscc %fcc0 */
! 1842: cond = GET_FIELD_SP(insn, 14, 17);
! 1843: gen_op_load_fpr_FT0(rd);
! 1844: gen_op_load_fpr_FT1(rs2);
! 1845: flush_T2(dc);
! 1846: gen_fcond[0][cond]();
! 1847: gen_op_fmovs_cc();
! 1848: gen_op_store_FT0_fpr(rd);
! 1849: break;
! 1850: case 0x002: /* V9 fmovdcc %fcc0 */
! 1851: cond = GET_FIELD_SP(insn, 14, 17);
! 1852: gen_op_load_fpr_DT0(DFPREG(rd));
! 1853: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1854: flush_T2(dc);
! 1855: gen_fcond[0][cond]();
! 1856: gen_op_fmovd_cc();
! 1857: gen_op_store_DT0_fpr(DFPREG(rd));
! 1858: break;
! 1859: case 0x003: /* V9 fmovqcc %fcc0 */
! 1860: #if defined(CONFIG_USER_ONLY)
! 1861: cond = GET_FIELD_SP(insn, 14, 17);
! 1862: gen_op_load_fpr_QT0(QFPREG(rd));
! 1863: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1864: flush_T2(dc);
! 1865: gen_fcond[0][cond]();
! 1866: gen_op_fmovq_cc();
! 1867: gen_op_store_QT0_fpr(QFPREG(rd));
! 1868: break;
! 1869: #else
! 1870: goto nfpu_insn;
! 1871: #endif
! 1872: case 0x041: /* V9 fmovscc %fcc1 */
! 1873: cond = GET_FIELD_SP(insn, 14, 17);
! 1874: gen_op_load_fpr_FT0(rd);
! 1875: gen_op_load_fpr_FT1(rs2);
! 1876: flush_T2(dc);
! 1877: gen_fcond[1][cond]();
! 1878: gen_op_fmovs_cc();
! 1879: gen_op_store_FT0_fpr(rd);
! 1880: break;
! 1881: case 0x042: /* V9 fmovdcc %fcc1 */
! 1882: cond = GET_FIELD_SP(insn, 14, 17);
! 1883: gen_op_load_fpr_DT0(DFPREG(rd));
! 1884: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1885: flush_T2(dc);
! 1886: gen_fcond[1][cond]();
! 1887: gen_op_fmovd_cc();
! 1888: gen_op_store_DT0_fpr(DFPREG(rd));
! 1889: break;
! 1890: case 0x043: /* V9 fmovqcc %fcc1 */
! 1891: #if defined(CONFIG_USER_ONLY)
! 1892: cond = GET_FIELD_SP(insn, 14, 17);
! 1893: gen_op_load_fpr_QT0(QFPREG(rd));
! 1894: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1895: flush_T2(dc);
! 1896: gen_fcond[1][cond]();
! 1897: gen_op_fmovq_cc();
! 1898: gen_op_store_QT0_fpr(QFPREG(rd));
! 1899: break;
! 1900: #else
! 1901: goto nfpu_insn;
! 1902: #endif
! 1903: case 0x081: /* V9 fmovscc %fcc2 */
! 1904: cond = GET_FIELD_SP(insn, 14, 17);
! 1905: gen_op_load_fpr_FT0(rd);
! 1906: gen_op_load_fpr_FT1(rs2);
! 1907: flush_T2(dc);
! 1908: gen_fcond[2][cond]();
! 1909: gen_op_fmovs_cc();
! 1910: gen_op_store_FT0_fpr(rd);
! 1911: break;
! 1912: case 0x082: /* V9 fmovdcc %fcc2 */
! 1913: cond = GET_FIELD_SP(insn, 14, 17);
! 1914: gen_op_load_fpr_DT0(DFPREG(rd));
! 1915: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1916: flush_T2(dc);
! 1917: gen_fcond[2][cond]();
! 1918: gen_op_fmovd_cc();
! 1919: gen_op_store_DT0_fpr(DFPREG(rd));
! 1920: break;
! 1921: case 0x083: /* V9 fmovqcc %fcc2 */
! 1922: #if defined(CONFIG_USER_ONLY)
! 1923: cond = GET_FIELD_SP(insn, 14, 17);
! 1924: gen_op_load_fpr_QT0(rd);
! 1925: gen_op_load_fpr_QT1(rs2);
! 1926: flush_T2(dc);
! 1927: gen_fcond[2][cond]();
! 1928: gen_op_fmovq_cc();
! 1929: gen_op_store_QT0_fpr(rd);
! 1930: break;
! 1931: #else
! 1932: goto nfpu_insn;
! 1933: #endif
! 1934: case 0x0c1: /* V9 fmovscc %fcc3 */
! 1935: cond = GET_FIELD_SP(insn, 14, 17);
! 1936: gen_op_load_fpr_FT0(rd);
! 1937: gen_op_load_fpr_FT1(rs2);
! 1938: flush_T2(dc);
! 1939: gen_fcond[3][cond]();
! 1940: gen_op_fmovs_cc();
! 1941: gen_op_store_FT0_fpr(rd);
! 1942: break;
! 1943: case 0x0c2: /* V9 fmovdcc %fcc3 */
! 1944: cond = GET_FIELD_SP(insn, 14, 17);
! 1945: gen_op_load_fpr_DT0(DFPREG(rd));
! 1946: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1947: flush_T2(dc);
! 1948: gen_fcond[3][cond]();
! 1949: gen_op_fmovd_cc();
! 1950: gen_op_store_DT0_fpr(DFPREG(rd));
! 1951: break;
! 1952: case 0x0c3: /* V9 fmovqcc %fcc3 */
! 1953: #if defined(CONFIG_USER_ONLY)
! 1954: cond = GET_FIELD_SP(insn, 14, 17);
! 1955: gen_op_load_fpr_QT0(QFPREG(rd));
! 1956: gen_op_load_fpr_QT1(QFPREG(rs2));
! 1957: flush_T2(dc);
! 1958: gen_fcond[3][cond]();
! 1959: gen_op_fmovq_cc();
! 1960: gen_op_store_QT0_fpr(QFPREG(rd));
! 1961: break;
! 1962: #else
! 1963: goto nfpu_insn;
! 1964: #endif
! 1965: case 0x101: /* V9 fmovscc %icc */
! 1966: cond = GET_FIELD_SP(insn, 14, 17);
! 1967: gen_op_load_fpr_FT0(rd);
! 1968: gen_op_load_fpr_FT1(rs2);
! 1969: flush_T2(dc);
! 1970: gen_cond[0][cond]();
! 1971: gen_op_fmovs_cc();
! 1972: gen_op_store_FT0_fpr(rd);
! 1973: break;
! 1974: case 0x102: /* V9 fmovdcc %icc */
! 1975: cond = GET_FIELD_SP(insn, 14, 17);
! 1976: gen_op_load_fpr_DT0(DFPREG(rd));
! 1977: gen_op_load_fpr_DT1(DFPREG(rs2));
! 1978: flush_T2(dc);
! 1979: gen_cond[0][cond]();
! 1980: gen_op_fmovd_cc();
! 1981: gen_op_store_DT0_fpr(DFPREG(rd));
! 1982: break;
! 1983: case 0x103: /* V9 fmovqcc %icc */
! 1984: #if defined(CONFIG_USER_ONLY)
! 1985: cond = GET_FIELD_SP(insn, 14, 17);
! 1986: gen_op_load_fpr_QT0(rd);
! 1987: gen_op_load_fpr_QT1(rs2);
! 1988: flush_T2(dc);
! 1989: gen_cond[0][cond]();
! 1990: gen_op_fmovq_cc();
! 1991: gen_op_store_QT0_fpr(rd);
! 1992: break;
! 1993: #else
! 1994: goto nfpu_insn;
! 1995: #endif
! 1996: case 0x181: /* V9 fmovscc %xcc */
! 1997: cond = GET_FIELD_SP(insn, 14, 17);
! 1998: gen_op_load_fpr_FT0(rd);
! 1999: gen_op_load_fpr_FT1(rs2);
! 2000: flush_T2(dc);
! 2001: gen_cond[1][cond]();
! 2002: gen_op_fmovs_cc();
! 2003: gen_op_store_FT0_fpr(rd);
! 2004: break;
! 2005: case 0x182: /* V9 fmovdcc %xcc */
! 2006: cond = GET_FIELD_SP(insn, 14, 17);
! 2007: gen_op_load_fpr_DT0(DFPREG(rd));
! 2008: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2009: flush_T2(dc);
! 2010: gen_cond[1][cond]();
! 2011: gen_op_fmovd_cc();
! 2012: gen_op_store_DT0_fpr(DFPREG(rd));
! 2013: break;
! 2014: case 0x183: /* V9 fmovqcc %xcc */
! 2015: #if defined(CONFIG_USER_ONLY)
! 2016: cond = GET_FIELD_SP(insn, 14, 17);
! 2017: gen_op_load_fpr_QT0(rd);
! 2018: gen_op_load_fpr_QT1(rs2);
! 2019: flush_T2(dc);
! 2020: gen_cond[1][cond]();
! 2021: gen_op_fmovq_cc();
! 2022: gen_op_store_QT0_fpr(rd);
! 2023: break;
! 2024: #else
! 2025: goto nfpu_insn;
! 2026: #endif
! 2027: #endif
! 2028: case 0x51: /* fcmps, V9 %fcc */
! 2029: gen_op_load_fpr_FT0(rs1);
! 2030: gen_op_load_fpr_FT1(rs2);
! 2031: #ifdef TARGET_SPARC64
! 2032: gen_fcmps[rd & 3]();
! 2033: #else
! 2034: gen_op_fcmps();
! 2035: #endif
! 2036: break;
! 2037: case 0x52: /* fcmpd, V9 %fcc */
! 2038: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2039: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2040: #ifdef TARGET_SPARC64
! 2041: gen_fcmpd[rd & 3]();
! 2042: #else
! 2043: gen_op_fcmpd();
! 2044: #endif
! 2045: break;
! 2046: case 0x53: /* fcmpq, V9 %fcc */
! 2047: #if defined(CONFIG_USER_ONLY)
! 2048: gen_op_load_fpr_QT0(QFPREG(rs1));
! 2049: gen_op_load_fpr_QT1(QFPREG(rs2));
! 2050: #ifdef TARGET_SPARC64
! 2051: gen_fcmpq[rd & 3]();
! 2052: #else
! 2053: gen_op_fcmpq();
! 2054: #endif
! 2055: break;
! 2056: #else /* !defined(CONFIG_USER_ONLY) */
! 2057: goto nfpu_insn;
! 2058: #endif
! 2059: case 0x55: /* fcmpes, V9 %fcc */
! 2060: gen_op_load_fpr_FT0(rs1);
! 2061: gen_op_load_fpr_FT1(rs2);
! 2062: #ifdef TARGET_SPARC64
! 2063: gen_fcmpes[rd & 3]();
! 2064: #else
! 2065: gen_op_fcmpes();
! 2066: #endif
! 2067: break;
! 2068: case 0x56: /* fcmped, V9 %fcc */
! 2069: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2070: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2071: #ifdef TARGET_SPARC64
! 2072: gen_fcmped[rd & 3]();
! 2073: #else
! 2074: gen_op_fcmped();
! 2075: #endif
! 2076: break;
! 2077: case 0x57: /* fcmpeq, V9 %fcc */
! 2078: #if defined(CONFIG_USER_ONLY)
! 2079: gen_op_load_fpr_QT0(QFPREG(rs1));
! 2080: gen_op_load_fpr_QT1(QFPREG(rs2));
! 2081: #ifdef TARGET_SPARC64
! 2082: gen_fcmpeq[rd & 3]();
! 2083: #else
! 2084: gen_op_fcmpeq();
! 2085: #endif
! 2086: break;
! 2087: #else/* !defined(CONFIG_USER_ONLY) */
! 2088: goto nfpu_insn;
! 2089: #endif
! 2090: default:
! 2091: goto illegal_insn;
! 2092: }
! 2093: #if defined(OPTIM)
! 2094: } else if (xop == 0x2) {
! 2095: // clr/mov shortcut
! 2096:
! 2097: rs1 = GET_FIELD(insn, 13, 17);
! 2098: if (rs1 == 0) {
! 2099: // or %g0, x, y -> mov T1, x; mov y, T1
! 2100: if (IS_IMM) { /* immediate */
! 2101: rs2 = GET_FIELDs(insn, 19, 31);
! 2102: gen_movl_simm_T1(rs2);
! 2103: } else { /* register */
! 2104: rs2 = GET_FIELD(insn, 27, 31);
! 2105: gen_movl_reg_T1(rs2);
! 2106: }
! 2107: gen_movl_T1_reg(rd);
! 2108: } else {
! 2109: gen_movl_reg_T0(rs1);
! 2110: if (IS_IMM) { /* immediate */
! 2111: // or x, #0, y -> mov T1, x; mov y, T1
! 2112: rs2 = GET_FIELDs(insn, 19, 31);
! 2113: if (rs2 != 0) {
! 2114: gen_movl_simm_T1(rs2);
! 2115: gen_op_or_T1_T0();
! 2116: }
! 2117: } else { /* register */
! 2118: // or x, %g0, y -> mov T1, x; mov y, T1
! 2119: rs2 = GET_FIELD(insn, 27, 31);
! 2120: if (rs2 != 0) {
! 2121: gen_movl_reg_T1(rs2);
! 2122: gen_op_or_T1_T0();
! 2123: }
! 2124: }
! 2125: gen_movl_T0_reg(rd);
! 2126: }
! 2127: #endif
! 2128: #ifdef TARGET_SPARC64
! 2129: } else if (xop == 0x25) { /* sll, V9 sllx */
! 2130: rs1 = GET_FIELD(insn, 13, 17);
! 2131: gen_movl_reg_T0(rs1);
! 2132: if (IS_IMM) { /* immediate */
! 2133: rs2 = GET_FIELDs(insn, 20, 31);
! 2134: gen_movl_simm_T1(rs2);
! 2135: } else { /* register */
! 2136: rs2 = GET_FIELD(insn, 27, 31);
! 2137: gen_movl_reg_T1(rs2);
! 2138: }
! 2139: if (insn & (1 << 12))
! 2140: gen_op_sllx();
! 2141: else
! 2142: gen_op_sll();
! 2143: gen_movl_T0_reg(rd);
! 2144: } else if (xop == 0x26) { /* srl, V9 srlx */
! 2145: rs1 = GET_FIELD(insn, 13, 17);
! 2146: gen_movl_reg_T0(rs1);
! 2147: if (IS_IMM) { /* immediate */
! 2148: rs2 = GET_FIELDs(insn, 20, 31);
1.1 root 2149: gen_movl_simm_T1(rs2);
1.1.1.5 ! root 2150: } else { /* register */
1.1 root 2151: rs2 = GET_FIELD(insn, 27, 31);
2152: gen_movl_reg_T1(rs2);
2153: }
1.1.1.5 ! root 2154: if (insn & (1 << 12))
! 2155: gen_op_srlx();
! 2156: else
! 2157: gen_op_srl();
! 2158: gen_movl_T0_reg(rd);
! 2159: } else if (xop == 0x27) { /* sra, V9 srax */
1.1 root 2160: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 2161: gen_movl_reg_T0(rs1);
! 2162: if (IS_IMM) { /* immediate */
1.1 root 2163: rs2 = GET_FIELDs(insn, 20, 31);
2164: gen_movl_simm_T1(rs2);
1.1.1.5 ! root 2165: } else { /* register */
1.1 root 2166: rs2 = GET_FIELD(insn, 27, 31);
2167: gen_movl_reg_T1(rs2);
2168: }
1.1.1.5 ! root 2169: if (insn & (1 << 12))
! 2170: gen_op_srax();
! 2171: else
! 2172: gen_op_sra();
! 2173: gen_movl_T0_reg(rd);
1.1 root 2174: #endif
1.1.1.5 ! root 2175: } else if (xop < 0x36) {
1.1 root 2176: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 2177: gen_movl_reg_T0(rs1);
! 2178: if (IS_IMM) { /* immediate */
1.1 root 2179: rs2 = GET_FIELDs(insn, 19, 31);
2180: gen_movl_simm_T1(rs2);
1.1.1.5 ! root 2181: } else { /* register */
1.1 root 2182: rs2 = GET_FIELD(insn, 27, 31);
2183: gen_movl_reg_T1(rs2);
2184: }
2185: if (xop < 0x20) {
2186: switch (xop & ~0x10) {
2187: case 0x0:
2188: if (xop & 0x10)
2189: gen_op_add_T1_T0_cc();
2190: else
2191: gen_op_add_T1_T0();
2192: break;
2193: case 0x1:
2194: gen_op_and_T1_T0();
2195: if (xop & 0x10)
2196: gen_op_logic_T0_cc();
2197: break;
2198: case 0x2:
1.1.1.5 ! root 2199: gen_op_or_T1_T0();
! 2200: if (xop & 0x10)
! 2201: gen_op_logic_T0_cc();
! 2202: break;
1.1 root 2203: case 0x3:
2204: gen_op_xor_T1_T0();
2205: if (xop & 0x10)
2206: gen_op_logic_T0_cc();
2207: break;
2208: case 0x4:
2209: if (xop & 0x10)
2210: gen_op_sub_T1_T0_cc();
2211: else
2212: gen_op_sub_T1_T0();
2213: break;
2214: case 0x5:
2215: gen_op_andn_T1_T0();
2216: if (xop & 0x10)
2217: gen_op_logic_T0_cc();
2218: break;
2219: case 0x6:
2220: gen_op_orn_T1_T0();
2221: if (xop & 0x10)
2222: gen_op_logic_T0_cc();
2223: break;
2224: case 0x7:
2225: gen_op_xnor_T1_T0();
2226: if (xop & 0x10)
2227: gen_op_logic_T0_cc();
2228: break;
2229: case 0x8:
2230: if (xop & 0x10)
2231: gen_op_addx_T1_T0_cc();
2232: else
2233: gen_op_addx_T1_T0();
2234: break;
1.1.1.3 root 2235: #ifdef TARGET_SPARC64
1.1.1.5 ! root 2236: case 0x9: /* V9 mulx */
1.1.1.3 root 2237: gen_op_mulx_T1_T0();
2238: break;
2239: #endif
1.1 root 2240: case 0xa:
2241: gen_op_umul_T1_T0();
2242: if (xop & 0x10)
2243: gen_op_logic_T0_cc();
2244: break;
2245: case 0xb:
2246: gen_op_smul_T1_T0();
2247: if (xop & 0x10)
2248: gen_op_logic_T0_cc();
2249: break;
2250: case 0xc:
2251: if (xop & 0x10)
2252: gen_op_subx_T1_T0_cc();
2253: else
2254: gen_op_subx_T1_T0();
2255: break;
1.1.1.3 root 2256: #ifdef TARGET_SPARC64
1.1.1.5 ! root 2257: case 0xd: /* V9 udivx */
1.1.1.3 root 2258: gen_op_udivx_T1_T0();
2259: break;
2260: #endif
1.1 root 2261: case 0xe:
2262: gen_op_udiv_T1_T0();
2263: if (xop & 0x10)
2264: gen_op_div_cc();
2265: break;
2266: case 0xf:
2267: gen_op_sdiv_T1_T0();
2268: if (xop & 0x10)
2269: gen_op_div_cc();
2270: break;
2271: default:
2272: goto illegal_insn;
2273: }
1.1.1.5 ! root 2274: gen_movl_T0_reg(rd);
1.1 root 2275: } else {
2276: switch (xop) {
1.1.1.5 ! root 2277: case 0x20: /* taddcc */
! 2278: gen_op_tadd_T1_T0_cc();
! 2279: gen_movl_T0_reg(rd);
! 2280: break;
! 2281: case 0x21: /* tsubcc */
! 2282: gen_op_tsub_T1_T0_cc();
! 2283: gen_movl_T0_reg(rd);
! 2284: break;
! 2285: case 0x22: /* taddcctv */
! 2286: save_state(dc);
! 2287: gen_op_tadd_T1_T0_ccTV();
! 2288: gen_movl_T0_reg(rd);
! 2289: break;
! 2290: case 0x23: /* tsubcctv */
! 2291: save_state(dc);
! 2292: gen_op_tsub_T1_T0_ccTV();
! 2293: gen_movl_T0_reg(rd);
! 2294: break;
1.1 root 2295: case 0x24: /* mulscc */
2296: gen_op_mulscc_T1_T0();
2297: gen_movl_T0_reg(rd);
2298: break;
2299: #ifndef TARGET_SPARC64
1.1.1.5 ! root 2300: case 0x25: /* sll */
! 2301: gen_op_sll();
1.1 root 2302: gen_movl_T0_reg(rd);
2303: break;
2304: case 0x26: /* srl */
1.1.1.5 ! root 2305: gen_op_srl();
1.1 root 2306: gen_movl_T0_reg(rd);
2307: break;
2308: case 0x27: /* sra */
1.1.1.5 ! root 2309: gen_op_sra();
1.1 root 2310: gen_movl_T0_reg(rd);
2311: break;
2312: #endif
2313: case 0x30:
2314: {
2315: switch(rd) {
2316: case 0: /* wry */
1.1.1.5 ! root 2317: gen_op_xor_T1_T0();
! 2318: gen_op_movtl_env_T0(offsetof(CPUSPARCState, y));
1.1 root 2319: break;
1.1.1.5 ! root 2320: #ifndef TARGET_SPARC64
! 2321: case 0x01 ... 0x0f: /* undefined in the
! 2322: SPARCv8 manual, nop
! 2323: on the microSPARC
! 2324: II */
! 2325: case 0x10 ... 0x1f: /* implementation-dependent
! 2326: in the SPARCv8
! 2327: manual, nop on the
! 2328: microSPARC II */
! 2329: break;
! 2330: #else
! 2331: case 0x2: /* V9 wrccr */
! 2332: gen_op_xor_T1_T0();
1.1 root 2333: gen_op_wrccr();
1.1.1.5 ! root 2334: break;
! 2335: case 0x3: /* V9 wrasi */
! 2336: gen_op_xor_T1_T0();
! 2337: gen_op_movl_env_T0(offsetof(CPUSPARCState, asi));
! 2338: break;
! 2339: case 0x6: /* V9 wrfprs */
! 2340: gen_op_xor_T1_T0();
! 2341: gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
! 2342: save_state(dc);
! 2343: gen_op_next_insn();
! 2344: gen_op_movl_T0_0();
! 2345: gen_op_exit_tb();
! 2346: dc->is_br = 1;
! 2347: break;
! 2348: case 0xf: /* V9 sir, nop if user */
1.1 root 2349: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 2350: if (supervisor(dc))
! 2351: gen_op_sir();
1.1 root 2352: #endif
1.1.1.5 ! root 2353: break;
! 2354: case 0x13: /* Graphics Status */
1.1.1.3 root 2355: if (gen_trap_ifnofpu(dc))
2356: goto jmp_insn;
1.1.1.5 ! root 2357: gen_op_xor_T1_T0();
! 2358: gen_op_movtl_env_T0(offsetof(CPUSPARCState, gsr));
! 2359: break;
! 2360: case 0x17: /* Tick compare */
1.1 root 2361: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 2362: if (!supervisor(dc))
! 2363: goto illegal_insn;
1.1 root 2364: #endif
1.1.1.5 ! root 2365: gen_op_xor_T1_T0();
! 2366: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr));
! 2367: gen_op_wrtick_cmpr();
! 2368: break;
! 2369: case 0x18: /* System tick */
1.1 root 2370: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 2371: if (!supervisor(dc))
! 2372: goto illegal_insn;
1.1 root 2373: #endif
1.1.1.5 ! root 2374: gen_op_xor_T1_T0();
! 2375: gen_op_wrstick();
! 2376: break;
! 2377: case 0x19: /* System tick compare */
1.1 root 2378: #if !defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 2379: if (!supervisor(dc))
! 2380: goto illegal_insn;
1.1 root 2381: #endif
1.1.1.5 ! root 2382: gen_op_xor_T1_T0();
! 2383: gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr));
! 2384: gen_op_wrstick_cmpr();
! 2385: break;
1.1 root 2386:
1.1.1.5 ! root 2387: case 0x10: /* Performance Control */
! 2388: case 0x11: /* Performance Instrumentation Counter */
! 2389: case 0x12: /* Dispatch Control */
! 2390: case 0x14: /* Softint set */
! 2391: case 0x15: /* Softint clear */
! 2392: case 0x16: /* Softint write */
1.1 root 2393: #endif
2394: default:
2395: goto illegal_insn;
2396: }
2397: }
2398: break;
2399: #if !defined(CONFIG_USER_ONLY)
2400: case 0x31: /* wrpsr, V9 saved, restored */
2401: {
1.1.1.5 ! root 2402: if (!supervisor(dc))
! 2403: goto priv_insn;
1.1 root 2404: #ifdef TARGET_SPARC64
1.1.1.5 ! root 2405: switch (rd) {
! 2406: case 0:
! 2407: gen_op_saved();
! 2408: break;
! 2409: case 1:
! 2410: gen_op_restored();
! 2411: break;
! 2412: case 2: /* UA2005 allclean */
! 2413: case 3: /* UA2005 otherw */
! 2414: case 4: /* UA2005 normalw */
! 2415: case 5: /* UA2005 invalw */
! 2416: // XXX
! 2417: default:
1.1 root 2418: goto illegal_insn;
2419: }
2420: #else
2421: gen_op_xor_T1_T0();
2422: gen_op_wrpsr();
1.1.1.2 root 2423: save_state(dc);
2424: gen_op_next_insn();
1.1.1.5 ! root 2425: gen_op_movl_T0_0();
! 2426: gen_op_exit_tb();
! 2427: dc->is_br = 1;
1.1 root 2428: #endif
2429: }
2430: break;
2431: case 0x32: /* wrwim, V9 wrpr */
2432: {
1.1.1.5 ! root 2433: if (!supervisor(dc))
! 2434: goto priv_insn;
1.1 root 2435: gen_op_xor_T1_T0();
2436: #ifdef TARGET_SPARC64
1.1.1.5 ! root 2437: switch (rd) {
! 2438: case 0: // tpc
! 2439: gen_op_wrtpc();
! 2440: break;
! 2441: case 1: // tnpc
! 2442: gen_op_wrtnpc();
! 2443: break;
! 2444: case 2: // tstate
! 2445: gen_op_wrtstate();
! 2446: break;
! 2447: case 3: // tt
! 2448: gen_op_wrtt();
! 2449: break;
! 2450: case 4: // tick
! 2451: gen_op_wrtick();
! 2452: break;
! 2453: case 5: // tba
! 2454: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
! 2455: break;
! 2456: case 6: // pstate
! 2457: gen_op_wrpstate();
1.1.1.3 root 2458: save_state(dc);
2459: gen_op_next_insn();
2460: gen_op_movl_T0_0();
2461: gen_op_exit_tb();
2462: dc->is_br = 1;
1.1.1.5 ! root 2463: break;
! 2464: case 7: // tl
! 2465: gen_op_movl_env_T0(offsetof(CPUSPARCState, tl));
! 2466: break;
! 2467: case 8: // pil
! 2468: gen_op_movl_env_T0(offsetof(CPUSPARCState, psrpil));
! 2469: break;
! 2470: case 9: // cwp
! 2471: gen_op_wrcwp();
! 2472: break;
! 2473: case 10: // cansave
! 2474: gen_op_movl_env_T0(offsetof(CPUSPARCState, cansave));
! 2475: break;
! 2476: case 11: // canrestore
! 2477: gen_op_movl_env_T0(offsetof(CPUSPARCState, canrestore));
! 2478: break;
! 2479: case 12: // cleanwin
! 2480: gen_op_movl_env_T0(offsetof(CPUSPARCState, cleanwin));
! 2481: break;
! 2482: case 13: // otherwin
! 2483: gen_op_movl_env_T0(offsetof(CPUSPARCState, otherwin));
! 2484: break;
! 2485: case 14: // wstate
! 2486: gen_op_movl_env_T0(offsetof(CPUSPARCState, wstate));
! 2487: break;
! 2488: case 16: // UA2005 gl
! 2489: gen_op_movl_env_T0(offsetof(CPUSPARCState, gl));
! 2490: break;
! 2491: case 26: // UA2005 strand status
! 2492: if (!hypervisor(dc))
! 2493: goto priv_insn;
! 2494: gen_op_movl_env_T0(offsetof(CPUSPARCState, ssr));
! 2495: break;
! 2496: default:
! 2497: goto illegal_insn;
! 2498: }
1.1 root 2499: #else
1.1.1.5 ! root 2500: gen_op_wrwim();
1.1 root 2501: #endif
2502: }
2503: break;
1.1.1.5 ! root 2504: case 0x33: /* wrtbr, UA2005 wrhpr */
1.1 root 2505: {
1.1.1.5 ! root 2506: #ifndef TARGET_SPARC64
! 2507: if (!supervisor(dc))
! 2508: goto priv_insn;
! 2509: gen_op_xor_T1_T0();
! 2510: gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr));
! 2511: #else
! 2512: if (!hypervisor(dc))
! 2513: goto priv_insn;
1.1 root 2514: gen_op_xor_T1_T0();
1.1.1.5 ! root 2515: switch (rd) {
! 2516: case 0: // hpstate
! 2517: // XXX gen_op_wrhpstate();
! 2518: save_state(dc);
! 2519: gen_op_next_insn();
! 2520: gen_op_movl_T0_0();
! 2521: gen_op_exit_tb();
! 2522: dc->is_br = 1;
! 2523: break;
! 2524: case 1: // htstate
! 2525: // XXX gen_op_wrhtstate();
! 2526: break;
! 2527: case 3: // hintp
! 2528: gen_op_movl_env_T0(offsetof(CPUSPARCState, hintp));
! 2529: break;
! 2530: case 5: // htba
! 2531: gen_op_movl_env_T0(offsetof(CPUSPARCState, htba));
! 2532: break;
! 2533: case 31: // hstick_cmpr
! 2534: gen_op_movtl_env_T0(offsetof(CPUSPARCState, hstick_cmpr));
! 2535: gen_op_wrhstick_cmpr();
! 2536: break;
! 2537: case 6: // hver readonly
! 2538: default:
! 2539: goto illegal_insn;
! 2540: }
! 2541: #endif
1.1 root 2542: }
2543: break;
2544: #endif
2545: #ifdef TARGET_SPARC64
1.1.1.5 ! root 2546: case 0x2c: /* V9 movcc */
! 2547: {
! 2548: int cc = GET_FIELD_SP(insn, 11, 12);
! 2549: int cond = GET_FIELD_SP(insn, 14, 17);
! 2550: if (IS_IMM) { /* immediate */
! 2551: rs2 = GET_FIELD_SPs(insn, 0, 10);
! 2552: gen_movl_simm_T1(rs2);
! 2553: }
! 2554: else {
! 2555: rs2 = GET_FIELD_SP(insn, 0, 4);
! 2556: gen_movl_reg_T1(rs2);
! 2557: }
! 2558: gen_movl_reg_T0(rd);
! 2559: flush_T2(dc);
! 2560: if (insn & (1 << 18)) {
! 2561: if (cc == 0)
! 2562: gen_cond[0][cond]();
! 2563: else if (cc == 2)
! 2564: gen_cond[1][cond]();
! 2565: else
! 2566: goto illegal_insn;
! 2567: } else {
! 2568: gen_fcond[cc][cond]();
! 2569: }
! 2570: gen_op_mov_cc();
! 2571: gen_movl_T0_reg(rd);
! 2572: break;
! 2573: }
! 2574: case 0x2d: /* V9 sdivx */
1.1 root 2575: gen_op_sdivx_T1_T0();
1.1.1.5 ! root 2576: gen_movl_T0_reg(rd);
1.1 root 2577: break;
1.1.1.5 ! root 2578: case 0x2e: /* V9 popc */
! 2579: {
! 2580: if (IS_IMM) { /* immediate */
! 2581: rs2 = GET_FIELD_SPs(insn, 0, 12);
! 2582: gen_movl_simm_T1(rs2);
! 2583: // XXX optimize: popc(constant)
! 2584: }
! 2585: else {
! 2586: rs2 = GET_FIELD_SP(insn, 0, 4);
! 2587: gen_movl_reg_T1(rs2);
! 2588: }
! 2589: gen_op_popc();
! 2590: gen_movl_T0_reg(rd);
! 2591: }
! 2592: case 0x2f: /* V9 movr */
! 2593: {
! 2594: int cond = GET_FIELD_SP(insn, 10, 12);
1.1.1.3 root 2595: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 2596: flush_T2(dc);
! 2597: gen_movl_reg_T0(rs1);
! 2598: gen_cond_reg(cond);
! 2599: if (IS_IMM) { /* immediate */
! 2600: rs2 = GET_FIELD_SPs(insn, 0, 9);
! 2601: gen_movl_simm_T1(rs2);
! 2602: }
! 2603: else {
! 2604: rs2 = GET_FIELD_SP(insn, 0, 4);
1.1.1.3 root 2605: gen_movl_reg_T1(rs2);
2606: }
1.1.1.5 ! root 2607: gen_movl_reg_T0(rd);
! 2608: gen_op_mov_cc();
! 2609: gen_movl_T0_reg(rd);
1.1.1.3 root 2610: break;
1.1.1.5 ! root 2611: }
! 2612: #endif
! 2613: default:
! 2614: goto illegal_insn;
! 2615: }
! 2616: }
! 2617: } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */
! 2618: #ifdef TARGET_SPARC64
! 2619: int opf = GET_FIELD_SP(insn, 5, 13);
! 2620: rs1 = GET_FIELD(insn, 13, 17);
! 2621: rs2 = GET_FIELD(insn, 27, 31);
! 2622: if (gen_trap_ifnofpu(dc))
! 2623: goto jmp_insn;
! 2624:
! 2625: switch (opf) {
! 2626: case 0x000: /* VIS I edge8cc */
! 2627: case 0x001: /* VIS II edge8n */
! 2628: case 0x002: /* VIS I edge8lcc */
! 2629: case 0x003: /* VIS II edge8ln */
! 2630: case 0x004: /* VIS I edge16cc */
! 2631: case 0x005: /* VIS II edge16n */
! 2632: case 0x006: /* VIS I edge16lcc */
! 2633: case 0x007: /* VIS II edge16ln */
! 2634: case 0x008: /* VIS I edge32cc */
! 2635: case 0x009: /* VIS II edge32n */
! 2636: case 0x00a: /* VIS I edge32lcc */
! 2637: case 0x00b: /* VIS II edge32ln */
! 2638: // XXX
! 2639: goto illegal_insn;
! 2640: case 0x010: /* VIS I array8 */
! 2641: gen_movl_reg_T0(rs1);
! 2642: gen_movl_reg_T1(rs2);
! 2643: gen_op_array8();
! 2644: gen_movl_T0_reg(rd);
! 2645: break;
! 2646: case 0x012: /* VIS I array16 */
! 2647: gen_movl_reg_T0(rs1);
! 2648: gen_movl_reg_T1(rs2);
! 2649: gen_op_array16();
! 2650: gen_movl_T0_reg(rd);
! 2651: break;
! 2652: case 0x014: /* VIS I array32 */
! 2653: gen_movl_reg_T0(rs1);
! 2654: gen_movl_reg_T1(rs2);
! 2655: gen_op_array32();
! 2656: gen_movl_T0_reg(rd);
! 2657: break;
! 2658: case 0x018: /* VIS I alignaddr */
! 2659: gen_movl_reg_T0(rs1);
! 2660: gen_movl_reg_T1(rs2);
! 2661: gen_op_alignaddr();
! 2662: gen_movl_T0_reg(rd);
! 2663: break;
! 2664: case 0x019: /* VIS II bmask */
! 2665: case 0x01a: /* VIS I alignaddrl */
! 2666: // XXX
! 2667: goto illegal_insn;
! 2668: case 0x020: /* VIS I fcmple16 */
! 2669: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2670: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2671: gen_op_fcmple16();
! 2672: gen_op_store_DT0_fpr(DFPREG(rd));
! 2673: break;
! 2674: case 0x022: /* VIS I fcmpne16 */
! 2675: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2676: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2677: gen_op_fcmpne16();
! 2678: gen_op_store_DT0_fpr(DFPREG(rd));
! 2679: break;
! 2680: case 0x024: /* VIS I fcmple32 */
! 2681: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2682: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2683: gen_op_fcmple32();
! 2684: gen_op_store_DT0_fpr(DFPREG(rd));
! 2685: break;
! 2686: case 0x026: /* VIS I fcmpne32 */
! 2687: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2688: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2689: gen_op_fcmpne32();
! 2690: gen_op_store_DT0_fpr(DFPREG(rd));
! 2691: break;
! 2692: case 0x028: /* VIS I fcmpgt16 */
! 2693: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2694: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2695: gen_op_fcmpgt16();
! 2696: gen_op_store_DT0_fpr(DFPREG(rd));
! 2697: break;
! 2698: case 0x02a: /* VIS I fcmpeq16 */
! 2699: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2700: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2701: gen_op_fcmpeq16();
! 2702: gen_op_store_DT0_fpr(DFPREG(rd));
! 2703: break;
! 2704: case 0x02c: /* VIS I fcmpgt32 */
! 2705: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2706: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2707: gen_op_fcmpgt32();
! 2708: gen_op_store_DT0_fpr(DFPREG(rd));
! 2709: break;
! 2710: case 0x02e: /* VIS I fcmpeq32 */
! 2711: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2712: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2713: gen_op_fcmpeq32();
! 2714: gen_op_store_DT0_fpr(DFPREG(rd));
! 2715: break;
! 2716: case 0x031: /* VIS I fmul8x16 */
! 2717: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2718: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2719: gen_op_fmul8x16();
! 2720: gen_op_store_DT0_fpr(DFPREG(rd));
! 2721: break;
! 2722: case 0x033: /* VIS I fmul8x16au */
! 2723: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2724: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2725: gen_op_fmul8x16au();
! 2726: gen_op_store_DT0_fpr(DFPREG(rd));
! 2727: break;
! 2728: case 0x035: /* VIS I fmul8x16al */
! 2729: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2730: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2731: gen_op_fmul8x16al();
! 2732: gen_op_store_DT0_fpr(DFPREG(rd));
! 2733: break;
! 2734: case 0x036: /* VIS I fmul8sux16 */
! 2735: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2736: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2737: gen_op_fmul8sux16();
! 2738: gen_op_store_DT0_fpr(DFPREG(rd));
! 2739: break;
! 2740: case 0x037: /* VIS I fmul8ulx16 */
! 2741: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2742: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2743: gen_op_fmul8ulx16();
! 2744: gen_op_store_DT0_fpr(DFPREG(rd));
! 2745: break;
! 2746: case 0x038: /* VIS I fmuld8sux16 */
! 2747: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2748: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2749: gen_op_fmuld8sux16();
! 2750: gen_op_store_DT0_fpr(DFPREG(rd));
! 2751: break;
! 2752: case 0x039: /* VIS I fmuld8ulx16 */
! 2753: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2754: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2755: gen_op_fmuld8ulx16();
! 2756: gen_op_store_DT0_fpr(DFPREG(rd));
! 2757: break;
! 2758: case 0x03a: /* VIS I fpack32 */
! 2759: case 0x03b: /* VIS I fpack16 */
! 2760: case 0x03d: /* VIS I fpackfix */
! 2761: case 0x03e: /* VIS I pdist */
! 2762: // XXX
! 2763: goto illegal_insn;
! 2764: case 0x048: /* VIS I faligndata */
! 2765: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2766: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2767: gen_op_faligndata();
! 2768: gen_op_store_DT0_fpr(DFPREG(rd));
! 2769: break;
! 2770: case 0x04b: /* VIS I fpmerge */
! 2771: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2772: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2773: gen_op_fpmerge();
! 2774: gen_op_store_DT0_fpr(DFPREG(rd));
! 2775: break;
! 2776: case 0x04c: /* VIS II bshuffle */
! 2777: // XXX
! 2778: goto illegal_insn;
! 2779: case 0x04d: /* VIS I fexpand */
! 2780: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2781: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2782: gen_op_fexpand();
! 2783: gen_op_store_DT0_fpr(DFPREG(rd));
! 2784: break;
! 2785: case 0x050: /* VIS I fpadd16 */
! 2786: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2787: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2788: gen_op_fpadd16();
! 2789: gen_op_store_DT0_fpr(DFPREG(rd));
! 2790: break;
! 2791: case 0x051: /* VIS I fpadd16s */
! 2792: gen_op_load_fpr_FT0(rs1);
! 2793: gen_op_load_fpr_FT1(rs2);
! 2794: gen_op_fpadd16s();
! 2795: gen_op_store_FT0_fpr(rd);
! 2796: break;
! 2797: case 0x052: /* VIS I fpadd32 */
! 2798: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2799: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2800: gen_op_fpadd32();
! 2801: gen_op_store_DT0_fpr(DFPREG(rd));
! 2802: break;
! 2803: case 0x053: /* VIS I fpadd32s */
! 2804: gen_op_load_fpr_FT0(rs1);
! 2805: gen_op_load_fpr_FT1(rs2);
! 2806: gen_op_fpadd32s();
! 2807: gen_op_store_FT0_fpr(rd);
! 2808: break;
! 2809: case 0x054: /* VIS I fpsub16 */
! 2810: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2811: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2812: gen_op_fpsub16();
! 2813: gen_op_store_DT0_fpr(DFPREG(rd));
! 2814: break;
! 2815: case 0x055: /* VIS I fpsub16s */
! 2816: gen_op_load_fpr_FT0(rs1);
! 2817: gen_op_load_fpr_FT1(rs2);
! 2818: gen_op_fpsub16s();
! 2819: gen_op_store_FT0_fpr(rd);
! 2820: break;
! 2821: case 0x056: /* VIS I fpsub32 */
! 2822: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2823: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2824: gen_op_fpadd32();
! 2825: gen_op_store_DT0_fpr(DFPREG(rd));
! 2826: break;
! 2827: case 0x057: /* VIS I fpsub32s */
! 2828: gen_op_load_fpr_FT0(rs1);
! 2829: gen_op_load_fpr_FT1(rs2);
! 2830: gen_op_fpsub32s();
! 2831: gen_op_store_FT0_fpr(rd);
! 2832: break;
! 2833: case 0x060: /* VIS I fzero */
! 2834: gen_op_movl_DT0_0();
! 2835: gen_op_store_DT0_fpr(DFPREG(rd));
! 2836: break;
! 2837: case 0x061: /* VIS I fzeros */
! 2838: gen_op_movl_FT0_0();
! 2839: gen_op_store_FT0_fpr(rd);
! 2840: break;
! 2841: case 0x062: /* VIS I fnor */
! 2842: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2843: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2844: gen_op_fnor();
! 2845: gen_op_store_DT0_fpr(DFPREG(rd));
! 2846: break;
! 2847: case 0x063: /* VIS I fnors */
! 2848: gen_op_load_fpr_FT0(rs1);
! 2849: gen_op_load_fpr_FT1(rs2);
! 2850: gen_op_fnors();
! 2851: gen_op_store_FT0_fpr(rd);
! 2852: break;
! 2853: case 0x064: /* VIS I fandnot2 */
! 2854: gen_op_load_fpr_DT1(DFPREG(rs1));
! 2855: gen_op_load_fpr_DT0(DFPREG(rs2));
! 2856: gen_op_fandnot();
! 2857: gen_op_store_DT0_fpr(DFPREG(rd));
! 2858: break;
! 2859: case 0x065: /* VIS I fandnot2s */
! 2860: gen_op_load_fpr_FT1(rs1);
! 2861: gen_op_load_fpr_FT0(rs2);
! 2862: gen_op_fandnots();
! 2863: gen_op_store_FT0_fpr(rd);
! 2864: break;
! 2865: case 0x066: /* VIS I fnot2 */
! 2866: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2867: gen_op_fnot();
! 2868: gen_op_store_DT0_fpr(DFPREG(rd));
! 2869: break;
! 2870: case 0x067: /* VIS I fnot2s */
! 2871: gen_op_load_fpr_FT1(rs2);
! 2872: gen_op_fnot();
! 2873: gen_op_store_FT0_fpr(rd);
! 2874: break;
! 2875: case 0x068: /* VIS I fandnot1 */
! 2876: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2877: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2878: gen_op_fandnot();
! 2879: gen_op_store_DT0_fpr(DFPREG(rd));
! 2880: break;
! 2881: case 0x069: /* VIS I fandnot1s */
! 2882: gen_op_load_fpr_FT0(rs1);
! 2883: gen_op_load_fpr_FT1(rs2);
! 2884: gen_op_fandnots();
! 2885: gen_op_store_FT0_fpr(rd);
! 2886: break;
! 2887: case 0x06a: /* VIS I fnot1 */
! 2888: gen_op_load_fpr_DT1(DFPREG(rs1));
! 2889: gen_op_fnot();
! 2890: gen_op_store_DT0_fpr(DFPREG(rd));
! 2891: break;
! 2892: case 0x06b: /* VIS I fnot1s */
! 2893: gen_op_load_fpr_FT1(rs1);
! 2894: gen_op_fnot();
! 2895: gen_op_store_FT0_fpr(rd);
! 2896: break;
! 2897: case 0x06c: /* VIS I fxor */
! 2898: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2899: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2900: gen_op_fxor();
! 2901: gen_op_store_DT0_fpr(DFPREG(rd));
! 2902: break;
! 2903: case 0x06d: /* VIS I fxors */
! 2904: gen_op_load_fpr_FT0(rs1);
! 2905: gen_op_load_fpr_FT1(rs2);
! 2906: gen_op_fxors();
! 2907: gen_op_store_FT0_fpr(rd);
! 2908: break;
! 2909: case 0x06e: /* VIS I fnand */
! 2910: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2911: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2912: gen_op_fnand();
! 2913: gen_op_store_DT0_fpr(DFPREG(rd));
! 2914: break;
! 2915: case 0x06f: /* VIS I fnands */
! 2916: gen_op_load_fpr_FT0(rs1);
! 2917: gen_op_load_fpr_FT1(rs2);
! 2918: gen_op_fnands();
! 2919: gen_op_store_FT0_fpr(rd);
! 2920: break;
! 2921: case 0x070: /* VIS I fand */
! 2922: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2923: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2924: gen_op_fand();
! 2925: gen_op_store_DT0_fpr(DFPREG(rd));
! 2926: break;
! 2927: case 0x071: /* VIS I fands */
! 2928: gen_op_load_fpr_FT0(rs1);
! 2929: gen_op_load_fpr_FT1(rs2);
! 2930: gen_op_fands();
! 2931: gen_op_store_FT0_fpr(rd);
! 2932: break;
! 2933: case 0x072: /* VIS I fxnor */
! 2934: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2935: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2936: gen_op_fxnor();
! 2937: gen_op_store_DT0_fpr(DFPREG(rd));
! 2938: break;
! 2939: case 0x073: /* VIS I fxnors */
! 2940: gen_op_load_fpr_FT0(rs1);
! 2941: gen_op_load_fpr_FT1(rs2);
! 2942: gen_op_fxnors();
! 2943: gen_op_store_FT0_fpr(rd);
! 2944: break;
! 2945: case 0x074: /* VIS I fsrc1 */
! 2946: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2947: gen_op_store_DT0_fpr(DFPREG(rd));
! 2948: break;
! 2949: case 0x075: /* VIS I fsrc1s */
! 2950: gen_op_load_fpr_FT0(rs1);
! 2951: gen_op_store_FT0_fpr(rd);
! 2952: break;
! 2953: case 0x076: /* VIS I fornot2 */
! 2954: gen_op_load_fpr_DT1(DFPREG(rs1));
! 2955: gen_op_load_fpr_DT0(DFPREG(rs2));
! 2956: gen_op_fornot();
! 2957: gen_op_store_DT0_fpr(DFPREG(rd));
! 2958: break;
! 2959: case 0x077: /* VIS I fornot2s */
! 2960: gen_op_load_fpr_FT1(rs1);
! 2961: gen_op_load_fpr_FT0(rs2);
! 2962: gen_op_fornots();
! 2963: gen_op_store_FT0_fpr(rd);
! 2964: break;
! 2965: case 0x078: /* VIS I fsrc2 */
! 2966: gen_op_load_fpr_DT0(DFPREG(rs2));
! 2967: gen_op_store_DT0_fpr(DFPREG(rd));
! 2968: break;
! 2969: case 0x079: /* VIS I fsrc2s */
! 2970: gen_op_load_fpr_FT0(rs2);
! 2971: gen_op_store_FT0_fpr(rd);
! 2972: break;
! 2973: case 0x07a: /* VIS I fornot1 */
! 2974: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2975: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2976: gen_op_fornot();
! 2977: gen_op_store_DT0_fpr(DFPREG(rd));
! 2978: break;
! 2979: case 0x07b: /* VIS I fornot1s */
! 2980: gen_op_load_fpr_FT0(rs1);
! 2981: gen_op_load_fpr_FT1(rs2);
! 2982: gen_op_fornots();
! 2983: gen_op_store_FT0_fpr(rd);
! 2984: break;
! 2985: case 0x07c: /* VIS I for */
! 2986: gen_op_load_fpr_DT0(DFPREG(rs1));
! 2987: gen_op_load_fpr_DT1(DFPREG(rs2));
! 2988: gen_op_for();
! 2989: gen_op_store_DT0_fpr(DFPREG(rd));
! 2990: break;
! 2991: case 0x07d: /* VIS I fors */
! 2992: gen_op_load_fpr_FT0(rs1);
! 2993: gen_op_load_fpr_FT1(rs2);
! 2994: gen_op_fors();
! 2995: gen_op_store_FT0_fpr(rd);
! 2996: break;
! 2997: case 0x07e: /* VIS I fone */
! 2998: gen_op_movl_DT0_1();
! 2999: gen_op_store_DT0_fpr(DFPREG(rd));
! 3000: break;
! 3001: case 0x07f: /* VIS I fones */
! 3002: gen_op_movl_FT0_1();
! 3003: gen_op_store_FT0_fpr(rd);
! 3004: break;
! 3005: case 0x080: /* VIS I shutdown */
! 3006: case 0x081: /* VIS II siam */
! 3007: // XXX
! 3008: goto illegal_insn;
! 3009: default:
! 3010: goto illegal_insn;
! 3011: }
! 3012: #else
! 3013: goto ncp_insn;
! 3014: #endif
! 3015: } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */
! 3016: #ifdef TARGET_SPARC64
! 3017: goto illegal_insn;
! 3018: #else
! 3019: goto ncp_insn;
1.1 root 3020: #endif
3021: #ifdef TARGET_SPARC64
1.1.1.5 ! root 3022: } else if (xop == 0x39) { /* V9 return */
1.1 root 3023: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 3024: save_state(dc);
! 3025: gen_movl_reg_T0(rs1);
! 3026: if (IS_IMM) { /* immediate */
! 3027: rs2 = GET_FIELDs(insn, 19, 31);
1.1 root 3028: #if defined(OPTIM)
1.1.1.5 ! root 3029: if (rs2) {
1.1 root 3030: #endif
1.1.1.5 ! root 3031: gen_movl_simm_T1(rs2);
! 3032: gen_op_add_T1_T0();
1.1 root 3033: #if defined(OPTIM)
1.1.1.5 ! root 3034: }
1.1 root 3035: #endif
1.1.1.5 ! root 3036: } else { /* register */
1.1 root 3037: rs2 = GET_FIELD(insn, 27, 31);
3038: #if defined(OPTIM)
1.1.1.5 ! root 3039: if (rs2) {
1.1 root 3040: #endif
1.1.1.5 ! root 3041: gen_movl_reg_T1(rs2);
! 3042: gen_op_add_T1_T0();
1.1 root 3043: #if defined(OPTIM)
1.1.1.5 ! root 3044: }
1.1 root 3045: #endif
3046: }
1.1.1.5 ! root 3047: gen_op_restore();
! 3048: gen_mov_pc_npc(dc);
! 3049: gen_op_check_align_T0_3();
! 3050: gen_op_movl_npc_T0();
! 3051: dc->npc = DYNAMIC_PC;
! 3052: goto jmp_insn;
1.1 root 3053: #endif
1.1.1.5 ! root 3054: } else {
1.1 root 3055: rs1 = GET_FIELD(insn, 13, 17);
1.1.1.5 ! root 3056: gen_movl_reg_T0(rs1);
! 3057: if (IS_IMM) { /* immediate */
! 3058: rs2 = GET_FIELDs(insn, 19, 31);
1.1 root 3059: #if defined(OPTIM)
1.1.1.5 ! root 3060: if (rs2) {
1.1 root 3061: #endif
1.1.1.5 ! root 3062: gen_movl_simm_T1(rs2);
! 3063: gen_op_add_T1_T0();
1.1 root 3064: #if defined(OPTIM)
1.1.1.5 ! root 3065: }
1.1 root 3066: #endif
1.1.1.5 ! root 3067: } else { /* register */
1.1 root 3068: rs2 = GET_FIELD(insn, 27, 31);
3069: #if defined(OPTIM)
1.1.1.5 ! root 3070: if (rs2) {
1.1 root 3071: #endif
1.1.1.5 ! root 3072: gen_movl_reg_T1(rs2);
! 3073: gen_op_add_T1_T0();
1.1 root 3074: #if defined(OPTIM)
1.1.1.5 ! root 3075: }
1.1 root 3076: #endif
3077: }
1.1.1.5 ! root 3078: switch (xop) {
! 3079: case 0x38: /* jmpl */
! 3080: {
! 3081: if (rd != 0) {
1.1.1.3 root 3082: #ifdef TARGET_SPARC64
3083: if (dc->pc == (uint32_t)dc->pc) {
3084: gen_op_movl_T1_im(dc->pc);
3085: } else {
3086: gen_op_movq_T1_im64(dc->pc >> 32, dc->pc);
3087: }
3088: #else
1.1.1.5 ! root 3089: gen_op_movl_T1_im(dc->pc);
1.1.1.3 root 3090: #endif
1.1.1.5 ! root 3091: gen_movl_T1_reg(rd);
! 3092: }
1.1 root 3093: gen_mov_pc_npc(dc);
1.1.1.5 ! root 3094: gen_op_check_align_T0_3();
! 3095: gen_op_movl_npc_T0();
! 3096: dc->npc = DYNAMIC_PC;
! 3097: }
! 3098: goto jmp_insn;
1.1 root 3099: #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1.1.1.5 ! root 3100: case 0x39: /* rett, V9 return */
! 3101: {
! 3102: if (!supervisor(dc))
! 3103: goto priv_insn;
1.1 root 3104: gen_mov_pc_npc(dc);
1.1.1.5 ! root 3105: gen_op_check_align_T0_3();
! 3106: gen_op_movl_npc_T0();
! 3107: dc->npc = DYNAMIC_PC;
! 3108: gen_op_rett();
! 3109: }
! 3110: goto jmp_insn;
! 3111: #endif
! 3112: case 0x3b: /* flush */
! 3113: gen_op_flush_T0();
! 3114: break;
! 3115: case 0x3c: /* save */
! 3116: save_state(dc);
! 3117: gen_op_save();
! 3118: gen_movl_T0_reg(rd);
! 3119: break;
! 3120: case 0x3d: /* restore */
! 3121: save_state(dc);
! 3122: gen_op_restore();
! 3123: gen_movl_T0_reg(rd);
! 3124: break;
1.1 root 3125: #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
1.1.1.5 ! root 3126: case 0x3e: /* V9 done/retry */
! 3127: {
! 3128: switch (rd) {
! 3129: case 0:
! 3130: if (!supervisor(dc))
! 3131: goto priv_insn;
! 3132: dc->npc = DYNAMIC_PC;
! 3133: dc->pc = DYNAMIC_PC;
! 3134: gen_op_done();
! 3135: goto jmp_insn;
! 3136: case 1:
! 3137: if (!supervisor(dc))
! 3138: goto priv_insn;
! 3139: dc->npc = DYNAMIC_PC;
! 3140: dc->pc = DYNAMIC_PC;
! 3141: gen_op_retry();
! 3142: goto jmp_insn;
! 3143: default:
! 3144: goto illegal_insn;
! 3145: }
! 3146: }
! 3147: break;
! 3148: #endif
! 3149: default:
! 3150: goto illegal_insn;
! 3151: }
! 3152: }
! 3153: break;
! 3154: }
! 3155: break;
! 3156: case 3: /* load/store instructions */
! 3157: {
! 3158: unsigned int xop = GET_FIELD(insn, 7, 12);
! 3159: rs1 = GET_FIELD(insn, 13, 17);
! 3160: save_state(dc);
! 3161: gen_movl_reg_T0(rs1);
! 3162: if (xop == 0x3c || xop == 0x3e)
! 3163: {
! 3164: rs2 = GET_FIELD(insn, 27, 31);
! 3165: gen_movl_reg_T1(rs2);
1.1 root 3166: }
1.1.1.5 ! root 3167: else if (IS_IMM) { /* immediate */
! 3168: rs2 = GET_FIELDs(insn, 19, 31);
1.1 root 3169: #if defined(OPTIM)
1.1.1.5 ! root 3170: if (rs2 != 0) {
1.1 root 3171: #endif
1.1.1.5 ! root 3172: gen_movl_simm_T1(rs2);
! 3173: gen_op_add_T1_T0();
1.1 root 3174: #if defined(OPTIM)
1.1.1.5 ! root 3175: }
1.1 root 3176: #endif
1.1.1.5 ! root 3177: } else { /* register */
! 3178: rs2 = GET_FIELD(insn, 27, 31);
1.1 root 3179: #if defined(OPTIM)
1.1.1.5 ! root 3180: if (rs2 != 0) {
1.1 root 3181: #endif
1.1.1.5 ! root 3182: gen_movl_reg_T1(rs2);
! 3183: gen_op_add_T1_T0();
1.1 root 3184: #if defined(OPTIM)
1.1.1.5 ! root 3185: }
! 3186: #endif
! 3187: }
! 3188: if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
! 3189: (xop > 0x17 && xop <= 0x1d ) ||
! 3190: (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
! 3191: switch (xop) {
! 3192: case 0x0: /* load word */
! 3193: gen_op_check_align_T0_3();
! 3194: #ifndef TARGET_SPARC64
! 3195: gen_op_ldst(ld);
! 3196: #else
! 3197: gen_op_ldst(lduw);
1.1 root 3198: #endif
1.1.1.5 ! root 3199: break;
! 3200: case 0x1: /* load unsigned byte */
! 3201: gen_op_ldst(ldub);
! 3202: break;
! 3203: case 0x2: /* load unsigned halfword */
! 3204: gen_op_check_align_T0_1();
! 3205: gen_op_ldst(lduh);
! 3206: break;
! 3207: case 0x3: /* load double word */
! 3208: if (rd & 1)
! 3209: goto illegal_insn;
! 3210: gen_op_check_align_T0_7();
! 3211: gen_op_ldst(ldd);
! 3212: gen_movl_T0_reg(rd + 1);
! 3213: break;
! 3214: case 0x9: /* load signed byte */
! 3215: gen_op_ldst(ldsb);
! 3216: break;
! 3217: case 0xa: /* load signed halfword */
! 3218: gen_op_check_align_T0_1();
! 3219: gen_op_ldst(ldsh);
! 3220: break;
! 3221: case 0xd: /* ldstub -- XXX: should be atomically */
! 3222: gen_op_ldst(ldstub);
! 3223: break;
! 3224: case 0x0f: /* swap register with memory. Also atomically */
! 3225: gen_op_check_align_T0_3();
! 3226: gen_movl_reg_T1(rd);
! 3227: gen_op_ldst(swap);
! 3228: break;
1.1 root 3229: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1.1.1.5 ! root 3230: case 0x10: /* load word alternate */
1.1 root 3231: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3232: if (IS_IMM)
! 3233: goto illegal_insn;
! 3234: if (!supervisor(dc))
! 3235: goto priv_insn;
1.1 root 3236: #endif
1.1.1.5 ! root 3237: gen_op_check_align_T0_3();
! 3238: gen_ld_asi(insn, 4, 0);
! 3239: break;
! 3240: case 0x11: /* load unsigned byte alternate */
1.1 root 3241: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3242: if (IS_IMM)
! 3243: goto illegal_insn;
! 3244: if (!supervisor(dc))
! 3245: goto priv_insn;
1.1 root 3246: #endif
1.1.1.5 ! root 3247: gen_ld_asi(insn, 1, 0);
! 3248: break;
! 3249: case 0x12: /* load unsigned halfword alternate */
1.1 root 3250: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3251: if (IS_IMM)
! 3252: goto illegal_insn;
! 3253: if (!supervisor(dc))
! 3254: goto priv_insn;
1.1 root 3255: #endif
1.1.1.5 ! root 3256: gen_op_check_align_T0_1();
! 3257: gen_ld_asi(insn, 2, 0);
! 3258: break;
! 3259: case 0x13: /* load double word alternate */
1.1 root 3260: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3261: if (IS_IMM)
! 3262: goto illegal_insn;
! 3263: if (!supervisor(dc))
! 3264: goto priv_insn;
1.1 root 3265: #endif
1.1.1.5 ! root 3266: if (rd & 1)
! 3267: goto illegal_insn;
! 3268: gen_op_check_align_T0_7();
! 3269: gen_ldda_asi(insn);
! 3270: gen_movl_T0_reg(rd + 1);
! 3271: break;
! 3272: case 0x19: /* load signed byte alternate */
1.1 root 3273: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3274: if (IS_IMM)
! 3275: goto illegal_insn;
! 3276: if (!supervisor(dc))
! 3277: goto priv_insn;
1.1 root 3278: #endif
1.1.1.5 ! root 3279: gen_ld_asi(insn, 1, 1);
! 3280: break;
! 3281: case 0x1a: /* load signed halfword alternate */
1.1 root 3282: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3283: if (IS_IMM)
! 3284: goto illegal_insn;
! 3285: if (!supervisor(dc))
! 3286: goto priv_insn;
1.1 root 3287: #endif
1.1.1.5 ! root 3288: gen_op_check_align_T0_1();
! 3289: gen_ld_asi(insn, 2, 1);
! 3290: break;
! 3291: case 0x1d: /* ldstuba -- XXX: should be atomically */
1.1 root 3292: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3293: if (IS_IMM)
! 3294: goto illegal_insn;
! 3295: if (!supervisor(dc))
! 3296: goto priv_insn;
1.1 root 3297: #endif
1.1.1.5 ! root 3298: gen_ldstub_asi(insn);
! 3299: break;
! 3300: case 0x1f: /* swap reg with alt. memory. Also atomically */
1.1 root 3301: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3302: if (IS_IMM)
! 3303: goto illegal_insn;
! 3304: if (!supervisor(dc))
! 3305: goto priv_insn;
1.1 root 3306: #endif
1.1.1.5 ! root 3307: gen_op_check_align_T0_3();
! 3308: gen_movl_reg_T1(rd);
! 3309: gen_swap_asi(insn);
! 3310: break;
1.1 root 3311:
3312: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3313: case 0x30: /* ldc */
! 3314: case 0x31: /* ldcsr */
! 3315: case 0x33: /* lddc */
! 3316: goto ncp_insn;
1.1 root 3317: #endif
3318: #endif
3319: #ifdef TARGET_SPARC64
1.1.1.5 ! root 3320: case 0x08: /* V9 ldsw */
! 3321: gen_op_check_align_T0_3();
! 3322: gen_op_ldst(ldsw);
! 3323: break;
! 3324: case 0x0b: /* V9 ldx */
! 3325: gen_op_check_align_T0_7();
! 3326: gen_op_ldst(ldx);
! 3327: break;
! 3328: case 0x18: /* V9 ldswa */
! 3329: gen_op_check_align_T0_3();
! 3330: gen_ld_asi(insn, 4, 1);
! 3331: break;
! 3332: case 0x1b: /* V9 ldxa */
! 3333: gen_op_check_align_T0_7();
! 3334: gen_ld_asi(insn, 8, 0);
! 3335: break;
! 3336: case 0x2d: /* V9 prefetch, no effect */
! 3337: goto skip_move;
! 3338: case 0x30: /* V9 ldfa */
! 3339: gen_op_check_align_T0_3();
! 3340: gen_ldf_asi(insn, 4, rd);
! 3341: goto skip_move;
! 3342: case 0x33: /* V9 lddfa */
! 3343: gen_op_check_align_T0_3();
! 3344: gen_ldf_asi(insn, 8, DFPREG(rd));
! 3345: goto skip_move;
! 3346: case 0x3d: /* V9 prefetcha, no effect */
! 3347: goto skip_move;
! 3348: case 0x32: /* V9 ldqfa */
! 3349: #if defined(CONFIG_USER_ONLY)
! 3350: gen_op_check_align_T0_3();
! 3351: gen_ldf_asi(insn, 16, QFPREG(rd));
! 3352: goto skip_move;
! 3353: #else
! 3354: goto nfpu_insn;
! 3355: #endif
! 3356: #endif
! 3357: default:
! 3358: goto illegal_insn;
! 3359: }
! 3360: gen_movl_T1_reg(rd);
1.1 root 3361: #ifdef TARGET_SPARC64
1.1.1.5 ! root 3362: skip_move: ;
1.1 root 3363: #endif
1.1.1.5 ! root 3364: } else if (xop >= 0x20 && xop < 0x24) {
1.1.1.3 root 3365: if (gen_trap_ifnofpu(dc))
3366: goto jmp_insn;
1.1.1.5 ! root 3367: switch (xop) {
! 3368: case 0x20: /* load fpreg */
! 3369: gen_op_check_align_T0_3();
! 3370: gen_op_ldst(ldf);
! 3371: gen_op_store_FT0_fpr(rd);
! 3372: break;
! 3373: case 0x21: /* load fsr */
! 3374: gen_op_check_align_T0_3();
! 3375: gen_op_ldst(ldf);
! 3376: gen_op_ldfsr();
! 3377: break;
! 3378: case 0x22: /* load quad fpreg */
! 3379: #if defined(CONFIG_USER_ONLY)
! 3380: gen_op_check_align_T0_7();
! 3381: gen_op_ldst(ldqf);
! 3382: gen_op_store_QT0_fpr(QFPREG(rd));
! 3383: break;
! 3384: #else
! 3385: goto nfpu_insn;
! 3386: #endif
! 3387: case 0x23: /* load double fpreg */
! 3388: gen_op_check_align_T0_7();
! 3389: gen_op_ldst(lddf);
! 3390: gen_op_store_DT0_fpr(DFPREG(rd));
! 3391: break;
! 3392: default:
! 3393: goto illegal_insn;
! 3394: }
! 3395: } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || \
! 3396: xop == 0xe || xop == 0x1e) {
! 3397: gen_movl_reg_T1(rd);
! 3398: switch (xop) {
! 3399: case 0x4:
! 3400: gen_op_check_align_T0_3();
! 3401: gen_op_ldst(st);
! 3402: break;
! 3403: case 0x5:
! 3404: gen_op_ldst(stb);
! 3405: break;
! 3406: case 0x6:
! 3407: gen_op_check_align_T0_1();
! 3408: gen_op_ldst(sth);
! 3409: break;
! 3410: case 0x7:
! 3411: if (rd & 1)
! 3412: goto illegal_insn;
! 3413: gen_op_check_align_T0_7();
1.1 root 3414: flush_T2(dc);
1.1.1.5 ! root 3415: gen_movl_reg_T2(rd + 1);
! 3416: gen_op_ldst(std);
! 3417: break;
1.1 root 3418: #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1.1.1.5 ! root 3419: case 0x14:
1.1 root 3420: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3421: if (IS_IMM)
! 3422: goto illegal_insn;
! 3423: if (!supervisor(dc))
! 3424: goto priv_insn;
1.1 root 3425: #endif
1.1.1.5 ! root 3426: gen_op_check_align_T0_3();
! 3427: gen_st_asi(insn, 4);
1.1 root 3428: break;
1.1.1.5 ! root 3429: case 0x15:
1.1 root 3430: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3431: if (IS_IMM)
! 3432: goto illegal_insn;
! 3433: if (!supervisor(dc))
! 3434: goto priv_insn;
1.1 root 3435: #endif
1.1.1.5 ! root 3436: gen_st_asi(insn, 1);
1.1 root 3437: break;
1.1.1.5 ! root 3438: case 0x16:
1.1 root 3439: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3440: if (IS_IMM)
! 3441: goto illegal_insn;
! 3442: if (!supervisor(dc))
! 3443: goto priv_insn;
1.1 root 3444: #endif
1.1.1.5 ! root 3445: gen_op_check_align_T0_1();
! 3446: gen_st_asi(insn, 2);
1.1 root 3447: break;
1.1.1.5 ! root 3448: case 0x17:
1.1 root 3449: #ifndef TARGET_SPARC64
1.1.1.5 ! root 3450: if (IS_IMM)
! 3451: goto illegal_insn;
! 3452: if (!supervisor(dc))
! 3453: goto priv_insn;
1.1 root 3454: #endif
1.1.1.5 ! root 3455: if (rd & 1)
! 3456: goto illegal_insn;
! 3457: gen_op_check_align_T0_7();
1.1 root 3458: flush_T2(dc);
1.1.1.5 ! root 3459: gen_movl_reg_T2(rd + 1);
! 3460: gen_stda_asi(insn);
1.1 root 3461: break;
3462: #endif
3463: #ifdef TARGET_SPARC64
1.1.1.5 ! root 3464: case 0x0e: /* V9 stx */
! 3465: gen_op_check_align_T0_7();
! 3466: gen_op_ldst(stx);
! 3467: break;
! 3468: case 0x1e: /* V9 stxa */
! 3469: gen_op_check_align_T0_7();
! 3470: gen_st_asi(insn, 8);
! 3471: break;
! 3472: #endif
! 3473: default:
! 3474: goto illegal_insn;
! 3475: }
! 3476: } else if (xop > 0x23 && xop < 0x28) {
1.1.1.3 root 3477: if (gen_trap_ifnofpu(dc))
3478: goto jmp_insn;
1.1.1.5 ! root 3479: switch (xop) {
! 3480: case 0x24:
! 3481: gen_op_check_align_T0_3();
! 3482: gen_op_load_fpr_FT0(rd);
! 3483: gen_op_ldst(stf);
! 3484: break;
! 3485: case 0x25: /* stfsr, V9 stxfsr */
! 3486: #ifdef CONFIG_USER_ONLY
! 3487: gen_op_check_align_T0_3();
! 3488: #endif
! 3489: gen_op_stfsr();
! 3490: gen_op_ldst(stf);
! 3491: break;
! 3492: case 0x26:
! 3493: #ifdef TARGET_SPARC64
! 3494: #if defined(CONFIG_USER_ONLY)
! 3495: /* V9 stqf, store quad fpreg */
! 3496: gen_op_check_align_T0_7();
! 3497: gen_op_load_fpr_QT0(QFPREG(rd));
! 3498: gen_op_ldst(stqf);
! 3499: break;
! 3500: #else
! 3501: goto nfpu_insn;
! 3502: #endif
! 3503: #else /* !TARGET_SPARC64 */
! 3504: /* stdfq, store floating point queue */
! 3505: #if defined(CONFIG_USER_ONLY)
! 3506: goto illegal_insn;
! 3507: #else
! 3508: if (!supervisor(dc))
! 3509: goto priv_insn;
! 3510: if (gen_trap_ifnofpu(dc))
! 3511: goto jmp_insn;
! 3512: goto nfq_insn;
! 3513: #endif
! 3514: #endif
! 3515: case 0x27:
! 3516: gen_op_check_align_T0_7();
! 3517: gen_op_load_fpr_DT0(DFPREG(rd));
! 3518: gen_op_ldst(stdf);
! 3519: break;
! 3520: default:
! 3521: goto illegal_insn;
! 3522: }
! 3523: } else if (xop > 0x33 && xop < 0x3f) {
! 3524: switch (xop) {
! 3525: #ifdef TARGET_SPARC64
! 3526: case 0x34: /* V9 stfa */
! 3527: gen_op_check_align_T0_3();
1.1 root 3528: gen_op_load_fpr_FT0(rd);
1.1.1.5 ! root 3529: gen_stf_asi(insn, 4, rd);
! 3530: break;
! 3531: case 0x36: /* V9 stqfa */
! 3532: #if defined(CONFIG_USER_ONLY)
! 3533: gen_op_check_align_T0_7();
! 3534: gen_op_load_fpr_QT0(QFPREG(rd));
! 3535: gen_stf_asi(insn, 16, QFPREG(rd));
! 3536: break;
! 3537: #else
! 3538: goto nfpu_insn;
! 3539: #endif
! 3540: case 0x37: /* V9 stdfa */
! 3541: gen_op_check_align_T0_3();
1.1 root 3542: gen_op_load_fpr_DT0(DFPREG(rd));
1.1.1.5 ! root 3543: gen_stf_asi(insn, 8, DFPREG(rd));
! 3544: break;
! 3545: case 0x3c: /* V9 casa */
! 3546: gen_op_check_align_T0_3();
! 3547: flush_T2(dc);
! 3548: gen_movl_reg_T2(rd);
! 3549: gen_cas_asi(insn);
! 3550: gen_movl_T1_reg(rd);
! 3551: break;
! 3552: case 0x3e: /* V9 casxa */
! 3553: gen_op_check_align_T0_7();
! 3554: flush_T2(dc);
! 3555: gen_movl_reg_T2(rd);
! 3556: gen_casx_asi(insn);
! 3557: gen_movl_T1_reg(rd);
! 3558: break;
1.1 root 3559: #else
1.1.1.5 ! root 3560: case 0x34: /* stc */
! 3561: case 0x35: /* stcsr */
! 3562: case 0x36: /* stdcq */
! 3563: case 0x37: /* stdc */
! 3564: goto ncp_insn;
1.1 root 3565: #endif
1.1.1.5 ! root 3566: default:
! 3567: goto illegal_insn;
! 3568: }
1.1 root 3569: }
1.1.1.5 ! root 3570: else
! 3571: goto illegal_insn;
! 3572: }
! 3573: break;
1.1 root 3574: }
3575: /* default case for non jump instructions */
3576: if (dc->npc == DYNAMIC_PC) {
1.1.1.5 ! root 3577: dc->pc = DYNAMIC_PC;
! 3578: gen_op_next_insn();
1.1 root 3579: } else if (dc->npc == JUMP_PC) {
3580: /* we can do a static jump */
1.1.1.5 ! root 3581: gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1]);
1.1 root 3582: dc->is_br = 1;
3583: } else {
1.1.1.5 ! root 3584: dc->pc = dc->npc;
! 3585: dc->npc = dc->npc + 4;
1.1 root 3586: }
3587: jmp_insn:
3588: return;
3589: illegal_insn:
3590: save_state(dc);
3591: gen_op_exception(TT_ILL_INSN);
3592: dc->is_br = 1;
3593: return;
3594: #if !defined(CONFIG_USER_ONLY)
3595: priv_insn:
3596: save_state(dc);
3597: gen_op_exception(TT_PRIV_INSN);
3598: dc->is_br = 1;
3599: return;
3600: nfpu_insn:
3601: save_state(dc);
3602: gen_op_fpexception_im(FSR_FTT_UNIMPFPOP);
3603: dc->is_br = 1;
1.1.1.5 ! root 3604: return;
! 3605: #ifndef TARGET_SPARC64
! 3606: nfq_insn:
! 3607: save_state(dc);
! 3608: gen_op_fpexception_im(FSR_FTT_SEQ_ERROR);
! 3609: dc->is_br = 1;
! 3610: return;
! 3611: #endif
! 3612: #endif
! 3613: #ifndef TARGET_SPARC64
! 3614: ncp_insn:
! 3615: save_state(dc);
! 3616: gen_op_exception(TT_NCP_INSN);
! 3617: dc->is_br = 1;
! 3618: return;
! 3619: #endif
1.1 root 3620: }
3621:
3622: static inline int gen_intermediate_code_internal(TranslationBlock * tb,
1.1.1.5 ! root 3623: int spc, CPUSPARCState *env)
1.1 root 3624: {
3625: target_ulong pc_start, last_pc;
3626: uint16_t *gen_opc_end;
3627: DisasContext dc1, *dc = &dc1;
3628: int j, lj = -1;
3629:
3630: memset(dc, 0, sizeof(DisasContext));
3631: dc->tb = tb;
3632: pc_start = tb->pc;
3633: dc->pc = pc_start;
3634: last_pc = dc->pc;
3635: dc->npc = (target_ulong) tb->cs_base;
1.1.1.5 ! root 3636: dc->mem_idx = cpu_mmu_index(env);
! 3637: dc->fpu_enabled = cpu_fpu_enabled(env);
1.1 root 3638: gen_opc_ptr = gen_opc_buf;
3639: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3640: gen_opparam_ptr = gen_opparam_buf;
3641: nb_gen_labels = 0;
3642:
3643: do {
3644: if (env->nb_breakpoints > 0) {
3645: for(j = 0; j < env->nb_breakpoints; j++) {
3646: if (env->breakpoints[j] == dc->pc) {
1.1.1.5 ! root 3647: if (dc->pc != pc_start)
! 3648: save_state(dc);
1.1 root 3649: gen_op_debug();
1.1.1.5 ! root 3650: gen_op_movl_T0_0();
! 3651: gen_op_exit_tb();
! 3652: dc->is_br = 1;
1.1 root 3653: goto exit_gen_loop;
3654: }
3655: }
3656: }
3657: if (spc) {
3658: if (loglevel > 0)
3659: fprintf(logfile, "Search PC...\n");
3660: j = gen_opc_ptr - gen_opc_buf;
3661: if (lj < j) {
3662: lj++;
3663: while (lj < j)
3664: gen_opc_instr_start[lj++] = 0;
3665: gen_opc_pc[lj] = dc->pc;
3666: gen_opc_npc[lj] = dc->npc;
3667: gen_opc_instr_start[lj] = 1;
3668: }
3669: }
1.1.1.5 ! root 3670: last_pc = dc->pc;
! 3671: disas_sparc_insn(dc);
1.1 root 3672:
1.1.1.5 ! root 3673: if (dc->is_br)
! 3674: break;
! 3675: /* if the next PC is different, we abort now */
! 3676: if (dc->pc != (last_pc + 4))
! 3677: break;
1.1 root 3678: /* if we reach a page boundary, we stop generation so that the
3679: PC of a TT_TFAULT exception is always in the right page */
3680: if ((dc->pc & (TARGET_PAGE_SIZE - 1)) == 0)
3681: break;
3682: /* if single step mode, we generate only one instruction and
3683: generate an exception */
3684: if (env->singlestep_enabled) {
3685: gen_jmp_im(dc->pc);
3686: gen_op_movl_T0_0();
3687: gen_op_exit_tb();
3688: break;
3689: }
3690: } while ((gen_opc_ptr < gen_opc_end) &&
1.1.1.5 ! root 3691: (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1.1 root 3692:
3693: exit_gen_loop:
3694: if (!dc->is_br) {
1.1.1.5 ! root 3695: if (dc->pc != DYNAMIC_PC &&
1.1 root 3696: (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) {
3697: /* static PC and NPC: we can use direct chaining */
1.1.1.5 ! root 3698: gen_branch(dc, dc->pc, dc->npc);
1.1 root 3699: } else {
3700: if (dc->pc != DYNAMIC_PC)
3701: gen_jmp_im(dc->pc);
3702: save_npc(dc);
3703: gen_op_movl_T0_0();
3704: gen_op_exit_tb();
3705: }
3706: }
3707: *gen_opc_ptr = INDEX_op_end;
3708: if (spc) {
3709: j = gen_opc_ptr - gen_opc_buf;
3710: lj++;
3711: while (lj <= j)
3712: gen_opc_instr_start[lj++] = 0;
3713: #if 0
3714: if (loglevel > 0) {
3715: page_dump(logfile);
3716: }
3717: #endif
3718: gen_opc_jump_pc[0] = dc->jump_pc[0];
3719: gen_opc_jump_pc[1] = dc->jump_pc[1];
3720: } else {
3721: tb->size = last_pc + 4 - pc_start;
3722: }
3723: #ifdef DEBUG_DISAS
3724: if (loglevel & CPU_LOG_TB_IN_ASM) {
1.1.1.5 ! root 3725: fprintf(logfile, "--------------\n");
! 3726: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
! 3727: target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
! 3728: fprintf(logfile, "\n");
1.1 root 3729: if (loglevel & CPU_LOG_TB_OP) {
3730: fprintf(logfile, "OP:\n");
3731: dump_ops(gen_opc_buf, gen_opparam_buf);
3732: fprintf(logfile, "\n");
3733: }
3734: }
3735: #endif
3736: return 0;
3737: }
3738:
3739: int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
3740: {
3741: return gen_intermediate_code_internal(tb, 0, env);
3742: }
3743:
3744: int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
3745: {
3746: return gen_intermediate_code_internal(tb, 1, env);
3747: }
3748:
3749: extern int ram_size;
3750:
3751: void cpu_reset(CPUSPARCState *env)
3752: {
3753: tlb_flush(env, 1);
3754: env->cwp = 0;
3755: env->wim = 1;
3756: env->regwptr = env->regbase + (env->cwp * 16);
3757: #if defined(CONFIG_USER_ONLY)
3758: env->user_mode_only = 1;
1.1.1.3 root 3759: #ifdef TARGET_SPARC64
1.1.1.5 ! root 3760: env->cleanwin = NWINDOWS - 2;
! 3761: env->cansave = NWINDOWS - 2;
! 3762: env->pstate = PS_RMO | PS_PEF | PS_IE;
! 3763: env->asi = 0x82; // Primary no-fault
1.1.1.3 root 3764: #endif
1.1 root 3765: #else
1.1.1.5 ! root 3766: env->psret = 0;
1.1 root 3767: env->psrs = 1;
3768: env->psrps = 1;
3769: #ifdef TARGET_SPARC64
3770: env->pstate = PS_PRIV;
1.1.1.5 ! root 3771: env->hpstate = HS_PRIV;
1.1 root 3772: env->pc = 0x1fff0000000ULL;
3773: #else
1.1.1.5 ! root 3774: env->pc = 0;
! 3775: env->mmuregs[0] &= ~(MMU_E | MMU_NF);
! 3776: env->mmuregs[0] |= env->mmu_bm;
1.1 root 3777: #endif
3778: env->npc = env->pc + 4;
3779: #endif
3780: }
3781:
1.1.1.5 ! root 3782: CPUSPARCState *cpu_sparc_init(const char *cpu_model)
1.1 root 3783: {
3784: CPUSPARCState *env;
1.1.1.5 ! root 3785: const sparc_def_t *def;
! 3786:
! 3787: def = cpu_sparc_find_by_name(cpu_model);
! 3788: if (!def)
! 3789: return NULL;
1.1 root 3790:
1.1.1.2 root 3791: env = qemu_mallocz(sizeof(CPUSPARCState));
3792: if (!env)
1.1.1.5 ! root 3793: return NULL;
1.1.1.2 root 3794: cpu_exec_init(env);
1.1.1.5 ! root 3795: env->cpu_model_str = cpu_model;
! 3796: env->version = def->iu_version;
! 3797: env->fsr = def->fpu_version;
! 3798: #if !defined(TARGET_SPARC64)
! 3799: env->mmu_bm = def->mmu_bm;
! 3800: env->mmuregs[0] |= def->mmu_version;
! 3801: cpu_sparc_set_id(env, 0);
! 3802: #endif
1.1 root 3803: cpu_reset(env);
1.1.1.5 ! root 3804:
! 3805: return env;
! 3806: }
! 3807:
! 3808: void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
! 3809: {
! 3810: #if !defined(TARGET_SPARC64)
! 3811: env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
! 3812: #endif
! 3813: }
! 3814:
! 3815: static const sparc_def_t sparc_defs[] = {
! 3816: #ifdef TARGET_SPARC64
! 3817: {
! 3818: .name = "Fujitsu Sparc64",
! 3819: .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)
! 3820: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3821: .fpu_version = 0x00000000,
! 3822: .mmu_version = 0,
! 3823: },
! 3824: {
! 3825: .name = "Fujitsu Sparc64 III",
! 3826: .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)
! 3827: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3828: .fpu_version = 0x00000000,
! 3829: .mmu_version = 0,
! 3830: },
! 3831: {
! 3832: .name = "Fujitsu Sparc64 IV",
! 3833: .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)
! 3834: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3835: .fpu_version = 0x00000000,
! 3836: .mmu_version = 0,
! 3837: },
! 3838: {
! 3839: .name = "Fujitsu Sparc64 V",
! 3840: .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)
! 3841: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3842: .fpu_version = 0x00000000,
! 3843: .mmu_version = 0,
! 3844: },
! 3845: {
! 3846: .name = "TI UltraSparc I",
! 3847: .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
! 3848: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3849: .fpu_version = 0x00000000,
! 3850: .mmu_version = 0,
! 3851: },
! 3852: {
! 3853: .name = "TI UltraSparc II",
! 3854: .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)
! 3855: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3856: .fpu_version = 0x00000000,
! 3857: .mmu_version = 0,
! 3858: },
! 3859: {
! 3860: .name = "TI UltraSparc IIi",
! 3861: .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)
! 3862: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3863: .fpu_version = 0x00000000,
! 3864: .mmu_version = 0,
! 3865: },
! 3866: {
! 3867: .name = "TI UltraSparc IIe",
! 3868: .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)
! 3869: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3870: .fpu_version = 0x00000000,
! 3871: .mmu_version = 0,
! 3872: },
! 3873: {
! 3874: .name = "Sun UltraSparc III",
! 3875: .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)
! 3876: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3877: .fpu_version = 0x00000000,
! 3878: .mmu_version = 0,
! 3879: },
! 3880: {
! 3881: .name = "Sun UltraSparc III Cu",
! 3882: .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)
! 3883: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3884: .fpu_version = 0x00000000,
! 3885: .mmu_version = 0,
! 3886: },
! 3887: {
! 3888: .name = "Sun UltraSparc IIIi",
! 3889: .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)
! 3890: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3891: .fpu_version = 0x00000000,
! 3892: .mmu_version = 0,
! 3893: },
! 3894: {
! 3895: .name = "Sun UltraSparc IV",
! 3896: .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)
! 3897: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3898: .fpu_version = 0x00000000,
! 3899: .mmu_version = 0,
! 3900: },
! 3901: {
! 3902: .name = "Sun UltraSparc IV+",
! 3903: .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)
! 3904: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3905: .fpu_version = 0x00000000,
! 3906: .mmu_version = 0,
! 3907: },
! 3908: {
! 3909: .name = "Sun UltraSparc IIIi+",
! 3910: .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)
! 3911: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3912: .fpu_version = 0x00000000,
! 3913: .mmu_version = 0,
! 3914: },
! 3915: {
! 3916: .name = "NEC UltraSparc I",
! 3917: .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)
! 3918: | (MAXTL << 8) | (NWINDOWS - 1)),
! 3919: .fpu_version = 0x00000000,
! 3920: .mmu_version = 0,
! 3921: },
! 3922: #else
! 3923: {
! 3924: .name = "Fujitsu MB86900",
! 3925: .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
! 3926: .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
! 3927: .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
! 3928: .mmu_bm = 0x00004000,
! 3929: },
! 3930: {
! 3931: .name = "Fujitsu MB86904",
! 3932: .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
! 3933: .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
! 3934: .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
! 3935: .mmu_bm = 0x00004000,
! 3936: },
! 3937: {
! 3938: .name = "Fujitsu MB86907",
! 3939: .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
! 3940: .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
! 3941: .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
! 3942: .mmu_bm = 0x00004000,
! 3943: },
! 3944: {
! 3945: .name = "LSI L64811",
! 3946: .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
! 3947: .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
! 3948: .mmu_version = 0x10 << 24,
! 3949: .mmu_bm = 0x00004000,
! 3950: },
! 3951: {
! 3952: .name = "Cypress CY7C601",
! 3953: .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
! 3954: .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
! 3955: .mmu_version = 0x10 << 24,
! 3956: .mmu_bm = 0x00004000,
! 3957: },
! 3958: {
! 3959: .name = "Cypress CY7C611",
! 3960: .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
! 3961: .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
! 3962: .mmu_version = 0x10 << 24,
! 3963: .mmu_bm = 0x00004000,
! 3964: },
! 3965: {
! 3966: .name = "TI SuperSparc II",
! 3967: .iu_version = 0x40000000,
! 3968: .fpu_version = 0 << 17,
! 3969: .mmu_version = 0x04000000,
! 3970: .mmu_bm = 0x00002000,
! 3971: },
! 3972: {
! 3973: .name = "TI MicroSparc I",
! 3974: .iu_version = 0x41000000,
! 3975: .fpu_version = 4 << 17,
! 3976: .mmu_version = 0x41000000,
! 3977: .mmu_bm = 0x00004000,
! 3978: },
! 3979: {
! 3980: .name = "TI MicroSparc II",
! 3981: .iu_version = 0x42000000,
! 3982: .fpu_version = 4 << 17,
! 3983: .mmu_version = 0x02000000,
! 3984: .mmu_bm = 0x00004000,
! 3985: },
! 3986: {
! 3987: .name = "TI MicroSparc IIep",
! 3988: .iu_version = 0x42000000,
! 3989: .fpu_version = 4 << 17,
! 3990: .mmu_version = 0x04000000,
! 3991: .mmu_bm = 0x00004000,
! 3992: },
! 3993: {
! 3994: .name = "TI SuperSparc 51",
! 3995: .iu_version = 0x43000000,
! 3996: .fpu_version = 0 << 17,
! 3997: .mmu_version = 0x04000000,
! 3998: .mmu_bm = 0x00002000,
! 3999: },
! 4000: {
! 4001: .name = "TI SuperSparc 61",
! 4002: .iu_version = 0x44000000,
! 4003: .fpu_version = 0 << 17,
! 4004: .mmu_version = 0x04000000,
! 4005: .mmu_bm = 0x00002000,
! 4006: },
! 4007: {
! 4008: .name = "Ross RT625",
! 4009: .iu_version = 0x1e000000,
! 4010: .fpu_version = 1 << 17,
! 4011: .mmu_version = 0x1e000000,
! 4012: .mmu_bm = 0x00004000,
! 4013: },
! 4014: {
! 4015: .name = "Ross RT620",
! 4016: .iu_version = 0x1f000000,
! 4017: .fpu_version = 1 << 17,
! 4018: .mmu_version = 0x1f000000,
! 4019: .mmu_bm = 0x00004000,
! 4020: },
! 4021: {
! 4022: .name = "BIT B5010",
! 4023: .iu_version = 0x20000000,
! 4024: .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
! 4025: .mmu_version = 0x20000000,
! 4026: .mmu_bm = 0x00004000,
! 4027: },
! 4028: {
! 4029: .name = "Matsushita MN10501",
! 4030: .iu_version = 0x50000000,
! 4031: .fpu_version = 0 << 17,
! 4032: .mmu_version = 0x50000000,
! 4033: .mmu_bm = 0x00004000,
! 4034: },
! 4035: {
! 4036: .name = "Weitek W8601",
! 4037: .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
! 4038: .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
! 4039: .mmu_version = 0x10 << 24,
! 4040: .mmu_bm = 0x00004000,
! 4041: },
! 4042: {
! 4043: .name = "LEON2",
! 4044: .iu_version = 0xf2000000,
! 4045: .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
! 4046: .mmu_version = 0xf2000000,
! 4047: .mmu_bm = 0x00004000,
! 4048: },
! 4049: {
! 4050: .name = "LEON3",
! 4051: .iu_version = 0xf3000000,
! 4052: .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
! 4053: .mmu_version = 0xf3000000,
! 4054: .mmu_bm = 0x00004000,
! 4055: },
! 4056: #endif
! 4057: };
! 4058:
! 4059: static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name)
! 4060: {
! 4061: unsigned int i;
! 4062:
! 4063: for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
! 4064: if (strcasecmp(name, sparc_defs[i].name) == 0) {
! 4065: return &sparc_defs[i];
! 4066: }
! 4067: }
! 4068: return NULL;
! 4069: }
! 4070:
! 4071: void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
! 4072: {
! 4073: unsigned int i;
! 4074:
! 4075: for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
! 4076: (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x\n",
! 4077: sparc_defs[i].name,
! 4078: sparc_defs[i].iu_version,
! 4079: sparc_defs[i].fpu_version,
! 4080: sparc_defs[i].mmu_version);
! 4081: }
1.1 root 4082: }
4083:
4084: #define GET_FLAG(a,b) ((env->psr & a)?b:'-')
4085:
1.1.1.5 ! root 4086: void cpu_dump_state(CPUState *env, FILE *f,
1.1 root 4087: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
4088: int flags)
4089: {
4090: int i, x;
4091:
4092: cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc);
4093: cpu_fprintf(f, "General Registers:\n");
4094: for (i = 0; i < 4; i++)
1.1.1.5 ! root 4095: cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1.1 root 4096: cpu_fprintf(f, "\n");
4097: for (; i < 8; i++)
1.1.1.5 ! root 4098: cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]);
1.1 root 4099: cpu_fprintf(f, "\nCurrent Register Window:\n");
4100: for (x = 0; x < 3; x++) {
1.1.1.5 ! root 4101: for (i = 0; i < 4; i++)
! 4102: cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
! 4103: (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i,
! 4104: env->regwptr[i + x * 8]);
! 4105: cpu_fprintf(f, "\n");
! 4106: for (; i < 8; i++)
! 4107: cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t",
! 4108: (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i,
! 4109: env->regwptr[i + x * 8]);
! 4110: cpu_fprintf(f, "\n");
1.1 root 4111: }
4112: cpu_fprintf(f, "\nFloating Point Registers:\n");
4113: for (i = 0; i < 32; i++) {
4114: if ((i & 3) == 0)
4115: cpu_fprintf(f, "%%f%02d:", i);
4116: cpu_fprintf(f, " %016lf", env->fpr[i]);
4117: if ((i & 3) == 3)
4118: cpu_fprintf(f, "\n");
4119: }
1.1.1.3 root 4120: #ifdef TARGET_SPARC64
1.1.1.5 ! root 4121: cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
! 4122: env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
1.1.1.3 root 4123: cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d cleanwin %d cwp %d\n",
1.1.1.5 ! root 4124: env->cansave, env->canrestore, env->otherwin, env->wstate,
! 4125: env->cleanwin, NWINDOWS - 1 - env->cwp);
1.1.1.3 root 4126: #else
1.1 root 4127: cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
1.1.1.5 ! root 4128: GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
! 4129: GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
! 4130: env->psrs?'S':'-', env->psrps?'P':'-',
! 4131: env->psret?'E':'-', env->wim);
1.1.1.3 root 4132: #endif
1.1 root 4133: cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
4134: }
4135:
4136: #if defined(CONFIG_USER_ONLY)
1.1.1.5 ! root 4137: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 4138: {
4139: return addr;
4140: }
4141:
4142: #else
4143: extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
4144: int *access_index, target_ulong address, int rw,
1.1.1.5 ! root 4145: int mmu_idx);
1.1 root 4146:
1.1.1.5 ! root 4147: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 4148: {
4149: target_phys_addr_t phys_addr;
4150: int prot, access_index;
4151:
4152: if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
1.1.1.3 root 4153: if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
4154: return -1;
1.1.1.5 ! root 4155: if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
! 4156: return -1;
1.1 root 4157: return phys_addr;
4158: }
4159: #endif
4160:
4161: void helper_flush(target_ulong addr)
4162: {
4163: addr &= ~7;
4164: tb_invalidate_page_range(addr, addr + 8);
4165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.