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